diff --git a/configrations/trace_builtins.py b/configurations/trace_builtins.py similarity index 100% rename from configrations/trace_builtins.py rename to configurations/trace_builtins.py diff --git a/package.json b/package.json index f6d4017..502423b 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,11 @@ "type": "boolean", "default": false, "description": "Render workspace documentations as markdown content" + }, + "GodotTools.ignoreIndentedVars": { + "type": "boolean", + "default": true, + "description": "Only parse variables without indents in GDScript" } } }, diff --git a/src/config.ts b/src/config.ts index 46c6b00..3afb100 100644 --- a/src/config.ts +++ b/src/config.ts @@ -31,7 +31,10 @@ class Config { } loadSymbolsFromFile(path) { - const script = this.parser.parseFile(path); + var ignoreIndentedVars = false; + if(workspace) + ignoreIndentedVars = workspace.getConfiguration("GodotTools").get("ignoreIndentedVars", false); + const script = this.parser.parseFile(path, ignoreIndentedVars); this.setSymbols(path, script); return script; } diff --git a/src/gdscript/diagnostic.ts b/src/gdscript/diagnostic.ts index 62014f4..75b37b3 100644 --- a/src/gdscript/diagnostic.ts +++ b/src/gdscript/diagnostic.ts @@ -57,11 +57,13 @@ class GDScriptDiagnosticSeverity { private validateUnusedSymbols(doc: vscode.TextDocument,script) { let diagnostics = []; - const text = doc.getText().replace(new RegExp(/#.*$/, "gm"), ""); //excludes comments from being checked for syntax + const text = doc.getText(); const check = (name:string, range: vscode.Range) => { var matchs = text.match(new RegExp(`[^0-9A-Za-z_]\\s*${name}[^0-9A-Za-z_]\\s*`, 'g')); let count = matchs?matchs.length:0; + var incomment = text.match(new RegExp(`#[^0-9A-z_]*${name}[^0-9A-z_]`, 'g')); + count -= incomment?incomment.length:0; if(count <= 1) diagnostics.push(new vscode.Diagnostic(range, `${name} is never used.`, DiagnosticSeverity.Warning)); }; diff --git a/src/gdscript/symbolparser.ts b/src/gdscript/symbolparser.ts index 57a4269..558026c 100644 --- a/src/gdscript/symbolparser.ts +++ b/src/gdscript/symbolparser.ts @@ -20,7 +20,7 @@ class GDScriptSymbolParser { constructor() { } - parseContent(content: string): GDScript { + parseContent(content: string, ignoreIndentedVars:boolean = false): GDScript { const script: GDScript = { constants: {}, functions: {}, @@ -36,13 +36,23 @@ class GDScriptSymbolParser { const text = content; const lines = text.split(/\r?\n/); - const getMatches = (string, regex, index=1) => { + const getMatches = (regex:RegExp, index=1) => { var matches = []; - var match; - while (match = regex.exec(string)) { - matches.push(match[index]); + for(let line of lines) { + let match; + if (match = regex.exec(line)) { + let commentReg = RegExp(/#.*?/.source+regex.source); + if(!commentReg.exec(line)) + matches.push(match[index]); + } } return matches; + // var matches = []; + // var match; + // while (match = regex.exec(string)) { + // matches.push(match[index]); + // } + // return matches; }; const findLineRanges = (symbols, reg)=>{ @@ -89,7 +99,9 @@ class GDScriptSymbolParser { while( line > 0){ const linecontent = lines[line]; let match = linecontent.match(/\s*#\s*(.*)/); - const commentAtEnd = linecontent.match(/[\w'",\[\{\]\}\(\)]+\s*#\s*(.*)/); + let commentAtEnd = linecontent.match(/[\w'",\[\{\]\}\(\)]+\s*#\s*(.*)/) != null; + if(commentAtEnd && linecontent.match(/^#/)) + commentAtEnd = false; if(!match && line != range.start.line) break; if(commentAtEnd && line != range.start.line) @@ -107,7 +119,7 @@ class GDScriptSymbolParser { return mdoc; } - let funcsnames = getMatches(text, /func\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/g, 1); + let funcsnames = getMatches(/func\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/, 1); const funcs = findLineRanges(funcsnames, "func\\s+$X$\\s*\\("); for (let key of Object.keys(funcs)) { let r: Range = determRange(key, funcs); @@ -116,7 +128,7 @@ class GDScriptSymbolParser { script.documents[key] = parseDocument(r); } - let signalnames = getMatches(text, /signal\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/g, 1); + let signalnames = getMatches(/signal\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/, 1); const signals = findLineRanges(signalnames, "signal\\s+$X$\\s*\\("); for (let key of Object.keys(signals)) { let r: Range = determRange(key, signals); @@ -125,8 +137,14 @@ class GDScriptSymbolParser { script.documents[key] = parseDocument(r); } - let varnames = getMatches(text, /var\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/g, 1); - const vars = findLineRanges(varnames, "var\\s+$X$\\s*"); + let varreg = /var\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/; + let varreg2 = "var\\s+$X$\\s*"; + if(ignoreIndentedVars) { + varreg = /^var\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/; + varreg2 = "^var\\s+$X$\\s*"; + } + let varnames = getMatches(varreg, 1); + const vars = findLineRanges(varnames, varreg2); for (let key of Object.keys(vars)){ const r:Range = determRange(key, vars) script.variables[key] = r; @@ -136,7 +154,7 @@ class GDScriptSymbolParser { script.documents[key] = newdoc; } - let constnames = getMatches(text, /const\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/g, 1); + let constnames = getMatches(/const\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/, 1); const consts = findLineRanges(constnames, "const\\s+$X$\\s*"); for (let key of Object.keys(consts)){ const r:Range = determRange(key, consts) @@ -152,7 +170,7 @@ class GDScriptSymbolParser { script.constvalues[key] = match[2]; } - let classnames = getMatches(text, /class\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*extends\s+/g, 1); + let classnames = getMatches(/class\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*extends\s+/, 1); const classes = findLineRanges(classnames, "class\\s+$X$\\s*extends\\s+"); for (let key of Object.keys(classes)) { const r:Range = determRange(key, classes) @@ -163,11 +181,11 @@ class GDScriptSymbolParser { return script; } - parseFile(path:string): GDScript { + parseFile(path:string, ignoreIndentedVars:boolean = false): GDScript { const self = this; if(fs.existsSync(path) && fs.statSync(path).isFile()){ const content = fs.readFileSync(path, 'utf-8'); - return this.parseContent(content); + return this.parseContent(content, ignoreIndentedVars); } return null; } diff --git a/src/gdscript/symbolprovider.ts b/src/gdscript/symbolprovider.ts index f2ffd4d..6bc5ea1 100644 --- a/src/gdscript/symbolprovider.ts +++ b/src/gdscript/symbolprovider.ts @@ -4,7 +4,8 @@ import { SymbolInformation, CancellationToken, SymbolKind, - Range + Range, + workspace } from 'vscode'; import GDScriptSymbolParser from '../gdscript/symbolparser'; @@ -20,7 +21,10 @@ class GDScriptSymbolProvider implements DocumentSymbolProvider { provideDocumentSymbols(document: TextDocument, token: CancellationToken): SymbolInformation[] | Thenable { const symbols: SymbolInformation[] = []; - const script = this.parser.parseContent(document.getText()); + var ignoreIndentedVars = false; + if(workspace) + ignoreIndentedVars = workspace.getConfiguration("GodotTools").get("ignoreIndentedVars", false); + const script = this.parser.parseContent(document.getText(), ignoreIndentedVars); const signatures = script.signatures; config.setSymbols(document.fileName, script); diff --git a/test_files/0.2.2/test.gd b/test_files/0.2.2/test.gd deleted file mode 100644 index 758b9e3..0000000 --- a/test_files/0.2.2/test.gd +++ /dev/null @@ -1,64 +0,0 @@ -#Highlights syntax highglighting issues in godot-tools release 0.2.2 - -extends Node - -# class member variables go here, for example: -#var a = 2 -# var b = "textvar" - -#func read(): #in 0.2.2, false positive -# var path = "res://assets/instructions.toml" -# var file = File.new() -# file.open(path, file.READ) -# -#func _ready(): #in 0.2.2 false positive -# # Called every time the node is added to the scene. -# # Initialization here -# read() - -func remove_ends(text): #in 0.2.2 false positive -#vasdfs - var result = "result" #hello - result = result.replace("[", "") - result = result.replace("]", "") - return result - -func read_cfg(path): #in 0.2.2 false positive - - var config = ConfigFile.new() - var err = config.load(path) - - var sections = {} - if err == OK: # if not, something went wrong with the file loading - # Look for the display/width pair, and default to 1024 if missing -# #var screen_width = get_value("display", "width", 1024) #in 0.2.2 false positive -# # Store a variable if and only it hasn't been defined yet -# if not config.has_section_key("audio", "mute"): -# config.set_value("audio", "mute", false) -# # Save the changes by overwriting the previous file -# config.save("user://settings.cfg" - for i in config.get_sections(): - var section_pairs = {} - for j in config.get_section_keys(i): - section_pairs[j] = config.get_value(i, j) - sections[i] = section_pairs - print(sections) - return sections - -func something(): #in 0.2.2 diagnostics correctly complains -asdfsdd - -asdfsdf -asdf -func somethingelse(): #in 0.2.2 correctly doesn't complain - asdfsd - -asdfsd #in 0.2.2 should complain? - -func something_else(): - var asds = 2 #in 0.2.2 diagnostics should complain - asdfsdaf s = 3 #in 0.2.2 diagnostics should complain - return 3 - -func yet_else(): - pass \ No newline at end of file diff --git a/test_files/0.2.2/test2.gd b/test_files/0.2.2/test2.gd deleted file mode 100644 index e6240d3..0000000 --- a/test_files/0.2.2/test2.gd +++ /dev/null @@ -1,5 +0,0 @@ -#func read(): -#func read(): #in 0.2.2, false positive -# func read(): #in 0.2.2, not false positive -#func -#var a = 0 \ No newline at end of file