Skip to content

Commit

Permalink
use clang-tidy command with task to generate items in problem's view
Browse files Browse the repository at this point in the history
Enable running the `clang-tidy` C/C++ linting present from clang-tidy as a task.
With the new updates, linting can be performed across an entire workspace using user
specified checks and linting rules. The problem markers collected when executing the
task will be recorded and displayed in the `problems-widget`.
The result in the "Problems" view is persistent until you
re-generates the task.

Signed-off-by: Jacques Bouthillier <[email protected]>
  • Loading branch information
lmcbout committed Jul 12, 2019
1 parent b2fbe6e commit 16f1583
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 10 deletions.
44 changes: 40 additions & 4 deletions packages/cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ To get this working, you need to enable clangd's global index using the

## Using the clang-tidy linter

Note: This functionality is available when using clangd 9 and later.
**Note: This functionality is available when using clangd 9 and later.**

You can set the preference 'cpp.clangTidy' to enable the clang-tidy linter included in clangd. When the preference is set, there are two ways to chose which of its built-in checks clang-tidy will use:
You can set the preference 'cpp.clangTidy' to enable the clang-tidy linter included in clangd. When the preference is enabled, there are two ways to choose which of its built-in checks clang-tidy will use:

- using the preferences: 'cpp.clangTidyChecks'
- using the file '.clang-tidy' . The file is located in the same folder of the files or a parent folder.
- using the file '.clang-tidy' . This file is located in the same folder of the files or a parent folder.

Note: using the preference checks will supersede the value found in the .clang-tidy file.
**Note**: When the preference setting for "cpp.clangTidyChecks" is set, the configs will be merged with the configuration found in the ".clang-tidy" file. If you want to drop the configs from ".clang-tidy", you'd need to disable it in "cpp.clangTidyChecks" with **"cpp.clangTidyChecks": "-*"**.

The syntax used to fill the checks can be found at http://clang.llvm.org/extra/clang-tidy/

Expand All @@ -102,6 +102,42 @@ There are two ways to configure clang-tidy's checks: through a Theia preference
- for the .clang-tidy file: Checks: "-*,readability-*"
- Meaning: disable all list-checks and enable all readability-* checks

### Running clang-tidy as a task

To be able to run clang-tidy as a task, you need to install the program.

```bash
UNIX
sudo apt-get install clang-tidy
Note: not all operating system are currently supported with this linter yet.
```

In .theia/tasks.json, add the following:

```json
{
"label": "[Task] clang-tidy",
"type": "shell",
"cwd": "${workspaceFolder}",
"command": "clang-tidy",
"args": [
"*"
],
"options": {},
"problemMatcher": [
"$clangTidyMatcher"
]
}
```

