Skip to content

Commit b332fb1

Browse files
committed
Merge branch 'master' of github.com:krvajal/vscode-fortran-support
2 parents ff1a52f + 2b5832b commit b332fb1

File tree

4 files changed

+173
-135
lines changed

4 files changed

+173
-135
lines changed

src/features/document-symbol-provider.ts

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
import { CancellationToken, TextDocument, Position, Hover } from "vscode";
1+
import {
2+
CancellationToken,
3+
TextDocument,
4+
Position,
5+
Hover,
6+
TextLine,
7+
SymbolInformation
8+
} from "vscode";
29

310
import * as vscode from "vscode";
4-
import { getDeclaredFunctions, getDeclaredSubroutines } from "../lib/functions";
5-
import { getDeclaredVars } from "../lib/variables";
11+
import {
12+
parseFunction as getDeclaredFunction,
13+
parseSubroutine as getDeclaredSubroutine
14+
} from "../lib/functions";
15+
import { parseVars as getDeclaredVar } from "../lib/variables";
16+
import { error } from "util";
617

718
type SymbolType = "subroutine" | "function" | "variable";
19+
type ParserFunc = (line: TextLine) => SymbolInformation | undefined;
820

921
export class FortranDocumentSymbolProvider
1022
implements vscode.DocumentSymbolProvider {
@@ -16,75 +28,88 @@ export class FortranDocumentSymbolProvider
1628
document: TextDocument,
1729
token: CancellationToken
1830
): Thenable<vscode.SymbolInformation[]> {
19-
return new Promise<vscode.SymbolInformation[]>((resolve, reject) => {
20-
token.onCancellationRequested(e => {
21-
reject();
22-
});
23-
const symbolTypes = this.getSymbolTypes();
24-
const documentSymbols = symbolTypes.reduce<vscode.SymbolInformation[]>(
25-
(symbols, type: SymbolType) => {
26-
return [...symbols, ...this.getSymbolsOfType(type, document)];
27-
},
28-
[]
29-
);
30-
31-
resolve(documentSymbols);
32-
});
31+
const cancel = new Promise<vscode.SymbolInformation[]>(
32+
(resolve, reject) => {
33+
token.onCancellationRequested(evt => {
34+
reject(error);
35+
});
36+
}
37+
);
38+
return Promise.race([this.parseDoc(document), cancel]);
3339
}
34-
getSymbolsOfType(
35-
type: "subroutine" | "function" | "variable",
36-
document: TextDocument
37-
) {
40+
parseDoc = async (document: TextDocument) => {
41+
let lines = document.lineCount;
42+
let symbols = [];
43+
const symbolTypes = this.getSymbolTypes();
44+
45+
for (let i = 0; i < lines; i++) {
46+
let line: vscode.TextLine = document.lineAt(i);
47+
line = { ...line, text: line.text.trim() };
48+
if (line.isEmptyOrWhitespace) continue;
49+
let initialCharacter = line.text.trim().charAt(0);
50+
if (initialCharacter === "!" || initialCharacter === "#") continue;
51+
const symbolsInLine = symbolTypes
52+
.map(type => this.getSymbolsOfType(type))
53+
.map(fn => fn(line))
54+
.filter(symb => symb != undefined);
55+
if (symbolsInLine.length > 0) {
56+
symbols = symbols.concat(symbolsInLine);
57+
}
58+
}
59+
return symbols;
60+
};
61+
getSymbolsOfType(type: "subroutine" | "function" | "variable"): ParserFunc {
3862
switch (type) {
3963
case "subroutine":
40-
this.updateSubroutineDefinitions(document);
41-
return this.subroutines;
64+
return this.parseSubroutineDefinition;
4265
case "function":
43-
this.updateFunctionDefinitions(document);
44-
return this.functions;
66+
return this.parseFunctionDefinition;
67+
4568
case "variable":
46-
this.updateVariablesDefiniton(document);
47-
return this.vars;
69+
return this.parseVariableDefinition;
4870
default:
49-
return [];
71+
return () => undefined;
5072
}
5173
}
5274

53-
private updateFunctionDefinitions(document: TextDocument) {
54-
this.functions = getDeclaredFunctions(document).map(fun => {
55-
let range = new vscode.Range(fun.lineNumber, 0, fun.lineNumber, 100);
56-
return new vscode.SymbolInformation(
57-
fun.name,
58-
vscode.SymbolKind.Function,
59-
range
60-
);
61-
});
75+
private parseSubroutineDefinition(line: TextLine) {
76+
try {
77+
const fun = getDeclaredSubroutine(line);
78+
if (fun) {
79+
let range = new vscode.Range(line.range.start, line.range.end);
80+
return new vscode.SymbolInformation(
81+
fun.name,
82+
vscode.SymbolKind.Method,
83+
range
84+
);
85+
}
86+
} catch (err) {
87+
console.log(err);
88+
}
6289
}
6390

64-
private updateSubroutineDefinitions(document: TextDocument) {
65-
this.subroutines = getDeclaredSubroutines(document).map(fun => {
66-
let range = new vscode.Range(fun.lineNumber, 0, fun.lineNumber, 100);
91+
private parseFunctionDefinition(line: TextLine) {
92+
const subroutine = getDeclaredFunction(line);
93+
if (subroutine) {
94+
let range = new vscode.Range(line.range.start, line.range.end);
95+
6796
return new vscode.SymbolInformation(
68-
fun.name,
97+
subroutine.name,
6998
vscode.SymbolKind.Function,
7099
range
71100
);
72-
});
101+
}
73102
}
74-
private updateVariablesDefiniton(document: TextDocument) {
75-
this.vars = getDeclaredVars(document).map(variable => {
76-
let range = new vscode.Range(
77-
variable.lineNumber,
78-
0,
79-
variable.lineNumber,
80-
100
81-
);
103+
private parseVariableDefinition(line: TextLine) {
104+
const variable = getDeclaredVar(line);
105+
if (variable) {
106+
let range = new vscode.Range(line.range.start, line.range.end);
82107
return new vscode.SymbolInformation(
83108
variable.name,
84109
vscode.SymbolKind.Variable,
85110
range
86111
);
87-
});
112+
}
88113
}
89114
getSymbolTypes() {
90115
let config = vscode.workspace.getConfiguration("fortran");

src/lib/functions.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
import * as vscode from "vscode";
2+
import { TextLine } from "vscode";
23

3-
export interface Variable {
4+
interface SymbolParser {}
5+
6+
export interface Tag {
7+
name: string;
8+
path?: string;
9+
scope?: string;
10+
parseMe?: (SymbolParser) => vscode.SymbolInformation;
11+
}
12+
13+
export interface Variable extends Tag {
414
name: string;
515
type?: string;
616
lineNumber?: number;
717
}
818

9-
export interface Subroutine {
19+
export interface Subroutine extends Tag {
1020
name: string;
1121
args: Variable[];
12-
docstr: string;
22+
docstr?: string;
1323
lineNumber: number;
1424
}
1525

@@ -31,9 +41,9 @@ export function getDeclaredFunctions(
3141
for (let i = 0; i < lines; i++) {
3242
let line: vscode.TextLine = document.lineAt(i);
3343
if (line.isEmptyOrWhitespace) continue;
34-
let newFunc = parseFunction(line.text);
44+
let newFunc = parseFunction(line);
3545
if (newFunc) {
36-
funcs.push({ ...newFunc, lineNumber: i });
46+
funcs.push(newFunc);
3747
}
3848
}
3949
return funcs;
@@ -48,41 +58,49 @@ export function getDeclaredSubroutines(
4858
for (let i = 0; i < lines; i++) {
4959
let line: vscode.TextLine = document.lineAt(i);
5060
if (line.isEmptyOrWhitespace) continue;
51-
let newSubroutine = parseSubroutine(line.text);
61+
let newSubroutine = parseSubroutine(line);
5262
if (newSubroutine) {
53-
subroutines.push({ ...newSubroutine, lineNumber: i });
63+
subroutines.push(newSubroutine);
5464
}
5565
}
5666
return subroutines;
5767
}
5868

59-
export const parseFunction = (line: string) => {
69+
export const parseFunction = (line: vscode.TextLine) => {
6070
return _parse(line, MethodType.Function);
6171
};
6272

63-
export const parseSubroutine = (line: string) => {
73+
export const parseSubroutine = (line: TextLine) => {
6474
return _parse(line, MethodType.Subroutine);
6575
};
66-
export const _parse = (line: string, type: MethodType) => {
67-
const functionRegEx = /([a-zA-Z]+(\([\w.=]+\))*)*\s*function\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\((\s*[a-zA-Z_][a-zA-Z0-9_,\s]*)*\s*\)\s*(result\([a-zA-Z_][\w]*\))*/gi;
68-
const subroutineRegEx = /subroutine\s*([a-zA-Z][a-zA-Z0-9_]*)\s*\((\s*[a-zA-Z][a-zA-z0-9_,\s]*)*\s*\)/gi;
76+
export const _parse = (line: TextLine, type: MethodType) => {
77+
const functionRegEx = /([a-zA-Z]+(\([\w.=]+\))*)*\s*function\s*([a-zA-Z_][a-z0-9_]*)\s*\((\s*[a-z_][a-z0-9_,\s]*)*\s*\)\s*(result\([a-z_][\w]*\))*/i;
78+
const subroutineRegEx = /subroutine\s*([a-z][a-z0-9_]*)\s*\((\s*[a-z][a-z0-9_,\s]*)*\s*(\)|&)/i;
6979
const regEx =
7080
type === MethodType.Subroutine ? subroutineRegEx : functionRegEx;
71-
if (line.match(regEx) && type === MethodType.Function) {
72-
let [attr, kind_descriptor, name, argsstr, result] = regEx
73-
.exec(line)
74-
.slice(1, 5);
81+
82+
if (type === MethodType.Subroutine && line.text.toLowerCase().indexOf("subroutine") < 0)
83+
return;
84+
if (type === MethodType.Function && line.text.toLowerCase().indexOf("function") < 0) return;
85+
const searchResult = regEx.exec(line.text);
86+
if (searchResult && type === MethodType.Function) {
87+
let [attr, kind_descriptor, name, argsstr, result] = searchResult.slice(
88+
1,
89+
5
90+
);
7591
let args = argsstr ? parseArgs(argsstr) : [];
7692
return {
7793
name: name,
78-
args: args
94+
args: args,
95+
lineNumber: line.lineNumber
7996
};
80-
} else if (line.match(regEx) && type === MethodType.Subroutine) {
81-
let [name, argsstr] = regEx.exec(line).slice(1);
97+
} else if (searchResult && type === MethodType.Subroutine) {
98+
let [name, argsstr] = searchResult.slice(1);
8299
let args = argsstr ? parseArgs(argsstr) : [];
83100
return {
84101
name: name,
85-
args: args
102+
args: args,
103+
lineNumber: line.lineNumber
86104
};
87105
}
88106
};

src/lib/variables.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
1-
2-
import * as vscode from 'vscode';
3-
import { Variable } from './functions';
4-
5-
1+
import * as vscode from "vscode";
2+
import { Variable } from "./functions";
3+
import { TextLine } from "vscode";
64

75
const varibleDecRegEx = /([a-zA-Z]{1,}(\([a-zA-Z0-9]{1,}\))?)(\s*,\s*[a-zA-Z\(\)])*\s*::\s*([a-zA-Z_][a-zA-Z0-9_]*)/g;
86

97
export function getDeclaredVars(document: vscode.TextDocument): Variable[] {
10-
11-
let lines = document.lineCount;
12-
let vars = [];
13-
14-
for (let i = 0; i < lines; i++) {
15-
let line: vscode.TextLine = document.lineAt(i);
16-
if (line.isEmptyOrWhitespace) continue;
17-
let newVar = parseVars(line.text);
18-
if ( newVar) {
19-
vars.push({...newVar, lineNumber: i });
20-
}
8+
let lines = document.lineCount;
9+
let vars = [];
10+
11+
for (let i = 0; i < lines; i++) {
12+
let line: vscode.TextLine = document.lineAt(i);
13+
if (line.isEmptyOrWhitespace) continue;
14+
let newVar = parseVars(line);
15+
if (newVar) {
16+
vars.push({ ...newVar, lineNumber: i });
2117
}
22-
return vars;
18+
}
19+
return vars;
2320
}
2421

25-
26-
export const parseVars = (line: string) => {
27-
28-
if(line.match(varibleDecRegEx)) {
29-
let [matchExp, type, kind, props, name ] = varibleDecRegEx.exec(line)
30-
return {name: name, type: type};
31-
}
22+
export const parseVars = (line: TextLine) => {
23+
if (line.text.match(varibleDecRegEx)) {
24+
let [matchExp, type, kind, props, name] = varibleDecRegEx.exec(line.text);
25+
return { name: name, type: type };
26+
}
3227
};
33-

0 commit comments

Comments
 (0)