|
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