mirror of
https://github.com/godotengine/godot-vscode-plugin.git
synced 2025-12-31 13:48:24 +03:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ba776dc40 | ||
|
|
abaa5d32d0 | ||
|
|
06817de78e | ||
|
|
6aab0be1d4 | ||
|
|
307e29a7ec | ||
|
|
58e8626cac | ||
|
|
3ac359af86 | ||
|
|
c20909fdb3 | ||
|
|
ec9fe7fdc1 | ||
|
|
c84d7f9c12 | ||
|
|
492fe5663c | ||
|
|
8f5da41a41 | ||
|
|
e4d86f35be | ||
|
|
eed2d4f516 | ||
|
|
63b10b1d72 | ||
|
|
fdc07e4743 | ||
|
|
80ce466d53 | ||
|
|
7e3e95086b | ||
|
|
7c8696abc1 | ||
|
|
8ddc7dd310 | ||
|
|
e76c06a31a | ||
|
|
4c0f864cf8 | ||
|
|
462a7bdbd7 | ||
|
|
e2dbf8146f | ||
|
|
7b21267d07 | ||
|
|
ef3a70f417 | ||
|
|
fc027ea9ad | ||
|
|
4c47fff9af | ||
|
|
d7ff45edac | ||
|
|
38b0898649 | ||
|
|
a3b062e242 | ||
|
|
071e59364f | ||
|
|
a47980981b | ||
|
|
edcb8b96d1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ test
|
||||
*.vsix
|
||||
configurations/tmp.txt
|
||||
configurations/test.py
|
||||
.vscode-test
|
||||
|
||||
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,5 +1,35 @@
|
||||
# Change Log
|
||||
|
||||
### 0.3.7
|
||||
* Add `lint` configuration to control the behaviors of syntax checking
|
||||
* Fix error with run godot editor when the editor contains spaces
|
||||
* Disable semicolons and brackets checks as default can be enabled with project settings
|
||||
* Fix bugs in syntax valiadating
|
||||
* Sync documentations with godot 3.0.4
|
||||
```json
|
||||
{
|
||||
"lint": {
|
||||
"semicolon": true,
|
||||
"conditionBrackets": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 0.3.6
|
||||
* Fix project configuartion file path
|
||||
|
||||
### 0.3.5
|
||||
* Add option to disable syntax checking for GDScript
|
||||
* Improved inline if else statement syntax checking
|
||||
* More resource type supported for syntax highglight
|
||||
* Bump default godot version to 3.0
|
||||
* Sync the documentations from godot 3.0
|
||||
|
||||
### 0.3.4
|
||||
* Fix bug with builtin symbols parsing for godot 2.1
|
||||
* Improved hover documentation
|
||||
* Show window progress when parsing workspace symbols
|
||||
|
||||
### 0.3.3
|
||||
* Fix some syntax checking errors.
|
||||
* Fix problems with hover documentation with latest VSCode.
|
||||
|
||||
88
README.md
88
README.md
@@ -2,77 +2,63 @@ A complete set of tools to code games with the [Godot game engine](http://www.go
|
||||
|
||||
## Features
|
||||
|
||||
The plug-in comes with a wealth of features to make your programming experience as comfortable as possible
|
||||
The extension comes with a wealth of features to make your Godot programming experience as comfortable as possible:
|
||||
|
||||
- Syntax highlighting for the GDscript language
|
||||
- Syntax highlighting for the tscn and tres scene formats
|
||||
- Function definitions and documentation on hover
|
||||
- Rich auto completion
|
||||
- Syntax highlighting for the GDscript (`.gd`) language
|
||||
- Syntax highlighting for the `.tscn` and `.tres` scene formats
|
||||
- Function definitions and documentation display on hover (see image below)
|
||||
- Rich auto-completion
|
||||
- Static code validation
|
||||
- Open projects and scenes in Godot from VScode
|
||||
- Ctrl click on a variable or method call to jump to its definition
|
||||
- Full documentation supported with API of godot engine
|
||||
- Open projects and scenes in Godot from VS Code
|
||||
- Ctrl-click on a variable or method call to jump to its definition
|
||||
- Full documentation of the Godot engine's API supported
|
||||
|
||||

|
||||
|
||||
## Available commands
|
||||
## Available Commands
|
||||
|
||||
The plug-ins adds a few entries to the command palette
|
||||
The extension adds a few entries to the VS Code Command Palette under "GodotTools":
|
||||
|
||||
- Update Workspace Symbols
|
||||
- Run workspace as godot project
|
||||
- Open workspace with godot editor
|
||||
- Update workspace symbols
|
||||
- Run workspace as Godot project
|
||||
- Open workspace with Godot editor
|
||||
- Run current scene
|
||||
|
||||
## Settings
|
||||
|
||||
If you like this plugin you can set VSCode as your default script editor with following steps:
|
||||
### Godot
|
||||
|
||||
If you like this extension, you can set VS Code as your default script editor for Godot by following these steps:
|
||||
1. Open editor settings
|
||||
2. Select `Text Editor / External`
|
||||
3. Check the `Use External Editor` box with mouse click
|
||||
4. Fill `Exec Path` to the path of your Visual Studio Code
|
||||
3. Make sure the `Use External Editor` box is checked
|
||||
4. Fill `Exec Path` with the path to your VS Code executable
|
||||
5. Fill `Exec Flags` with `{project} --goto {file}:{line}:{col}`
|
||||
|
||||
You can use the following settings to setup the Godot Tools:
|
||||
- GodotTools.godotVersion: The godot version of your project
|
||||
- GodotTools.editorPath: An absolute path pointing at the Godot Editor executable file. Required to run the project and test scenes from VScode
|
||||
- GodotTools.workspaceDocumentWithMarkdown: Control the documentations of workspace symbols should be rendered as plain text or html from markdown
|
||||
- GodotTools.ignoreIndentedVars: Parse variables defined after indent of not
|
||||
- GodotTools.parseTextScene: Parse scene files with extension ends with tscn
|
||||
- GodotTools.completeNodePath: Show node paths of of workspace in the code completion
|
||||
- GodotTools.godotProjectRoot: The godot project directory wich contains project.godot or engine.cfg
|
||||
## Issues and contributions
|
||||
### VS Code
|
||||
|
||||
The [Godot Tools](https://github.com/GodotExplorer/godot-tools) and the go to [engine modules](https://github.com/GodotExplorer/editor-server) are all hosted on GitHub. Feel free to open issues there and create pull requests anytime.
|
||||
You can use the following settings to configure Godot Tools:
|
||||
- **GodotTools.godotVersion** - The Godot version of your project.
|
||||
- **GodotTools.editorPath** - The absolute path to the Godot executable. Required to run the project and test scenes directly from VS Code.
|
||||
- **GodotTools.workspaceDocumentWithMarkdown** - Control how the documentation of workspace symbols should be rendered: as plain text or as HTML from Markdown.
|
||||
- **GodotTools.ignoreIndentedVars** - Only parse variables defined on lines without an indentation.
|
||||
- **GodotTools.parseTextScene** - Parse a file as a Godot scene when the file name ends with `.tscn`.
|
||||
- **GodotTools.completeNodePath** - Show node paths within a workspace as part of code completion.
|
||||
- **GodotTools.godotProjectRoot** - Your Godot project's directory, which contains `project.godot` or `engine.cfg`.
|
||||
|
||||
## Issues and Contributions
|
||||
|
||||
The [Godot Tools](https://github.com/GodotExplorer/godot-tools) extension and [engine modules](https://github.com/GodotExplorer/editor-server) are both hosted on GitHub. Feel free to open issues there and create pull requests anytime.
|
||||
|
||||
See the [full changelog](https://github.com/GodotExplorer/godot-tools/blob/master/CHANGELOG.md) for the latest changes.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Intelisense isn't showing up for me
|
||||
### Why isn't Intellisense showing up for me?
|
||||
|
||||
Make sure you save your .gd file, then run "GodotTools: Update Workspace Symbols" from the command palate
|
||||
Make sure you save your `.gd` file, then run "GodotTools: Update Workspace Symbols" from the Command Palette.
|
||||
|
||||
## Release Notes
|
||||
|
||||
### 0.3.3
|
||||
* Fix some syntax checking errors.
|
||||
* Fix problems with hover documentation with latest VSCode.
|
||||
* Improved builtin class documentation page.
|
||||
* Update the documentation data with latest godot version.
|
||||
|
||||
### 0.3.2
|
||||
* Fix syntax checking error with match statement.
|
||||
* Improved documentation for builtin code blocks.
|
||||
* Start using MarkdonwString to keep links valid.
|
||||
|
||||
### 0.3.1
|
||||
* Update documentations with latest godot.
|
||||
* Fix errors with run script and run project.
|
||||
* Improve code completion with opening script file and constants.
|
||||
* Some improvements for documentations.
|
||||
|
||||
[Full change log](https://github.com/GodotExplorer/godot-tools/blob/master/CHANGELOG.md)
|
||||
|
||||
## TODOS:
|
||||
* Convert official BBCode documentation into Markdown and render it to HTML with documentation previewer pages
|
||||
## TODO:
|
||||
* Convert official BBCode documentation into Markdown and render it into HTML with documentation previewer pages
|
||||
* Add mermaid support with documentation
|
||||
* Undefined variable checking
|
||||
|
||||
179407
doc/classes-3.0.json
179407
doc/classes-3.0.json
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,15 @@ import xml.etree.ElementTree as ET
|
||||
import json
|
||||
import os
|
||||
|
||||
def glob_path(path, pattern):
|
||||
import os, fnmatch
|
||||
result = []
|
||||
for root, _, files in os.walk(path):
|
||||
for filename in files:
|
||||
if fnmatch.fnmatch(filename, pattern):
|
||||
result.append(os.path.join(root, filename))
|
||||
return result
|
||||
|
||||
def parseClass(data):
|
||||
dictCls = dict(data.attrib)
|
||||
dictCls['brief_description'] = data.find("brief_description").text.strip()
|
||||
@@ -56,13 +65,14 @@ def main():
|
||||
if len(sys.argv) >=2 :
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
classes = {}
|
||||
for fname in os.listdir(sys.argv[1]):
|
||||
f = os.path.join(sys.argv[1], fname)
|
||||
for f in glob_path(sys.argv[1], "**.xml"):
|
||||
if f.find("/classes/") == -1 and f.find("/doc_classes/") == -1:
|
||||
continue
|
||||
tree = ET.parse(open(f, 'r'))
|
||||
cls = tree.getroot()
|
||||
dictCls = parseClass(cls)
|
||||
classes[dictCls['name']] = dictCls
|
||||
jsonContent = json.dumps({"classes": classes, "version": "3.0.alpha"}, ensure_ascii=False, indent=2)
|
||||
jsonContent = json.dumps({"classes": classes, "version": "3.0.4"}, ensure_ascii=False, indent=2)
|
||||
print(jsonContent)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
2235
package-lock.json
generated
2235
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
57
package.json
57
package.json
@@ -3,12 +3,12 @@
|
||||
"displayName": "Godot Tools",
|
||||
"icon": "icon.png",
|
||||
"description": "Tools for game development with godot game engine",
|
||||
"version": "0.3.3",
|
||||
"version": "0.3.7",
|
||||
"publisher": "geequlim",
|
||||
"repository": "https://github.com/GodotExplorer/godot-tools",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"vscode": "^1.16.1"
|
||||
"vscode": "^1.1.21"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
@@ -23,15 +23,15 @@
|
||||
"commands": [
|
||||
{
|
||||
"command": "godot.updateWorkspaceSymbols",
|
||||
"title": "GodotTools: Update Workspace Symbols"
|
||||
"title": "GodotTools: Update workspace symbols"
|
||||
},
|
||||
{
|
||||
"command": "godot.runWorkspace",
|
||||
"title": "GodotTools: Run workspace as godot project"
|
||||
"title": "GodotTools: Run workspace as Godot project"
|
||||
},
|
||||
{
|
||||
"command": "godot.openWithEditor",
|
||||
"title": "GodotTools: Open workspace with godot editor"
|
||||
"title": "GodotTools: Open workspace with Godot editor"
|
||||
},
|
||||
{
|
||||
"command": "godot.runCurrentScene",
|
||||
@@ -40,7 +40,7 @@
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "Godot tools configuration",
|
||||
"title": "Godot Tools configuration",
|
||||
"properties": {
|
||||
"GodotTools.maxNumberOfProblems": {
|
||||
"type": "number",
|
||||
@@ -50,12 +50,12 @@
|
||||
"GodotTools.editorPath": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The absolute path of your godot editor"
|
||||
"description": "The absolute path to the Godot executable"
|
||||
},
|
||||
"GodotTools.workspaceDocumentWithMarkdown": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Render workspace documentations as markdown content"
|
||||
"description": "Render workspace documentations as Markdown content"
|
||||
},
|
||||
"GodotTools.ignoreIndentedVars": {
|
||||
"type": "boolean",
|
||||
@@ -64,23 +64,37 @@
|
||||
},
|
||||
"GodotTools.godotVersion": {
|
||||
"type": "number",
|
||||
"default": 2.1,
|
||||
"description": "The godot version of your project"
|
||||
"default": 3.0,
|
||||
"description": "The Godot version of your project"
|
||||
},
|
||||
"GodotTools.parseTextScene": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Parse scene files with extention ends with tscn"
|
||||
"description": "Parse a file as a Godot scene when the file name ends with tscn"
|
||||
},
|
||||
"GodotTools.completeNodePath": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Show node pathes of of workspace in the code completion"
|
||||
"description": "Show node paths within a workspace as part of code completion"
|
||||
},
|
||||
"GodotTools.godotProjectRoot": {
|
||||
"type": "string",
|
||||
"default": "${workspaceRoot}",
|
||||
"description": "Relate path to the godot project"
|
||||
"description": "Your Godot project's directory"
|
||||
},
|
||||
"GodotTools.enableSyntaxChecking": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Turn on/off syntax checking for GDScript"
|
||||
},
|
||||
"GodotTools.lint": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"semicolon": false,
|
||||
"conditionBrackets": false,
|
||||
"unusedSymbols": true
|
||||
},
|
||||
"description": "Lint configuration"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -99,9 +113,12 @@
|
||||
{
|
||||
"id": "properties",
|
||||
"extensions": [
|
||||
".cfg",
|
||||
"cfg",
|
||||
"tres",
|
||||
"tscn"
|
||||
"tscn",
|
||||
"godot",
|
||||
"gdns",
|
||||
"gdnlib"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -126,11 +143,11 @@
|
||||
"test": "node ./node_modules/vscode/bin/test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^2.0.3",
|
||||
"vscode": "^1.1.5",
|
||||
"mocha": "^2.3.3",
|
||||
"@types/node": "^6.0.40",
|
||||
"@types/mocha": "^2.2.32"
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/node": "^10.9.4",
|
||||
"mocha": "^5.2.0",
|
||||
"typescript": "^3.0.3",
|
||||
"vscode": "^1.1.21"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": "^7.1.1",
|
||||
|
||||
@@ -108,7 +108,7 @@ class Config {
|
||||
// ---------------------- class -----------------
|
||||
const item: CompletionItem = new CompletionItem(classdoc.name, CompletionItemKind.Class);
|
||||
item.detail = 'Native Class';
|
||||
item.documentation = classdoc.brief_description + " \n\n" +classdoc.description;
|
||||
item.documentation = classdoc.brief_description + " \n" +classdoc.description;
|
||||
this.builtinCompletions.classes.push(item);
|
||||
builtinSymbolInfoMap[classdoc.name] = {completionItem: item, rowDoc: classdoc};
|
||||
// ----------------------- functions -----------------------
|
||||
@@ -192,6 +192,11 @@ class Config {
|
||||
script_files = Object.keys(this.workspaceSymbols);
|
||||
for (let path of script_files) {
|
||||
const script = this.workspaceSymbols[path];
|
||||
if (workspace) {
|
||||
const root = this.normalizePath(workspace.rootPath) + "/";
|
||||
if (path.startsWith(root))
|
||||
path = path.replace(root, "");
|
||||
}
|
||||
const addScriptItems = (items, kind: CompletionItemKind, kindName:string = "Symbol", insertText = (n)=>n)=>{
|
||||
const _items: CompletionItem[] = [];
|
||||
for (let name of Object.keys(items)) {
|
||||
@@ -203,7 +208,7 @@ class Config {
|
||||
item.detail = cvalue;
|
||||
item.insertText = insertText(name) + (signature=="()"?"()":"");
|
||||
item.documentation = (script.documents && script.documents[name])?script.documents[name]+"\r\n":"";
|
||||
item.documentation += `${kindName} defined in ${workspace.asRelativePath(path)}`;
|
||||
item.documentation += `${kindName} defined in ${path}`;
|
||||
_items.push(item);
|
||||
}
|
||||
return _items;
|
||||
@@ -323,4 +328,4 @@ class Config {
|
||||
|
||||
};
|
||||
|
||||
export default new Config();
|
||||
export default new Config();
|
||||
|
||||
@@ -1,189 +1,194 @@
|
||||
import requestGodot from "../request";
|
||||
import * as vscode from 'vscode';
|
||||
import {DiagnosticCollection, DiagnosticSeverity} from 'vscode';
|
||||
import config from '../config';
|
||||
|
||||
interface GDParseError {
|
||||
message : string,
|
||||
column : number,
|
||||
row : number
|
||||
}
|
||||
|
||||
interface GDScript {
|
||||
members : {
|
||||
constants: {},
|
||||
functions: {},
|
||||
variables: {},
|
||||
signals: {}
|
||||
},
|
||||
base : string,
|
||||
errors : GDParseError[],
|
||||
valid : boolean,
|
||||
is_tool : boolean,
|
||||
native : string
|
||||
}
|
||||
|
||||
interface ParseRequest {
|
||||
text : string,
|
||||
path : string
|
||||
}
|
||||
|
||||
class GDScriptDiagnosticSeverity {
|
||||
private _subscription : DiagnosticCollection;
|
||||
|
||||
constructor() {
|
||||
this._subscription = vscode.languages.createDiagnosticCollection("gdscript")
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._subscription.dispose()
|
||||
}
|
||||
|
||||
async validateScript(doc : vscode.TextDocument, script : any) {
|
||||
if (doc.languageId == 'gdscript') {
|
||||
if (script) {
|
||||
let diagnostics = [ ...(this.validateExpression(doc)), ...(this.validateUnusedSymbols(doc, script)) ];
|
||||
this._subscription.set(doc.uri, diagnostics);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private validateUnusedSymbols(doc : vscode.TextDocument, script) {
|
||||
let diagnostics = [];
|
||||
const text = doc.getText();
|
||||
|
||||
const check = (name : string, range : vscode.Range) => {
|
||||
var matchs = text.match(new RegExp(`([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
|
||||
let count = matchs ? matchs.length : 0;
|
||||
var incomment = text.match(new RegExp(`#.*?([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
|
||||
count -= incomment ? incomment.length : 0;
|
||||
if (count <= 1)
|
||||
diagnostics.push(new vscode.Diagnostic(range, `${name} is never used.`, DiagnosticSeverity.Warning));
|
||||
};
|
||||
// Unused variables
|
||||
for (let key of Object.keys(script.variables))
|
||||
check(key, script.variables[key]);
|
||||
for (let key of Object.keys(script.constants))
|
||||
check(key, script.constants[key]);
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
private validateExpression(doc : vscode.TextDocument) {
|
||||
let diagnostics = [];
|
||||
let expectEndOfLine = false;
|
||||
const text = doc.getText();
|
||||
const lines = text.split(/\r?\n/);
|
||||
lines.map((line : string, i : number) => {
|
||||
let matchstart = /[^\s]+.*/.exec(line);
|
||||
let curLineStartAt = 0;
|
||||
if (matchstart)
|
||||
curLineStartAt = matchstart.index;
|
||||
|
||||
// ignore comments
|
||||
if (line.match(/^\s*#.*/) || line.match(/^#.*/))
|
||||
return
|
||||
// normalize line content
|
||||
line = "\t" + line + "\t";
|
||||
var range = new vscode.Range(i, curLineStartAt, i, line.length);
|
||||
|
||||
if (line.match(/[^#].*?\;/) && !line.match(/[#].*?\;/)) {
|
||||
const semicolonIndex = line.indexOf(';');
|
||||
diagnostics.push(new vscode.Diagnostic(new vscode.Range(i, semicolonIndex, i, semicolonIndex + 1), "Statement contains a semicolon.", DiagnosticSeverity.Warning));
|
||||
}
|
||||
if (line.match(/[^#].*?/) && expectEndOfLine) {
|
||||
if (!line.match(/.*?(\\|\:)/)) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
|
||||
expectEndOfLine = false;
|
||||
}
|
||||
if (line.match(/.*?\:/))
|
||||
expectEndOfLine = false;
|
||||
}
|
||||
const colonKeywords = /\b(if|elif|else|for|while|func|class|match)\b/;
|
||||
let keywords = line.match(colonKeywords)
|
||||
if (keywords) {
|
||||
if(line.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || line.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?\'`)))
|
||||
return
|
||||
if(line.match(new RegExp(`.*?#.*?\\s${keywords[1]}\\s.*?`)))
|
||||
return
|
||||
if(line.match(/.*?\sif\s+\w.*?\s+else\s+\w.*/))
|
||||
return
|
||||
if (line.match(/.*?\\/))
|
||||
expectEndOfLine = true;
|
||||
else if (line.match(/.*?\:[\s+]+[^#\s]+/))
|
||||
return
|
||||
else if (!line.match(/.*?(\\|\:)/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
|
||||
else if (line.match(/(if|elif|while|func|class|match)\s*\:/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Indentifier expected before ':'", DiagnosticSeverity.Error));
|
||||
else if (line.match(/[^\w]for[^\w]/) && !line.match(/\s+for\s\w+\s+in\s+|[\w+]|\{.*?\}|\[.*?\]|\(.*?\)/)){
|
||||
if(!(line.match(/".*?for.*?"/) || line.match(/'.*?for.*?'/)))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Invalid for expression", DiagnosticSeverity.Error));
|
||||
}
|
||||
else if (line.match(/(if|elif|while|match)\s*\(.*\)/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Extra brackets in condition expression.", DiagnosticSeverity.Warning));
|
||||
const blockIndetCheck = function() {
|
||||
const err = new vscode.Diagnostic(range, "Expected indented block after expression", DiagnosticSeverity.Error);
|
||||
if (i < lines.length - 1) {
|
||||
let next = i + 1;
|
||||
let nextline = lines[next];
|
||||
// changes nextline until finds a line containg text or comes to the last line
|
||||
while (((!nextline || !nextline.trim().length) || nextline.match(/^\s*#/)) && next < lines.length - 1) {
|
||||
++next;
|
||||
nextline = lines[next];
|
||||
}
|
||||
let nextLineStartAt = -1;
|
||||
let match = /[^\s]+.*/.exec(nextline);
|
||||
if (match)
|
||||
nextLineStartAt = match.index;
|
||||
|
||||
if (nextLineStartAt <= curLineStartAt)
|
||||
diagnostics.push(err);
|
||||
}
|
||||
else if(line.match(/\:\s*$/))
|
||||
diagnostics.push(err);
|
||||
};
|
||||
if(!expectEndOfLine)
|
||||
blockIndetCheck();
|
||||
}
|
||||
// Do not check : for end of statement as it breaks match statment
|
||||
let endOfStateMentWithComma = false;
|
||||
if(endOfStateMentWithComma && !line.match(colonKeywords) && line.match(/\:\s*$/)) {
|
||||
let showErr = true;
|
||||
if( i >= 1 ) {
|
||||
let previous = i - 1;
|
||||
let previousline = lines[previous];
|
||||
while(previousline.match(/\\\s*$/) && previous>=1) {
|
||||
--previous;
|
||||
const ppreviousline = lines[previous];
|
||||
if(ppreviousline.match(/\\\s*$/))
|
||||
previousline = ppreviousline;
|
||||
}
|
||||
const keywords = previousline.match(colonKeywords);
|
||||
if(keywords && !(previousline.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || previousline.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?'`)) ))
|
||||
showErr = false
|
||||
}
|
||||
if(showErr)
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Expected end of statement after expression", DiagnosticSeverity.Error));
|
||||
}
|
||||
if (line.match(/(if|elif|while|return)\s+\w+\s*=\s*\w+/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Assignment in condition or return expressions", DiagnosticSeverity.Warning));
|
||||
else if (line.indexOf("==") > 0 && !line.match(/\:\s*/)) {
|
||||
const endAt = line.indexOf("==");
|
||||
const precontent = line.substring(0, endAt);
|
||||
if (!precontent.match(/\s(if|elif|while|return)\s/) && !precontent.match(/=[^=]/) && !expectEndOfLine) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Unhandled comparation expression contains", DiagnosticSeverity.Warning));
|
||||
}
|
||||
}
|
||||
let match = /var\s+(\w+)\s*=\s*(\w+)/.exec(line);
|
||||
if (match && match.length > 2 && match[1].length > 0 && match[1] == match[2]) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Self Assignment may cause error.", DiagnosticSeverity.Warning));
|
||||
}
|
||||
});
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GDScriptDiagnosticSeverity;
|
||||
import requestGodot from "../request";
|
||||
import * as vscode from 'vscode';
|
||||
import {DiagnosticCollection, DiagnosticSeverity} from 'vscode';
|
||||
import config from '../config';
|
||||
|
||||
interface GDParseError {
|
||||
message : string,
|
||||
column : number,
|
||||
row : number
|
||||
}
|
||||
|
||||
interface GDScript {
|
||||
members : {
|
||||
constants: {},
|
||||
functions: {},
|
||||
variables: {},
|
||||
signals: {}
|
||||
},
|
||||
base : string,
|
||||
errors : GDParseError[],
|
||||
valid : boolean,
|
||||
is_tool : boolean,
|
||||
native : string
|
||||
}
|
||||
|
||||
interface ParseRequest {
|
||||
text : string,
|
||||
path : string
|
||||
}
|
||||
|
||||
class GDScriptDiagnosticSeverity {
|
||||
private _subscription : DiagnosticCollection;
|
||||
|
||||
constructor() {
|
||||
this._subscription = vscode.languages.createDiagnosticCollection("gdscript")
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._subscription.dispose()
|
||||
}
|
||||
|
||||
async validateScript(doc : vscode.TextDocument, script : any) {
|
||||
if (doc.languageId == 'gdscript') {
|
||||
if (script) {
|
||||
let diagnostics = [ ...(this.validateExpression(doc)), ...(this.validateUnusedSymbols(doc, script)) ];
|
||||
this._subscription.set(doc.uri, diagnostics);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private validateUnusedSymbols(doc : vscode.TextDocument, script) {
|
||||
let diagnostics = [];
|
||||
let cfg : any = vscode.workspace.getConfiguration("GodotTools").get("lint");
|
||||
if (!cfg.unusedSymbols)
|
||||
return diagnostics
|
||||
|
||||
const text = doc.getText();
|
||||
const check = (name : string, range : vscode.Range) => {
|
||||
var matchs = text.match(new RegExp(`([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
|
||||
let count = matchs ? matchs.length : 0;
|
||||
var incomment = text.match(new RegExp(`#.*?([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
|
||||
count -= incomment ? incomment.length : 0;
|
||||
if (count <= 1)
|
||||
diagnostics.push(new vscode.Diagnostic(range, `${name} is never used.`, DiagnosticSeverity.Warning));
|
||||
};
|
||||
// Unused variables
|
||||
for (let key of Object.keys(script.variables))
|
||||
check(key, script.variables[key]);
|
||||
for (let key of Object.keys(script.constants))
|
||||
check(key, script.constants[key]);
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
private validateExpression(doc : vscode.TextDocument) {
|
||||
let cfg : any = vscode.workspace.getConfiguration("GodotTools").get("lint");
|
||||
|
||||
let diagnostics = [];
|
||||
let expectEndOfLine = false;
|
||||
const text = doc.getText();
|
||||
const lines = text.split(/\r?\n/);
|
||||
lines.map((line : string, i : number) => {
|
||||
let matchstart = /[^\s]+.*/.exec(line);
|
||||
let curLineStartAt = 0;
|
||||
if (matchstart)
|
||||
curLineStartAt = matchstart.index;
|
||||
|
||||
// ignore comments
|
||||
if (line.match(/^\s*#.*/) || line.match(/^#.*/))
|
||||
return
|
||||
// normalize line content
|
||||
line = "\t" + line + "\t";
|
||||
var range = new vscode.Range(i, curLineStartAt, i, line.length);
|
||||
|
||||
if (cfg.semicolon && line.match(/[^#].*?\;/) && !line.match(/[#].*?\;/)) {
|
||||
const semicolonIndex = line.indexOf(';');
|
||||
diagnostics.push(new vscode.Diagnostic(new vscode.Range(i, semicolonIndex, i, semicolonIndex + 1), "Statement contains a semicolon.", DiagnosticSeverity.Warning));
|
||||
}
|
||||
if (line.match(/[^#].*?/) && expectEndOfLine) {
|
||||
if (!line.match(/.*?(\\|\:)/)) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
|
||||
expectEndOfLine = false;
|
||||
}
|
||||
if (line.match(/.*?\:/))
|
||||
expectEndOfLine = false;
|
||||
}
|
||||
const colonKeywords = /\b(if|elif|else|for|while|func|class|match)\b/;
|
||||
let keywords = line.match(colonKeywords)
|
||||
if (keywords) {
|
||||
if(line.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || line.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?\'`)))
|
||||
return
|
||||
if(line.match(new RegExp(`.*?#.*?\\s${keywords[1]}\\s.*?`)))
|
||||
return
|
||||
if(line.match(/.*?\sif\s+(\!|\[|\{|\w|").*?\s+else\s+[^\s]+/))
|
||||
return
|
||||
if (line.match(/.*?\\/))
|
||||
expectEndOfLine = true;
|
||||
else if (line.match(/.*?\:[\s+]+[^#\s]+/))
|
||||
return
|
||||
else if (!line.match(/.*?(\\|\:)/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
|
||||
else if (line.match(/\s(if|elif|while|func|class|match)\s*\:/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Indentifier expected before ':'", DiagnosticSeverity.Error));
|
||||
else if (line.match(/[^\w]for[^\w]/) && !line.match(/\s+for\s\w+\s+in\s+|[\w+]|\{.*?\}|\[.*?\]|\(.*?\)/)){
|
||||
if(!(line.match(/".*?for.*?"/) || line.match(/'.*?for.*?'/)))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Invalid for expression", DiagnosticSeverity.Error));
|
||||
}
|
||||
else if (cfg.conditionBrackets && line.match(/\s(if|elif|while|match)\s*\(.*\)\s*:\s*$/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Extra brackets in condition expression.", DiagnosticSeverity.Warning));
|
||||
const blockIndetCheck = function() {
|
||||
const err = new vscode.Diagnostic(range, "Expected indented block after expression", DiagnosticSeverity.Error);
|
||||
if (i < lines.length - 1) {
|
||||
let next = i + 1;
|
||||
let nextline = lines[next];
|
||||
// changes nextline until finds a line containg text or comes to the last line
|
||||
while (((!nextline || !nextline.trim().length) || nextline.match(/^\s*#/)) && next < lines.length - 1) {
|
||||
++next;
|
||||
nextline = lines[next];
|
||||
}
|
||||
let nextLineStartAt = -1;
|
||||
let match = /[^\s]+.*/.exec(nextline);
|
||||
if (match)
|
||||
nextLineStartAt = match.index;
|
||||
|
||||
if (nextLineStartAt <= curLineStartAt)
|
||||
diagnostics.push(err);
|
||||
}
|
||||
else if(line.match(/\:\s*$/))
|
||||
diagnostics.push(err);
|
||||
};
|
||||
if(!expectEndOfLine)
|
||||
blockIndetCheck();
|
||||
}
|
||||
// Do not check : for end of statement as it breaks match statment
|
||||
let endOfStateMentWithComma = false;
|
||||
if(endOfStateMentWithComma && !line.match(colonKeywords) && line.match(/\:\s*$/)) {
|
||||
let showErr = true;
|
||||
if( i >= 1 ) {
|
||||
let previous = i - 1;
|
||||
let previousline = lines[previous];
|
||||
while(previousline.match(/\\\s*$/) && previous>=1) {
|
||||
--previous;
|
||||
const ppreviousline = lines[previous];
|
||||
if(ppreviousline.match(/\\\s*$/))
|
||||
previousline = ppreviousline;
|
||||
}
|
||||
const keywords = previousline.match(colonKeywords);
|
||||
if(keywords && !(previousline.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || previousline.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?'`)) ))
|
||||
showErr = false
|
||||
}
|
||||
if(showErr)
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Expected end of statement after expression", DiagnosticSeverity.Error));
|
||||
}
|
||||
if (line.match(/(if|elif|while|return)\s+\w+\s*=\s*\w+/))
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Assignment in condition or return expressions", DiagnosticSeverity.Warning));
|
||||
else if (line.indexOf("==") > 0 && !line.match(/\:\s*/)) {
|
||||
const endAt = line.indexOf("==");
|
||||
const precontent = line.substring(0, endAt);
|
||||
if (!precontent.match(/\s(if|elif|while|return)\s/) && !precontent.match(/=[^=]/) && !precontent.match(/assert\s*\(/) && !expectEndOfLine) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Unhandled comparation expression contains", DiagnosticSeverity.Warning));
|
||||
}
|
||||
}
|
||||
let match = /var\s+(\w+)\s*=\s*(\w+)/.exec(line);
|
||||
if (match && match.length > 2 && match[1].length > 0 && match[1] == match[2]) {
|
||||
diagnostics.push(new vscode.Diagnostic(range, "Self Assignment may cause error.", DiagnosticSeverity.Warning));
|
||||
}
|
||||
});
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GDScriptDiagnosticSeverity;
|
||||
|
||||
@@ -44,16 +44,19 @@ class GDScriptHoverProvider implements HoverProvider {
|
||||
|
||||
// check from workspace
|
||||
const genWorkspaceTips = ()=> {
|
||||
for (let path of Object.keys(workspaceSymbols)) {
|
||||
const script = workspaceSymbols[path];
|
||||
for (let filepath of Object.keys(workspaceSymbols)) {
|
||||
const script = workspaceSymbols[filepath];
|
||||
let scriptips: MarkdownString[] = [];
|
||||
const getHoverText = (items, type, path): MarkdownString[] => {
|
||||
const getHoverText = (items, type, gdpath): MarkdownString[] => {
|
||||
const _items: MarkdownString[] = [];
|
||||
for (let name of Object.keys(items)) {
|
||||
if (name == hoverText) {
|
||||
let dfile = path;
|
||||
if (workspace && workspace.asRelativePath(dfile))
|
||||
dfile = workspace.asRelativePath(dfile);
|
||||
let dfile = gdpath;
|
||||
if (workspace) {
|
||||
const root = config.normalizePath(workspace.rootPath) + "/";
|
||||
if (gdpath.startsWith(root))
|
||||
dfile = gdpath.replace(root, "");
|
||||
}
|
||||
let signature = "";
|
||||
if(type == "func"|| type == "signal" && script.signatures[name])
|
||||
signature = script.signatures[name];
|
||||
@@ -65,21 +68,21 @@ class GDScriptHoverProvider implements HoverProvider {
|
||||
rowDoc += "```plaintext\r\n"+rowDoc+"\r\n```";
|
||||
doc += rowDoc;
|
||||
doc = doc?doc+"\r\n\r\n":"";
|
||||
if(path != "autoload")
|
||||
doc += `*Defined in [${dfile}](${Uri.file(path).toString()})*`;
|
||||
if(gdpath != "autoload")
|
||||
doc += `*Defined in [${dfile}](${Uri.file(gdpath).toString()})*`;
|
||||
_items.push(makeMarkdown(doc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return _items;
|
||||
}
|
||||
scriptips = [...scriptips, ...getHoverText(script.variables, 'var', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.constants, 'const', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.functions, 'func', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.signals, 'signal', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.classes, 'class', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.variables, 'var', filepath)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.constants, 'const', filepath)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.functions, 'func', filepath)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.signals, 'signal', filepath)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.classes, 'class', filepath)];
|
||||
if(script.enumerations)
|
||||
scriptips = [...scriptips, ...getHoverText(script.enumerations, 'const', path)];
|
||||
scriptips = [...scriptips, ...getHoverText(script.enumerations, 'const', filepath)];
|
||||
tips = [...tips, ...scriptips];
|
||||
}
|
||||
};
|
||||
@@ -153,18 +156,18 @@ class GDScriptHoverProvider implements HoverProvider {
|
||||
|
||||
switch (item.kind) {
|
||||
case CompletionItemKind.Class:
|
||||
return makeMarkdown(`Native Class ${genLink(classname, classname)} ${doc}`);
|
||||
return makeMarkdown(`Native Class ${genLink(classname, classname)}\n${doc}`);
|
||||
case CompletionItemKind.Method:
|
||||
doc = doc.substring(doc.indexOf("\n")+1, doc.length);
|
||||
return makeMarkdown(`${genMethodMarkDown()} ${doc}`);
|
||||
return makeMarkdown(`${genMethodMarkDown()}\n${doc}`);
|
||||
case CompletionItemKind.Interface:
|
||||
doc = doc.substring(doc.indexOf("\n")+1, doc.length);
|
||||
return makeMarkdown(`signal + ${genMethodMarkDown()} ${doc}`);
|
||||
return makeMarkdown(`signal ${genMethodMarkDown()}\n${doc}`);
|
||||
case CompletionItemKind.Variable:
|
||||
case CompletionItemKind.Property:
|
||||
return makeMarkdown(`${rowDoc.type} ${genLink(classname, classname)}.${genLink(rowDoc.name, classname+"."+rowDoc.name)} ${doc}`);
|
||||
return makeMarkdown(`${rowDoc.type} ${genLink(classname, classname)}.${genLink(rowDoc.name, classname + "." + rowDoc.name)}\n${doc}`);
|
||||
case CompletionItemKind.Enum:
|
||||
return makeMarkdown(`const ${genLink(classname, classname)}.${genLink(rowDoc.name, classname+"."+rowDoc.name)} = ${rowDoc.value} ${doc}`);
|
||||
return makeMarkdown(`const ${genLink(classname, classname)}.${genLink(rowDoc.name, classname + "." + rowDoc.name)} = ${rowDoc.value}\n${doc}`);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -18,21 +18,22 @@ class ToolManager {
|
||||
private workspacesymbolprovider: GDScriptWorkspaceSymbolProvider = null;
|
||||
private _disposable: vscode.Disposable;
|
||||
private _context: vscode.ExtensionContext;
|
||||
private _projectFile : string = "engine.cfg";
|
||||
private _projectFile : string = "project.godot";
|
||||
private _rootDir : string = "";
|
||||
private _biuitinDocFile : string = "doc/classes-2.1.json";
|
||||
private _biuitinDocFile : string = "doc/classes-3.0.json";
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
this._context = context;
|
||||
this.workspaceDir = vscode.workspace.rootPath;
|
||||
let completionDollar = false;
|
||||
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("godotVersion", 2.1) >= 3) {
|
||||
this._projectFile = "project.godot";
|
||||
this._biuitinDocFile = "doc/classes-3.0.json";
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("godotVersion", 3.0) < 3) {
|
||||
this._projectFile = "engine.cfg";
|
||||
this._biuitinDocFile = "doc/classes-2.1.json";
|
||||
completionDollar = true;
|
||||
this.loadClasses();
|
||||
}
|
||||
this.loadClasses();
|
||||
|
||||
if (vscode.workspace && this.workspaceDir) {
|
||||
vscode.workspace.registerTextDocumentContentProvider('godotdoc', new GDScriptDocumentContentProvider());
|
||||
this.workspaceDir = this.workspaceDir.replace(/\\/g, "/");
|
||||
@@ -77,12 +78,12 @@ class ToolManager {
|
||||
if (path && path.length > 0 && path.endsWith("/"))
|
||||
path = path.substring(0, path.length - 1)
|
||||
if (path.toLowerCase() == self.workspaceDir.toLowerCase())
|
||||
vscode.window.showInformationMessage("Connected to godot editor server");
|
||||
vscode.window.showInformationMessage("Connected to the Godot editor server");
|
||||
else {
|
||||
vscode.window.showWarningMessage("The opened project is not same with godot editor");
|
||||
vscode.window.showWarningMessage("The opened project is not the same within the Godot editor");
|
||||
}
|
||||
}).catch(e => {
|
||||
vscode.window.showErrorMessage("Failed connect to godot editor server");
|
||||
vscode.window.showErrorMessage("Failed connecting to the Godot editor server");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -123,7 +124,7 @@ class ToolManager {
|
||||
gdpath = path.join(this._rootDir, gdpath);
|
||||
let showgdpath = vscode.workspace.asRelativePath(gdpath);
|
||||
|
||||
let doc = "Auto loaded instance of " + `[${showgdpath}](${vscode.Uri.file(gdpath).toString()})`;
|
||||
let doc = "Autoloaded instance of " + `[${showgdpath}](${vscode.Uri.file(gdpath).toString()})`;
|
||||
doc = doc.replace(/"/g, " ");
|
||||
|
||||
script.constants[name] = new vscode.Range(0, 0, 0, 0);
|
||||
@@ -156,13 +157,16 @@ class ToolManager {
|
||||
}
|
||||
|
||||
private loadWorkspaceSymbols() {
|
||||
let handle = this.showProgress("Loading symbols");
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("parseTextScene", false)) {
|
||||
this.loadAllNodesInWorkspace();
|
||||
}
|
||||
this.loadAllSymbols().then(symbols => {
|
||||
handle();
|
||||
vscode.window.setStatusBarMessage("$(check) Workspace symbols", 5000);
|
||||
config.setAllSymbols(symbols);
|
||||
}).catch(e => {
|
||||
handle();
|
||||
vscode.window.setStatusBarMessage("$(x) Workspace symbols", 5000);
|
||||
});
|
||||
}
|
||||
@@ -179,10 +183,10 @@ class ToolManager {
|
||||
let pathFlag = "-path";
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("godotVersion", 2.1) >= 3)
|
||||
pathFlag = "--path";
|
||||
this.runEditor(`${pathFlag} ${this._rootDir} ${params}`);
|
||||
this.runEditor(`${pathFlag} "${this._rootDir}" ${params}`);
|
||||
}
|
||||
else
|
||||
vscode.window.showErrorMessage("Current workspace is not a godot project");
|
||||
vscode.window.showErrorMessage("Current workspace is not a Godot project");
|
||||
}
|
||||
|
||||
private runEditor(params = "") {
|
||||
@@ -192,8 +196,13 @@ class ToolManager {
|
||||
if (!fs.existsSync(editorPath) || !fs.statSync(editorPath).isFile()) {
|
||||
vscode.window.showErrorMessage("Invalid editor path to run the project");
|
||||
} else {
|
||||
let terminal = vscode.window.createTerminal("Godot");
|
||||
let cmmand = `${editorPath.replace(" ", "\\ ")} ${params}`;
|
||||
let existingTerminal = vscode.window.terminals.find(t => t._name === "GodotTools")
|
||||
if (existingTerminal) {
|
||||
existingTerminal.dispose()
|
||||
}
|
||||
let terminal = vscode.window.createTerminal("GodotTools");
|
||||
editorPath = this.escapeCmd(editorPath);
|
||||
let cmmand = `${editorPath} ${params}`;
|
||||
terminal.sendText(cmmand, true);
|
||||
terminal.show();
|
||||
}
|
||||
@@ -214,7 +223,7 @@ class ToolManager {
|
||||
const script = config.loadSymbolsFromFile(absFilePath);
|
||||
if (script) {
|
||||
if(script.native == "SceneTree" || script.native == "MainLoop") {
|
||||
this.runEditor(`-s ${absFilePath}`);
|
||||
this.runEditor(`-s "${absFilePath}"`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -222,9 +231,9 @@ class ToolManager {
|
||||
}
|
||||
if (scenePath) {
|
||||
if (scenePath.endsWith(".gd"))
|
||||
scenePath = ` -s res://${scenePath} `;
|
||||
scenePath = ` -s "res://${scenePath}" `;
|
||||
else
|
||||
scenePath = ` res://${scenePath} `;
|
||||
scenePath = ` "res://${scenePath}" `;
|
||||
this.openWorkspaceWithEditor(scenePath);
|
||||
} else
|
||||
vscode.window.showErrorMessage("Current document is not a scene file or MainLoop");
|
||||
@@ -237,12 +246,38 @@ class ToolManager {
|
||||
if (!done)
|
||||
done = config.loadClasses(path.join(this._context.extensionPath, this._biuitinDocFile));
|
||||
if (!done)
|
||||
vscode.window.showErrorMessage("Load GDScript documentations failed");
|
||||
vscode.window.showErrorMessage("Loading GDScript documentation failed");
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposable.dispose();
|
||||
}
|
||||
|
||||
private showProgress(message: string) {
|
||||
let r_resolve;
|
||||
vscode.window.withProgress({ location: vscode.ProgressLocation.Window}, p => {
|
||||
return new Promise((resolve, reject) => {
|
||||
p.report({message});
|
||||
r_resolve = resolve;
|
||||
});
|
||||
});
|
||||
return r_resolve;
|
||||
}
|
||||
|
||||
private escapeCmd(cmd: string) {
|
||||
// Double quote command (should work in at least cmd.exe and bash)
|
||||
let cmdEsc = `"${cmd}"`;
|
||||
|
||||
// Fetch Windows shell type
|
||||
let shell = vscode.workspace.getConfiguration("terminal.integrated.shell").get("windows", "");
|
||||
|
||||
// For powershell we prepend an & to prevent the command being treated as a string
|
||||
if (shell.endsWith("powershell.exe") && process.platform === "win32") {
|
||||
cmdEsc = `&${cmdEsc}`;
|
||||
}
|
||||
return cmdEsc
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default ToolManager;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as vscode from 'vscode';
|
||||
import {Disposable, window} from 'vscode';
|
||||
import GDScriptDiagnosticSeverity from './gdscript/diagnostic';
|
||||
import GDScriptCompleter from './gdscript/completion';
|
||||
@@ -40,7 +41,9 @@ class WindowWatcher {
|
||||
if(window.activeTextEditor != undefined) {
|
||||
const doc = window.activeTextEditor.document;
|
||||
const script = config.loadSymbolsFromFile(doc.fileName);
|
||||
this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("enableSyntaxChecking", true)) {
|
||||
this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
|
||||
}
|
||||
this._lastText = {path: doc.fileName, version: doc.version};
|
||||
}
|
||||
}
|
||||
@@ -55,7 +58,9 @@ class WindowWatcher {
|
||||
// Check content changed
|
||||
if(this._lastText.path != curText.path || this._lastText.version != curText.version) {
|
||||
const script = config.loadSymbolsFromFile(doc.fileName);
|
||||
this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
|
||||
if (vscode.workspace.getConfiguration("GodotTools").get("enableSyntaxChecking", true)) {
|
||||
this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
|
||||
}
|
||||
this._lastText = curText;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user