|
3 | 3 | import * as path from 'path';
|
4 | 4 | import * as cp from 'child_process';
|
5 | 5 | import ChildProcess = cp.ChildProcess;
|
6 |
| -import { getIncludeParams } from '../lib/helper'; |
| 6 | +import { getIncludeParams, LANGUAGE_ID } from '../lib/helper'; |
7 | 7 |
|
8 | 8 | import * as vscode from 'vscode';
|
9 | 9 |
|
10 | 10 | export default class FortranLintingProvider {
|
| 11 | + |
| 12 | + constructor() { |
11 | 13 |
|
12 |
| - constructor(){ |
13 |
| - // filename:line:col: is common for multiline and single line warnings |
14 |
| - // this.regex = '^[^:]*:(\d+)[:.](?P<col>\d+):'; |
15 |
| - |
16 |
| - } |
17 |
| - |
18 |
| - private diagnosticCollection: vscode.DiagnosticCollection; |
19 |
| - private doModernFortranLint(textDocument: vscode.TextDocument) { |
20 |
| - let errorRegex:RegExp = /^([^:]*):([0-9]+):([0-9]+):\n\s(.*)\n.*\n(Error|Warning|Fatal Error):\s(.*)$/gm; |
21 |
| - |
22 |
| - if (textDocument.languageId !== 'fortran90') { |
23 |
| - return; |
24 |
| - } |
25 |
| - let decoded = ''; |
26 |
| - let diagnostics: vscode.Diagnostic[] = []; |
27 |
| - let options = vscode.workspace.rootPath ? { cwd: vscode.workspace.rootPath } : undefined; |
28 |
| - let args = [...this.getLinterExtraArgs(), "-cpp", "-fsyntax-only", '-fdiagnostics-show-option']; |
29 |
| - let includePaths = this.getIncludePaths(); |
30 |
| - let command = this.getGfortranPath(); |
31 |
| - |
32 |
| - let childProcess = cp.spawn(command, [ |
33 |
| - ...args, |
34 |
| - getIncludeParams(includePaths), // include paths |
35 |
| - textDocument.fileName]); |
36 |
| - |
37 |
| - if (childProcess.pid) { |
38 |
| - childProcess.stdout.on('data', (data: Buffer) => { |
39 |
| - decoded += data; |
40 |
| - }); |
41 |
| - childProcess.stderr.on('data', (data) => { |
42 |
| - decoded += data; |
43 |
| - }); |
44 |
| - childProcess.stderr.on('end', () => { |
45 |
| - let decodedOriginal = decoded; |
46 |
| - |
47 |
| - let matchesArray:string[]; |
48 |
| - while ((matchesArray = errorRegex.exec(decoded)) !== null) { |
49 |
| - let elements: string[] = matchesArray.slice(1); // get captured expressions |
50 |
| - let startLine = parseInt(elements[1]); |
51 |
| - let startColumn = parseInt(elements[2]) |
52 |
| - let type = elements[4]; //error or warning |
53 |
| - let severity = type.toLowerCase() === "warning" ? vscode.DiagnosticSeverity.Warning : vscode.DiagnosticSeverity.Error; |
54 |
| - let message = elements[5]; |
55 |
| - let range = new vscode.Range(new vscode.Position(startLine - 1 , startColumn), |
56 |
| - new vscode.Position(startLine - 1, startColumn)); |
57 |
| - let diagnostic = new vscode.Diagnostic(range,message , severity); |
58 |
| - diagnostics.push(diagnostic) |
59 |
| - } |
60 |
| - |
61 |
| - this.diagnosticCollection.set(textDocument.uri, diagnostics); |
62 |
| - }); |
63 |
| - childProcess.stdout.on('close', code => { |
64 |
| - console.log(`child process exited with code ${code}`); |
65 |
| - }); |
66 |
| - }else { |
67 |
| - childProcess.on('error', (err: any) => { |
68 |
| - if(err.code === "ENOENT"){ |
69 |
| - vscode.window.showErrorMessage("gfortran can't found on path, update your settings with a proper path or disable the linter."); |
70 |
| - } |
71 |
| - |
72 |
| - }); |
73 |
| - } |
74 |
| - } |
75 |
| - |
76 |
| - private static commandId: string = 'fortran.lint.runCodeAction'; |
77 |
| - |
78 |
| - public provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): vscode.Command[] { |
79 |
| - return; |
80 |
| - // let diagnostic: vscode.Diagnostic = context.diagnostics[0]; |
81 |
| - // return [{ |
82 |
| - // title: "Accept gfortran suggestion", |
83 |
| - // command: FortranLintingProvider.commandId, |
84 |
| - // arguments: [document, diagnostic.range, diagnostic.message] |
85 |
| - // }]; |
86 |
| - } |
87 |
| - |
88 |
| - private command: vscode.Disposable; |
89 |
| - |
90 |
| - public activate(subscriptions: vscode.Disposable[]) { |
91 |
| - |
92 |
| - |
93 |
| - this.diagnosticCollection = vscode.languages.createDiagnosticCollection(); |
94 |
| - |
95 |
| - vscode.workspace.onDidOpenTextDocument(this.doModernFortranLint, this, subscriptions); |
96 |
| - vscode.workspace.onDidCloseTextDocument((textDocument) => { |
97 |
| - this.diagnosticCollection.delete(textDocument.uri); |
98 |
| - }, null, subscriptions); |
99 |
| - |
100 |
| - vscode.workspace.onDidSaveTextDocument(this.doModernFortranLint, this); |
101 |
| - |
102 |
| - // Run gfortran in all open fortran files |
103 |
| - vscode.workspace.textDocuments.forEach(this.doModernFortranLint, this); |
104 |
| - } |
105 |
| - |
106 |
| - |
107 |
| - public dispose(): void { |
108 |
| - this.diagnosticCollection.clear(); |
109 |
| - this.diagnosticCollection.dispose(); |
110 |
| - this.command.dispose(); |
111 |
| - } |
112 |
| - |
113 |
| - private getIncludePaths():string[]{ |
114 |
| - let config = vscode.workspace.getConfiguration('fortran'); |
115 |
| - let includePaths:string[] = config.get("includePaths", []); |
116 |
| - |
117 |
| - return includePaths; |
118 |
| - } |
119 |
| - private getGfortranPath():string{ |
120 |
| - let config = vscode.workspace.getConfiguration('fortran'); |
121 |
| - return config.get("gfortranExecutable","gfortran"); |
122 |
| - } |
123 |
| - private getLinterExtraArgs():string[]{ |
124 |
| - let config = vscode.workspace.getConfiguration('fortran'); |
125 |
| - return config.get("linterExtraArgs",["-Wall"]); |
126 |
| - } |
| 14 | + |
| 15 | + } |
| 16 | + |
| 17 | + private diagnosticCollection: vscode.DiagnosticCollection; |
| 18 | + private doModernFortranLint(textDocument: vscode.TextDocument) { |
| 19 | + const errorRegex: RegExp = /^([^:]*):([0-9]+):([0-9]+):\n\s(.*)\n.*\n(Error|Warning|Fatal Error):\s(.*)$/gm; |
| 20 | + |
| 21 | + if (textDocument.languageId !== LANGUAGE_ID) { |
| 22 | + return; |
| 23 | + } |
| 24 | + let decoded = ''; |
| 25 | + let diagnostics: vscode.Diagnostic[] = []; |
| 26 | + let options = vscode.workspace.rootPath ? { cwd: vscode.workspace.rootPath } : undefined; |
| 27 | + let args = [...this.getLinterExtraArgs(), "-cpp", "-fsyntax-only", '-fdiagnostics-show-option']; |
| 28 | + let includePaths = this.getIncludePaths(); |
| 29 | + let command = this.getGfortranPath(); |
| 30 | + |
| 31 | + let childProcess = cp.spawn(command, [ |
| 32 | + ...args, |
| 33 | + getIncludeParams(includePaths), // include paths |
| 34 | + textDocument.fileName]); |
| 35 | + |
| 36 | + if (childProcess.pid) { |
| 37 | + childProcess.stdout.on('data', (data: Buffer) => { |
| 38 | + decoded += data; |
| 39 | + }); |
| 40 | + childProcess.stderr.on('data', (data) => { |
| 41 | + decoded += data; |
| 42 | + }); |
| 43 | + childProcess.stderr.on('end', () => { |
| 44 | + let decodedOriginal = decoded; |
| 45 | + |
| 46 | + let matchesArray: string[]; |
| 47 | + while ((matchesArray = errorRegex.exec(decoded)) !== null) { |
| 48 | + let elements: string[] = matchesArray.slice(1); // get captured expressions |
| 49 | + let startLine = parseInt(elements[1]); |
| 50 | + let startColumn = parseInt(elements[2]) |
| 51 | + let type = elements[4]; //error or warning |
| 52 | + let severity = type.toLowerCase() === "warning" ? vscode.DiagnosticSeverity.Warning : vscode.DiagnosticSeverity.Error; |
| 53 | + let message = elements[5]; |
| 54 | + let range = new vscode.Range(new vscode.Position(startLine - 1, startColumn), |
| 55 | + new vscode.Position(startLine - 1, startColumn)); |
| 56 | + let diagnostic = new vscode.Diagnostic(range, message, severity); |
| 57 | + diagnostics.push(diagnostic) |
| 58 | + } |
| 59 | + |
| 60 | + this.diagnosticCollection.set(textDocument.uri, diagnostics); |
| 61 | + }); |
| 62 | + childProcess.stdout.on('close', code => { |
| 63 | + console.log(`child process exited with code ${code}`); |
| 64 | + }); |
| 65 | + } else { |
| 66 | + childProcess.on('error', (err: any) => { |
| 67 | + if (err.code === "ENOENT") { |
| 68 | + vscode.window.showErrorMessage("gfortran can't found on path, update your settings with a proper path or disable the linter."); |
| 69 | + } |
| 70 | + |
| 71 | + }); |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + private static commandId: string = 'fortran.lint.runCodeAction'; |
| 76 | + |
| 77 | + public provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): vscode.Command[] { |
| 78 | + return; |
| 79 | + // let diagnostic: vscode.Diagnostic = context.diagnostics[0]; |
| 80 | + // return [{ |
| 81 | + // title: "Accept gfortran suggestion", |
| 82 | + // command: FortranLintingProvider.commandId, |
| 83 | + // arguments: [document, diagnostic.range, diagnostic.message] |
| 84 | + // }]; |
| 85 | + } |
| 86 | + |
| 87 | + private command: vscode.Disposable; |
| 88 | + |
| 89 | + public activate(subscriptions: vscode.Disposable[]) { |
| 90 | + |
| 91 | + |
| 92 | + this.diagnosticCollection = vscode.languages.createDiagnosticCollection(); |
| 93 | + |
| 94 | + vscode.workspace.onDidOpenTextDocument(this.doModernFortranLint, this, subscriptions); |
| 95 | + vscode.workspace.onDidCloseTextDocument((textDocument) => { |
| 96 | + this.diagnosticCollection.delete(textDocument.uri); |
| 97 | + }, null, subscriptions); |
| 98 | + |
| 99 | + vscode.workspace.onDidSaveTextDocument(this.doModernFortranLint, this); |
| 100 | + |
| 101 | + // Run gfortran in all open fortran files |
| 102 | + vscode.workspace.textDocuments.forEach(this.doModernFortranLint, this); |
| 103 | + } |
| 104 | + |
| 105 | + public dispose(): void { |
| 106 | + this.diagnosticCollection.clear(); |
| 107 | + this.diagnosticCollection.dispose(); |
| 108 | + this.command.dispose(); |
| 109 | + } |
| 110 | + |
| 111 | + private getIncludePaths(): string[] { |
| 112 | + let config = vscode.workspace.getConfiguration('fortran'); |
| 113 | + let includePaths: string[] = config.get("includePaths", []); |
| 114 | + |
| 115 | + return includePaths; |
| 116 | + } |
| 117 | + private getGfortranPath(): string { |
| 118 | + let config = vscode.workspace.getConfiguration('fortran'); |
| 119 | + return config.get("gfortranExecutable", "gfortran"); |
| 120 | + } |
| 121 | + private getLinterExtraArgs(): string[] { |
| 122 | + let config = vscode.workspace.getConfiguration('fortran'); |
| 123 | + return config.get("linterExtraArgs", ["-Wall"]); |
| 124 | + } |
127 | 125 |
|
128 | 126 | }
|
0 commit comments