Skip to content

Commit

Permalink
Handle clang-tidy functionality.
Browse files Browse the repository at this point in the history
Fixes issue #4579
This is a new linter for C/C++.

Signed-off-by: Jacques Bouthillier <[email protected]>
  • Loading branch information
lmcbout committed Mar 15, 2019
1 parent b21023e commit 9ddac67
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Change Log

## v0.5.0
- [cpp] added new clang-tidy and clang-tidy-checks preferences to lint cpp program.
- [plugin] `workspace.openTextDocument` API now respects the contributed `FileSystemProviders`

Breaking changes:
Expand Down
22 changes: 22 additions & 0 deletions packages/cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,28 @@ To get this working, you need to enable clangd's global index using the
"cpp.clangdArgs": "--background-index"
}

## Using the clang-tidy linter

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

You can set the preference 'cpp.clang-tidy' to initiate the linter. When the preference is set, there are two possibilities to pass the checks arguments:

- using the preferences: 'cpp.clang-tidy-checks'
- using the file '.clang-tidy' . The 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.

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

clang-tidy has its own checks and can also run Clang static analyzer checks. Each check has a name and the checks to run can be chosen using the -checks= option, which specifies a comma-separated list of positive and negative (prefixed with -) globs. Positive globs add subsets of checks, negative globs remove them. For example,

- Example for the preferences: "cpp.clang-tidy-checks": "*,-readability-*"
- Meaning: enables all list-checks and disable all readability-* checks

- Example for the .clang-tidy file: Checks: -*,readability-*
- Meaning: disable all list-checks and enable all readability-* checks

## License

- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
4 changes: 3 additions & 1 deletion packages/cpp/src/browser/cpp-language-client-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ export class CppLanguageClientContribution extends BaseLanguageClientContributio
protected getStartParameters(): CppStartParameters {
return {
clangdExecutable: this.cppPreferences['cpp.clangdExecutable'],
clangdArgs: this.cppPreferences['cpp.clangdArgs']
clangdArgs: this.cppPreferences['cpp.clangdArgs'],
clangTidy: this.cppPreferences['cpp.clangTidy'],
clangTidyChecks: this.cppPreferences['cpp.clangTidyChecks']
};
}
}
12 changes: 12 additions & 0 deletions packages/cpp/src/browser/cpp-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ export const cppPreferencesSchema: PreferenceSchema = {
description: 'Specify the arguments to pass to clangd when starting the language server.',
default: '',
type: 'string'
},
'cpp.clangTidy': {
description: 'Enable/disable C/C++ linting.',
default: false,
type: 'boolean'
},
'cpp.clangTidyChecks': {
description: 'Specify comma separated arguments to pass to clang-tidy. Activated only if cpp.clang-tidy is enabled',
default: '',
type: 'string'
}
}
};
Expand All @@ -70,6 +80,8 @@ export class CppConfiguration {
'cpp.experimentalCommands': boolean;
'cpp.clangdExecutable': string;
'cpp.clangdArgs': string;
'cpp.clangTidy': boolean;
'cpp.clangTidyChecks': string;
}

export const CppPreferences = Symbol('CppPreferences');
Expand Down
2 changes: 2 additions & 0 deletions packages/cpp/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ export const CLANGD_EXECUTABLE_DEFAULT = 'clangd';
export interface CppStartParameters {
clangdExecutable: string;
clangdArgs: string;
clangTidy?: boolean;
clangTidyChecks?: string;
}
29 changes: 28 additions & 1 deletion packages/cpp/src/node/cpp-contribution.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (C) 2017 Ericsson and others.
* Copyright (C) 2017-2019 Ericsson and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -42,7 +42,34 @@ export class CppContribution extends BaseLanguageServerContribution {
|| undefined
);

const clangTidy = parameters && parameters.clangTidy;
const clangTidyChecks = parameters && parameters.clangTidyChecks;

if (clangTidy) {
const supportsClangTidy = await this.testSupportsClangTidy(command);
if (supportsClangTidy) {
args.push('-clang-tidy');
if (typeof clangTidyChecks === 'string' && clangTidyChecks.length > 0) {
args.push(`-clang-tidy-checks=${clangTidyChecks}`);
}
}
}
const serverConnection = await this.createProcessStreamConnectionAsync(command, args);
this.forward(clientConnection, serverConnection);
}

protected async testSupportsClangTidy(command: string): Promise<boolean> {
// clangd should fail if -clang-tidy flag is not supported
// but if it is supported, it will run forever until killed/stopped.
// to avoid that, we pass -version flag which makes it exit early.
const process = await super.spawnProcessAsync(command, ['-clang-tidy', '-version']);
return new Promise<boolean>(resolve => {
process.errorOutput.on('data', (data: string) => {
if (data.includes('-clang-tidy')) {
resolve(false);
}
});
process.errorOutput.once('close', () => resolve(true));
});
}
}

0 comments on commit 9ddac67

Please sign in to comment.