Skip to content

Commit 98b2669

Browse files
committed
feat: basic linting setup
1 parent c2c22c0 commit 98b2669

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
"category": "flowR",
4646
"icon": "$(gear)"
4747
},
48+
{
49+
"command": "vscode-flowr.lint.run",
50+
"icon": "$(bug)",
51+
"title": "Code Quality Analysis (Linter)",
52+
"category": "flowR"
53+
},
4854
{
4955
"command": "vscode-flowr.internal.slice.dependency",
5056
"title": "Show Slice of Dependency",

src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { FlowrConfigOptions } from '@eagleoutice/flowr/config';
1313
import { DropPathsOption, InferWorkingDirectory, VariableResolve , defaultConfigOptions, setConfig } from '@eagleoutice/flowr/config';
1414
import type { BuiltInDefinitions } from '@eagleoutice/flowr/dataflow/environments/built-in-config';
1515
import { deepMergeObject } from '@eagleoutice/flowr/util/objects';
16+
import { registerLintCommands } from './lint';
1617

1718
export const MINIMUM_R_MAJOR = 3;
1819
export const BEST_R_MAJOR = 4;
@@ -29,6 +30,7 @@ export async function activate(context: vscode.ExtensionContext) {
2930

3031
registerDiagramCommands(context, outputChannel);
3132
registerSliceCommands(context, outputChannel);
33+
registerLintCommands(context, outputChannel);
3234

3335
updateFlowrConfig();
3436
vscode.workspace.onDidChangeConfiguration(updateFlowrConfig);

src/lint.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import * as vscode from 'vscode';
2+
import { getFlowrSession } from './extension';
3+
import { LintingRuleNames, LintingRuleResult, LintingRules } from '@eagleoutice/flowr/linter/linter-rules';
4+
import { FilePathValidityResult } from '@eagleoutice/flowr/linter/rules/2-file-path-validity';
5+
import { DeprecatedFunctionsResult } from '@eagleoutice/flowr/linter/rules/1-deprecated-functions';
6+
7+
export function registerLintCommands(context: vscode.ExtensionContext, output: vscode.OutputChannel) {
8+
const linter = new LinterService(output);
9+
context.subscriptions.push(vscode.commands.registerCommand('vscode-flowr.lint.run', async() => {
10+
await linter.runLinting()
11+
}));
12+
}
13+
14+
class LinterService {
15+
private readonly output: vscode.OutputChannel;
16+
private readonly collection = vscode.languages.createDiagnosticCollection('flowr-lint');
17+
18+
constructor(output: vscode.OutputChannel) {
19+
this.output = output;
20+
}
21+
22+
async runLinting(): Promise<void> {
23+
const activeEditor = vscode.window.activeTextEditor;
24+
25+
if (!activeEditor) {
26+
return;
27+
}
28+
29+
const diagnostics: vscode.Diagnostic[] = [];
30+
this.output.appendLine(`[Lint] Analyzing document: ${activeEditor.document.fileName}`);
31+
const session = await getFlowrSession();
32+
33+
const lint = await session.retrieveQuery(activeEditor.document, [{ type: 'linter' }]);
34+
35+
for(const [ruleName, findings] of Object.entries(lint.result.linter.results)) {
36+
const rule = LintingRules[ruleName as LintingRuleNames];
37+
38+
this.output.appendLine(`[Lint] Found ${findings.results.length} issues for rule: ${ruleName}`);
39+
this.output.appendLine(`[Lint] ${JSON.stringify(findings)}`);
40+
41+
for(const finding of findings.results) {
42+
const range = new vscode.Range(
43+
finding.range[0] - 1,
44+
finding.range[1] - 1,
45+
finding.range[2] - 1,
46+
finding.range[3] - 1
47+
);
48+
diagnostics.push(
49+
new vscode.Diagnostic(
50+
range,
51+
ruleName + ': ' + rule.prettyPrint(finding as LintingRuleResult<LintingRuleNames>),
52+
vscode.DiagnosticSeverity.Warning
53+
)
54+
);
55+
}
56+
}
57+
58+
this.collection.set(activeEditor.document.uri, diagnostics);
59+
}
60+
}

0 commit comments

Comments
 (0)