Skip to content

Commit

Permalink
Allow diagnostic code lookup on the web
Browse files Browse the repository at this point in the history
In some cases, like for misra rule checking with CppCheck, no useful
description is available from the tool. This change introduces the
ability to search the diagnostic code on the web for more information.
The query base Uri and the set of words to match to activate the
behavior are configurable through settings. For security reasons, the
query base Uri is only configurable from trusted workspaces.
The feature also only activates when the language server doesn't
already provide a link in the generated diagnostic.
  • Loading branch information
unai-i authored and jbenden committed Jul 28, 2022
1 parent cd90ce2 commit 2d1d5f7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
18 changes: 16 additions & 2 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { TextDocument, commands, env, ExtensionContext, window, workspace, tasks, TaskEndEvent, TaskGroup, Uri, WorkspaceConfiguration } from 'vscode';
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
SettingMonitor,
TransportKind,
} from 'vscode-languageclient/node';
import * as vscode from 'vscode';
import { FlylintLanguageClient } from './flylintLanguageClient';
import * as path from 'path';
import { getFromWorkspaceState, resetWorkspaceState, setWorkspaceState, updateWorkspaceState } from './stateUtils';
import { isBoolean } from 'lodash';
Expand All @@ -18,6 +19,7 @@ const SECURITY_SENSITIVE_CONFIG: string[] = [
'flawfinder.executable',
'lizard.executable',
'pclintplus.executable',
'queryUrlBase'
];
var IS_TRUSTED: boolean = false;

Expand Down Expand Up @@ -132,7 +134,19 @@ function startLSClient(serverOptions: ServerOptions, context: ExtensionContext)
}
};

const client = new LanguageClient('c-cpp-flylint', 'C/C++ Flylint', serverOptions, clientOptions);
let settings = vscode.workspace.getConfiguration('c-cpp-flylint');
let queryUrlBase = settings.get<string>('queryUrlBase');
let webQueryMatchSet = settings.get<Array<string>>('webQueryMatchSet');

if (queryUrlBase === undefined) {
queryUrlBase = 'https://www.google.com/search?q=';
}
if (webQueryMatchSet === undefined) {
webQueryMatchSet = [];
}

const client = new FlylintLanguageClient('c-cpp-flylint', 'C/C++ Flylint', serverOptions, clientOptions,
queryUrlBase, webQueryMatchSet);

client.onReady()
.then(() => {
Expand Down
34 changes: 34 additions & 0 deletions client/src/flylintLanguageClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {LanguageClient, LanguageClientOptions, ServerOptions} from 'vscode-languageclient/node';
import * as ls from 'vscode-languageserver';
import * as code from 'vscode';

export class FlylintLanguageClient extends LanguageClient {
constructor(
id: string,
name: string,
serverOptions: ServerOptions,
clientOptions: LanguageClientOptions,
queryUrlStr: string,
matchSet: string[],
forceDebug?: boolean
) {
super(id, name, serverOptions, clientOptions, forceDebug);
let originalAsDiagnostic = this.protocol2CodeConverter.asDiagnostic;
this.protocol2CodeConverter.asDiagnostic = ((diagnostic: ls.Diagnostic): code.Diagnostic => {
let result = originalAsDiagnostic(diagnostic);
if ((result.code !== undefined) && (typeof result.code === 'string') && (queryUrlStr.length > 0)) {
let codeStr = String(result.code);
if (matchSet.some(v => codeStr.includes(v))) {
result.code = {
value: result.code,
target: this.protocol2CodeConverter.asUri(`${queryUrlStr}${result.source}%20${result.code}`)
};
}
}
return result;
});
this.protocol2CodeConverter.asDiagnostics = ((diagnostics: ls.Diagnostic[]): code.Diagnostic[] => {
return diagnostics.map(this.protocol2CodeConverter.asDiagnostic);
});
}
}
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,19 @@
"default": [],
"description": "Paths to search for include files. They may be relative or absolute. Cascades to all analyzers unless overridden in one or more analyzers. If not specified it uses \"C_Cpp.default.includePath\" or \"includePath\" from c_cpp_properties.json"
},
"c-cpp-flylint.queryUrlBase": {
"type": "string",
"format": "uri",
"markdownDescription": "This option allows you to chose your preferred search engine for diagnostic code lookup. See also `#c-cpp-flylint.webQueryMatchSet#` to configure the keywords of the diagnostic code which will make it searchable on the web.",
"default": "https://www.google.com/search?q="
},
"c-cpp-flylint.webQueryMatchSet": {
"type": "array",
"default": [
"misra-"
],
"markdownDescription": "The diagnostic code match set for which a web lookup will be proposed. Web search engine can be customized through `#c-cpp-flylint.queryUrlBase#`."
},
"c-cpp-flylint.clang.enable": {
"type": "boolean",
"default": true,
Expand Down

0 comments on commit 2d1d5f7

Please sign in to comment.