@@ -10,14 +10,15 @@ import { Logger } from '../services/logging';
10
10
import { GNULinter , GNUModernLinter , IntelLinter , LFortranLinter , NAGLinter } from '../lib/linters' ;
11
11
import {
12
12
EXTENSION_ID ,
13
- FortranDocumentSelector ,
14
13
resolveVariables ,
15
14
promptForMissingTool ,
16
15
isFreeForm ,
17
16
spawnAsPromise ,
17
+ isFortran ,
18
+ shellTask ,
18
19
} from '../lib/tools' ;
19
20
import { arraysEqual } from '../lib/helper' ;
20
- import { RescanLint } from './commands' ;
21
+ import { BuildDebug , BuildRun , RescanLint } from './commands' ;
21
22
import { GlobPaths } from '../lib/glob-paths' ;
22
23
23
24
export class LinterSettings {
@@ -164,7 +165,24 @@ export class FortranLintingProvider {
164
165
public async activate ( subscriptions : vscode . Disposable [ ] ) {
165
166
// Register Linter commands
166
167
subscriptions . push ( vscode . commands . registerCommand ( RescanLint , this . rescanLinter , this ) ) ;
167
-
168
+ subscriptions . push (
169
+ vscode . commands . registerTextEditorCommand (
170
+ BuildRun ,
171
+ async ( textEditor : vscode . TextEditor , edit : vscode . TextEditorEdit , ...args : any [ ] ) => {
172
+ await this . buildAndRun ( textEditor ) ;
173
+ } ,
174
+ this
175
+ )
176
+ ) ;
177
+ subscriptions . push (
178
+ vscode . commands . registerTextEditorCommand (
179
+ BuildDebug ,
180
+ async ( textEditor : vscode . TextEditor , edit : vscode . TextEditorEdit , ...args : any [ ] ) => {
181
+ await this . buildAndDebug ( textEditor ) ;
182
+ } ,
183
+ this
184
+ )
185
+ ) ;
168
186
vscode . workspace . onDidOpenTextDocument ( this . doLint , this , subscriptions ) ;
169
187
vscode . workspace . onDidCloseTextDocument (
170
188
textDocument => {
@@ -194,12 +212,7 @@ export class FortranLintingProvider {
194
212
// Only lint if a compiler is specified
195
213
if ( ! this . settings . enabled ) return ;
196
214
// Only lint Fortran (free, fixed) format files
197
- if (
198
- ! FortranDocumentSelector ( ) . some ( e => e . scheme === textDocument . uri . scheme ) ||
199
- ! FortranDocumentSelector ( ) . some ( e => e . language === textDocument . languageId )
200
- ) {
201
- return ;
202
- }
215
+ if ( ! isFortran ( textDocument ) ) return ;
203
216
204
217
this . linter = this . getLinter ( this . settings . compiler ) ;
205
218
const command = this . getLinterExecutable ( ) ;
@@ -252,6 +265,45 @@ export class FortranLintingProvider {
252
265
}
253
266
}
254
267
268
+ private async buildAndRun ( textEditor : vscode . TextEditor ) {
269
+ return this . buildAndDebug ( textEditor , false ) ;
270
+ }
271
+
272
+ /**
273
+ * Compile and run the current file using the provided linter options.
274
+ * It has the ability to launch a Debug session or just run the executable.
275
+ * @param textEditor a text editor instance
276
+ * @param debug performing a debug build or not
277
+ */
278
+ private async buildAndDebug ( textEditor : vscode . TextEditor , debug = true ) : Promise < void > {
279
+ const textDocument = textEditor . document ;
280
+ this . linter = this . getLinter ( this . settings . compiler ) ;
281
+ const command = this . getLinterExecutable ( ) ;
282
+ let argList = [ ...this . constructArgumentList ( textDocument ) ] ;
283
+ // Remove mandatory linter args, used for mock compilation
284
+ argList = argList . filter ( arg => ! this . linter . args . includes ( arg ) ) ;
285
+ if ( debug ) argList . push ( '-g' ) ; // add debug symbols flag, same for all compilers
286
+ try {
287
+ await shellTask ( command , argList , 'Build Fortran file' ) ;
288
+ const folder : vscode . WorkspaceFolder = vscode . workspace . getWorkspaceFolder (
289
+ textEditor . document . uri
290
+ ) ;
291
+ const selectedConfig : vscode . DebugConfiguration = {
292
+ name : `${ debug ? 'Debug' : 'Run' } Fortran file` ,
293
+ // This relies on the C/C++ debug adapters
294
+ type : process . platform === 'win32' ? 'cppvsdbg' : 'cppdbg' ,
295
+ request : 'launch' ,
296
+ program : `${ textDocument . fileName } .o` ,
297
+ cwd : folder . uri . fsPath ,
298
+ } ;
299
+ await vscode . debug . startDebugging ( folder , selectedConfig , { noDebug : debug } ) ;
300
+ return ;
301
+ } catch ( err ) {
302
+ this . logger . error ( `[build] Compiling ${ textDocument . fileName } failed:` , err ) ;
303
+ console . error ( `ERROR: ${ err } ` ) ;
304
+ }
305
+ }
306
+
255
307
private getLinter ( compiler : string ) : GNULinter | GNUModernLinter | IntelLinter | NAGLinter {
256
308
switch ( compiler ) {
257
309
case 'gfortran' :
@@ -276,8 +328,8 @@ export class FortranLintingProvider {
276
328
this . logger . debug ( `[lint] glob paths:` , this . pathCache . get ( opt ) . globs ) ;
277
329
this . logger . debug ( `[lint] resolved paths:` , this . pathCache . get ( opt ) . paths ) ;
278
330
279
- const extensionIndex = textDocument . fileName . lastIndexOf ( '.' ) ;
280
- const fileNameWithoutExtension = textDocument . fileName . substring ( 0 , extensionIndex ) ;
331
+ // const extensionIndex = textDocument.fileName.lastIndexOf('.');
332
+ // const fileNameWithoutExtension = textDocument.fileName.substring(0, extensionIndex);
281
333
const fortranSource : string [ ] = this . settings . fyppEnabled
282
334
? [ '-xf95' , isFreeForm ( textDocument ) ? '-ffree-form' : '-ffixed-form' , '-' ]
283
335
: [ textDocument . fileName ] ;
@@ -286,7 +338,7 @@ export class FortranLintingProvider {
286
338
...args ,
287
339
...this . getIncludeParams ( includePaths ) , // include paths
288
340
'-o' ,
289
- `${ fileNameWithoutExtension } .mod ` ,
341
+ `${ textDocument . fileName } .o ` ,
290
342
...fortranSource ,
291
343
] ;
292
344
0 commit comments