1- import { strictEqual } from 'assert' ;
1+ import { deepStrictEqual , strictEqual } from 'assert' ;
22import * as path from 'path' ;
33
4- import * as vscode from 'vscode' ;
4+ import { glob } from 'glob' ;
5+ import {
6+ commands ,
7+ Diagnostic ,
8+ DiagnosticSeverity ,
9+ Position ,
10+ Range ,
11+ TextDocument ,
12+ Uri ,
13+ window ,
14+ workspace ,
15+ } from 'vscode' ;
516
617import {
718 CleanLintDiagnostics ,
819 CleanLintFiles ,
920 InitLint ,
1021 RescanLint ,
1122} from '../../src/commands/commands' ;
23+ import {
24+ GNULinter ,
25+ GNUModernLinter ,
26+ IntelLinter ,
27+ LFortranLinter ,
28+ NAGLinter ,
29+ } from '../../src/lint/compilers' ;
1230import { FortranLintingProvider } from '../../src/lint/provider' ;
31+ import { LogLevel , Logger } from '../../src/services/logging' ;
32+ import { EXTENSION_ID , pipInstall } from '../../src/util/tools' ;
1333
14- suite ( 'Linter' , async ( ) => {
15- let doc : vscode . TextDocument ;
16- const fileUri = vscode . Uri . file ( path . resolve ( __dirname , '../../../test/fortran/sample.f90' ) ) ;
34+ suite ( 'Linter VS Code commands ' , async ( ) => {
35+ let doc : TextDocument ;
36+ const fileUri = Uri . file ( path . resolve ( __dirname , '../../../test/fortran/sample.f90' ) ) ;
1737 const linter = new FortranLintingProvider ( ) ;
1838
1939 suiteSetup ( async ( ) => {
20- doc = await vscode . workspace . openTextDocument ( fileUri ) ;
21- await vscode . window . showTextDocument ( doc ) ;
40+ doc = await workspace . openTextDocument ( fileUri ) ;
41+ await window . showTextDocument ( doc ) ;
2242 } ) ;
2343
2444 test ( 'Check disposables array has been populated' , async ( ) => {
@@ -27,19 +47,19 @@ suite('Linter', async () => {
2747 } ) ;
2848
2949 // test(`Run command ${InitLint}`, async () => {
30- // await vscode. commands.executeCommand(InitLint);
50+ // await commands.executeCommand(InitLint);
3151 // });
3252
3353 test ( `Run command is ${ RescanLint } ` , async ( ) => {
34- await vscode . commands . executeCommand ( RescanLint ) ;
54+ await commands . executeCommand ( RescanLint ) ;
3555 } ) ;
3656
3757 test ( `Run command ${ CleanLintDiagnostics } ` , async ( ) => {
38- await vscode . commands . executeCommand ( CleanLintDiagnostics ) ;
58+ await commands . executeCommand ( CleanLintDiagnostics ) ;
3959 } ) ;
4060
4161 test ( `Run command ${ CleanLintFiles } ` , async ( ) => {
42- await vscode . commands . executeCommand ( CleanLintFiles ) ;
62+ await commands . executeCommand ( CleanLintFiles ) ;
4363 } ) ;
4464
4565 test ( 'Check disposables have been cleared' , ( ) => {
@@ -49,11 +69,133 @@ suite('Linter', async () => {
4969
5070 test ( 'Check file association overrides propagate to the linter' , async ( ) => {
5171 const file = '../../../test/fortran/lint/fixed-as-free.f77' ;
52- const fileUri = vscode . Uri . file ( path . resolve ( __dirname , file ) ) ;
53- doc = await vscode . workspace . openTextDocument ( fileUri ) ;
54- await vscode . window . showTextDocument ( doc ) ;
72+ const fileUri = Uri . file ( path . resolve ( __dirname , file ) ) ;
73+ doc = await workspace . openTextDocument ( fileUri ) ;
74+ await window . showTextDocument ( doc ) ;
5575 const res = await linter [ 'doLint' ] ( doc ) ;
5676 strictEqual ( res !== undefined , true ) ;
5777 strictEqual ( res ?. length , 0 ) ;
5878 } ) ;
5979} ) ;
80+
81+ const logger = new Logger ( window . createOutputChannel ( 'Modern Fortran' , 'log' ) , LogLevel . DEBUG ) ;
82+
83+ suite ( 'Linter integration' , async ( ) => {
84+ let doc : TextDocument ;
85+ const linter = new FortranLintingProvider ( logger ) ;
86+ const fileUri = Uri . file ( path . resolve ( __dirname , '../../../test/fortran/lint/test1.f90' ) ) ;
87+ const root = path . resolve ( __dirname , '../../../test/fortran/' ) ;
88+ const config = workspace . getConfiguration ( EXTENSION_ID ) ;
89+ const oldVals = config . get < string [ ] > ( 'linter.includePaths' ) ;
90+
91+ suiteSetup ( async ( ) => {
92+ doc = await workspace . openTextDocument ( fileUri ) ;
93+ await window . showTextDocument ( doc ) ;
94+ } ) ;
95+ // different versions of gfortran report the error at a different column number
96+ // need to implement a the compiler versioning see #523
97+ test ( 'GNU - API call to doLint produces correct diagnostics' , async ( ) => {
98+ const diags = await new FortranLintingProvider ( logger ) [ 'doLint' ] ( doc ) ;
99+ const ref : Diagnostic [ ] = [
100+ new Diagnostic (
101+ new Range ( new Position ( 21 - 1 , 18 - 1 ) , new Position ( 21 - 1 , 18 - 1 ) ) ,
102+ 'Syntax error in argument list at (1)' ,
103+ DiagnosticSeverity . Error
104+ ) ,
105+ new Diagnostic (
106+ new Range ( new Position ( 7 - 1 , 9 - 1 ) , new Position ( 7 - 1 , 9 - 1 ) ) ,
107+ "Type specified for intrinsic function 'size' at (1) is ignored [-Wsurprising]" ,
108+ DiagnosticSeverity . Warning
109+ ) ,
110+ ] ;
111+
112+ deepStrictEqual ( diags , ref ) ;
113+ } ) ;
114+
115+ test ( 'Include path globs & internal variable resolution' , async ( ) => {
116+ const paths = linter [ 'getGlobPathsFromSettings' ] ( 'linter.includePaths' ) ;
117+ // const refs: string[] = fg.sync(path.dirname(fileUri.path) + '/**', { onlyDirectories: true });
118+ const refs : string [ ] = glob . sync ( path . dirname ( fileUri . path ) + '/**/' ) ;
119+ deepStrictEqual ( paths , refs ) ;
120+ } ) ;
121+
122+ test ( 'Path cache contains expected values' , async ( ) => {
123+ let refs : string [ ] = [ '${workspaceFolder}/lint/**' ] ;
124+ deepStrictEqual ( linter [ 'pathCache' ] . get ( 'linter.includePaths' ) ?. globs , refs ) ;
125+ // refs = fg.sync(path.join(root, 'lint') + '/**', { onlyDirectories: true });
126+ refs = glob . sync ( path . join ( root , 'lint' ) + '/**/' ) ;
127+ deepStrictEqual ( linter [ 'pathCache' ] . get ( 'linter.includePaths' ) ?. paths , refs ) ;
128+ } ) ;
129+
130+ test ( 'Update paths using cache' , async ( ) => {
131+ // const refs: string[] = fg.sync([path.join(root, 'lint') + '/**', path.join(root, 'debug')], {
132+ // onlyDirectories: true,
133+ // });
134+ const refs : string [ ] = [ path . join ( root , 'lint' ) + '/**' , path . join ( root , 'debug' ) ]
135+ . map ( d => glob . sync ( d + '/' ) )
136+ . flat ( ) ;
137+ await config . update (
138+ 'linter.includePaths' ,
139+ [ '${workspaceFolder}/lint/**' , path . join ( root , 'debug' ) ] ,
140+ false
141+ ) ;
142+ const paths = linter [ 'getGlobPathsFromSettings' ] ( 'linter.includePaths' ) ;
143+ deepStrictEqual ( paths , refs ) ;
144+ } ) ;
145+
146+ test ( 'Linter user setting returns the right linter internally' , ( ) => {
147+ const names = [ 'gfortran' , 'ifort' , 'ifx' , 'nagfor' , 'lfortran' , 'fake' ] ;
148+ for ( const n of names ) {
149+ const compiler = linter [ 'getLinter' ] ( n ) ;
150+ if ( n === 'gfortran' ) {
151+ if ( linter [ 'settings' ] . modernGNU ) {
152+ strictEqual ( compiler instanceof GNUModernLinter , true ) ;
153+ } else {
154+ strictEqual ( compiler instanceof GNULinter , true ) ;
155+ }
156+ } else if ( n === 'ifort' || n === 'ifx' ) {
157+ strictEqual ( compiler instanceof IntelLinter , true ) ;
158+ } else if ( n === 'nagfor' ) {
159+ strictEqual ( compiler instanceof NAGLinter , true ) ;
160+ } else if ( n == 'lfortran' ) {
161+ strictEqual ( compiler instanceof LFortranLinter , true ) ;
162+ } else {
163+ strictEqual ( compiler instanceof GNULinter , true ) ;
164+ }
165+ }
166+ } ) ;
167+
168+ suiteTeardown ( async function ( ) : Promise < void > {
169+ await config . update ( 'linter.includePaths' , oldVals , false ) ;
170+ } ) ;
171+ } ) ;
172+
173+ suite ( 'Linter (fypp) integration' , ( ) => {
174+ const root = path . resolve ( __dirname , '../../../test/fortran/' ) ;
175+ const config = workspace . getConfiguration ( EXTENSION_ID ) ;
176+
177+ suiteSetup ( async ( ) => {
178+ await pipInstall ( 'fypp' ) ;
179+ await config . update ( `linter.fypp.enabled` , true , false ) ;
180+ } ) ;
181+
182+ test ( 'GNU - API call to doLint produces correct diagnostics' , async ( ) => {
183+ const fileUri = Uri . file ( path . resolve ( __dirname , '../../../test/fortran/fypp/demo.fypp' ) ) ;
184+ const doc = await workspace . openTextDocument ( fileUri ) ;
185+ await window . showTextDocument ( doc ) ;
186+
187+ const diags = await new FortranLintingProvider ( logger ) [ 'doLint' ] ( doc ) ;
188+ const refs : Diagnostic [ ] = [
189+ new Diagnostic (
190+ new Range ( new Position ( 18 , 35 ) , new Position ( 18 , 35 ) ) ,
191+ "Unused dummy argument 'this' at (1) [-Wunused-dummy-argument]" ,
192+ DiagnosticSeverity . Warning
193+ ) ,
194+ ] ;
195+ deepStrictEqual ( diags , refs ) ;
196+ } ) ;
197+
198+ suiteTeardown ( async ( ) => {
199+ await config . update ( `linter.fypp.enabled` , false , false ) ;
200+ } ) ;
201+ } ) ;
0 commit comments