If you want a description for each task field, see [theia/packages/task/src/browser/task-schema-updater.ts]( https://github.com/theia-ide/theia/blob/531aa3bde8dea7f022ea41beaee3aace65ce54de/packages/task/src/browser/task-schema-updater.ts#L62 )

```bash
When there is no compilation database, clang-tidy could run but you may need to be more specific which files to select. One way is to replace the "args" from the "*" to
"**/*.cpp" to only parse files with the "cpp" extension or
"**/*.c" to parse the "c" files extension.
```

## License

- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
Expand Down
11 changes: 8 additions & 3 deletions packages/cpp/src/browser/cpp-task-provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import { TaskResolverRegistry } from '@theia/task/lib/browser/task-contribution'
import { CppBuildConfigurationManager, CppBuildConfiguration } from './cpp-build-configurations';
import { Event } from '@theia/core';
import { expect } from 'chai';
import { TaskConfiguration } from '@theia/task/src/common';
import { TaskConfiguration } from '@theia/task/lib/common';
import { ProcessTaskConfiguration } from '@theia/task/lib/common/process/task-protocol';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser/task-definition-registry';
import { ProblemMatcherRegistry } from '@theia/task/lib/browser/task-problem-matcher-registry';
import { ProblemPatternRegistry } from '@theia/task/lib/browser/task-problem-pattern-registry';

// The object under test.
let taskProvider: CppTaskProvider;
Expand Down Expand Up @@ -67,9 +69,12 @@ class MockCppBuildConfigurationManager implements CppBuildConfigurationManager {
beforeEach(function () {
const container: Container = new Container();
container.bind(CppTaskProvider).toSelf().inSingletonScope();
container.bind(CppBuildConfigurationManager).to(MockCppBuildConfigurationManager);
container.bind(TaskResolverRegistry).toSelf().inSingletonScope();
container.bind(TaskDefinitionRegistry).toSelf().inSingletonScope();
container.bind(CppBuildConfigurationManager).to(MockCppBuildConfigurationManager);
container.bind(ProblemMatcherRegistry).toSelf().inSingletonScope();
container.bind(ProblemPatternRegistry).toSelf().inSingletonScope();

taskProvider = container.get(CppTaskProvider);

// Register a task resolver of type 'shell', on which the cpp build tasks
Expand Down
31 changes: 28 additions & 3 deletions packages/cpp/src/browser/cpp-task-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import parseArgv = require('string-argv');
import { inject, injectable, postConstruct } from 'inversify';
import { ProcessTaskConfiguration } from '@theia/task/lib/common/process/task-protocol';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser';
import { TaskContribution, TaskProvider, TaskProviderRegistry, TaskResolver, TaskResolverRegistry } from '@theia/task/lib/browser/task-contribution';
import { CppBuildConfigurationManager, CppBuildConfiguration } from './cpp-build-configurations';
import { ContributedTaskConfiguration, TaskConfiguration, } from '@theia/task/lib/common/task-protocol';
import { ContributedTaskConfiguration, TaskConfiguration } from '@theia/task/lib/common/task-protocol';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser/task-definition-registry';
import { ProblemMatcherRegistry } from '@theia/task/lib/browser/task-problem-matcher-registry';
import { ProblemPatternRegistry } from '@theia/task/lib/browser/task-problem-pattern-registry';

/**
* Data required to define a C/C++ build task the user could run.
Expand All @@ -38,10 +40,33 @@ export class CppTaskProvider implements TaskContribution, TaskProvider, TaskReso
@inject(TaskResolverRegistry) protected readonly taskResolverRegistry: TaskResolverRegistry;
@inject(TaskDefinitionRegistry) protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;
@inject(CppBuildConfigurationManager) protected readonly cppBuildConfigurationManager: CppBuildConfigurationManager;
@inject(ProblemMatcherRegistry) protected readonly problemMatcherRegistry: ProblemMatcherRegistry;
@inject(ProblemPatternRegistry) protected readonly problemPatternRegistry: ProblemPatternRegistry;

@postConstruct()
protected init(): void {
this.registerTaskDefinition();
this.problemPatternRegistry.register({
'name': 'clangTidyPattern',
'regexp': '^(.+):(\\d+):(\\d+):\\s+(error|warning|info|note):\\s+(.+?)\\s+\\[(.+)\\]$',
'file': 1,
'line': 2,
'character': 3,
'severity': 4,
'message': 5,
'code': 6
});
this.problemMatcherRegistry.register({
'name': 'clangTidyMatcher',
'label': 'Clang-tidy problems',
'owner': 'clang-tidy',
'source': 'clang-tidy-task',
'applyTo': 'alldocuments',
'fileLocation': [
'absolute'
],
'pattern': 'clangTidyPattern'
});
}

registerProviders(registry: TaskProviderRegistry) {
Expand Down Expand Up @@ -77,7 +102,7 @@ export class CppTaskProvider implements TaskContribution, TaskProvider, TaskReso
type: 'shell',
command,
args,
options: { cwd: task.config.directory }
cwd: task.config.directory,
};
return resolver.resolveTask(resolvedTask);
}
Expand Down

0 comments on commit 16f1583

Please sign in to comment.