Compare commits

...

11 Commits
1.2.0 ... 1.3.0

Author SHA1 Message Date
Hugo Locurcio
7b49c4b3e8 Bump to version 1.3.0 2022-05-09 23:02:59 +02:00
Hugo Locurcio
588df8fd93 Mention that the Godot editor must be running in connection error message (#358) 2022-05-09 14:44:19 +02:00
Daelon Suzuka
f860020c63 Add context menu options to copy resource path (#357)
* Add feature
* Fix "open_workspace_with_editor" command
* Added option to tab title context menu
* Add ability to get resource path using command palette
* Update lockfile

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-05-08 23:47:53 +02:00
Anton Vakhtel
1d76541f04 Add strict onEnterRules for controlling indentation (#344)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-05-06 17:33:49 +02:00
Daelon Suzuka
fb96098c70 Fix keywords being incorrectly highlighted as function calls (#353) 2022-04-28 01:16:44 +02:00
Hugo Locurcio
0835506157 Add download links for stable releases and development builds to README (#343) 2022-04-24 17:17:04 +02:00
Daelon Suzuka
2cfbed2dad Fix syntax highlighting edge cases (#350)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-04-22 15:35:36 +02:00
Daelon Suzuka
5e0d108953 Add missing NodePath-using functions (#348) 2022-04-18 23:37:06 +02:00
Daelon Suzuka
78e37e8016 Overhaul syntax highlighting (#342)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-04-11 18:33:16 +02:00
Anton Vakhtel
547b92ad80 Add option to run the project with visible collision shapes and navigation (#312)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-04-07 02:27:13 +02:00
Daelon Suzuka
4ac06a7691 Add configurable auto-reconnect (#341)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2022-04-06 17:46:50 +02:00
17 changed files with 3480 additions and 426 deletions

View File

@@ -40,7 +40,7 @@ body:
Open the **Extensions** side panel and click on the **godot-tools** extension to see your current version.
Specify the Git commit hash if using a development or non-official build.
If you use a custom build, please test if your issue is reproducible in official builds too.
placeholder: "1.2.0"
placeholder: "1.3.0"
validations:
required: true

View File

@@ -40,7 +40,7 @@ body:
Open the **Extensions** side panel and click on the **godot-tools** extension to see your current version.
Specify the Git commit hash if using a development or non-official build.
If you use a custom build, please test if your issue is reproducible in official builds too.
placeholder: "1.2.0"
placeholder: "1.3.0"
validations:
required: true

View File

@@ -1,5 +1,12 @@
# Change Log
### 1.3.0
* [Add context menu options to copy resource path](https://github.com/godotengine/godot-vscode-plugin/pull/357)
* [Add option to run the project with visible collision shapes and navigation](https://github.com/godotengine/godot-vscode-plugin/pull/312)
* [Overhaul syntax highlighting](https://github.com/godotengine/godot-vscode-plugin/pull/342)
* [Mention that the Godot editor must be running in connection error message](https://github.com/godotengine/godot-vscode-plugin/pull/358)
* [Fix automatic indentation on line breaks not working as expected](https://github.com/godotengine/godot-vscode-plugin/pull/344)
### 1.2.0
* [Add support for setting language-server-host](https://github.com/godotengine/godot-vscode-plugin/pull/297)
* [Improve syntax highlighting](https://github.com/godotengine/godot-vscode-plugin/pull/330)

View File

@@ -3,7 +3,7 @@
A complete set of tools to code games with
[Godot Engine](http://www.godotengine.org/) in Visual Studio Code.
**IMPORTANT NOTE:** Versions 1.0.0 and later of this plugin only support
**IMPORTANT NOTE:** Versions 1.0.0 and later of this extension only support
Godot 3.2 or later.
## Features
@@ -25,6 +25,20 @@ experience as comfortable as possible:
![Showing the documentation on hover feature](img/godot-tools.png)
## Download
- [Visual Studio Marketplace **(recommended)**](https://marketplace.visualstudio.com/items?itemName=geequlim.godot-tools)
- Stable release, with support for automatic updates.
- [GitHub Releases](https://github.com/godotengine/godot-vscode-plugin/releases)
- Stable release, but no automatic updates. Can be useful if you need to install an older version of the extension.
- [Development build (follows the `master` branch)](https://nightly.link/godotengine/godot-vscode-plugin/workflows/ci/master/godot-tools.zip)
- Development build. Contains new features and fixes not available in stable releases, but may be unstable.
- Extract the ZIP archive before installing (it contains the `.vsix` file inside).
To install from GitHub Releases or a development build,
see [Install from a VSIX](https://code.visualstudio.com/docs/editor/extension-marketplace#_install-from-a-vsix)
in the Visual Studio Code documentation.
## Available commands
The extension adds a few entries to the VS Code Command Palette under "Godot Tools":

View File

@@ -0,0 +1,24 @@
{
"comments": {
"lineComment": ";"
},
"brackets": [
["(", ")"],
["[", "]"],
["{", "}"]
],
"autoClosingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
],
"surroundingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
]
}

View File

@@ -1,36 +1,86 @@
{
"comments": {
"lineComment": "#",
"blockComment": ["\"\"\"", "\"\"\""]
"blockComment": [
"\"\"\"",
"\"\"\""
]
},
"brackets": [
["(", ")"],
["[", "]"],
["{", "}"]
[
"(",
")"
],
[
"[",
"]"
],
[
"{",
"}"
]
],
"autoClosingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
[
"'",
"'"
],
[
"\"",
"\""
],
[
"(",
")"
],
[
"[",
"]"
],
[
"{",
"}"
]
],
"surroundingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
[
"'",
"'"
],
[
"\"",
"\""
],
[
"(",
")"
],
[
"[",
"]"
],
[
"{",
"}"
]
],
"indentationRules": {
"increaseIndentPattern": "^\\s*((class|static func|func|else|elif|for|if|match|while|enum)|(.*\\sdo\\b))\\b[^\\{;]*$",
"decreaseIndentPattern": "^\\s*([}\\]]([,)]?\\s*(#|$)|\\.[a-zA-Z_]\\w*\\b)|(else|elif)\\b)"
},
"folding": {
"offSide": true,
"markers": {
"start": "^\\s*#\\s*region\\b",
"end": "^\\s*#\\s*endregion\\b"
}
}
"offSide": true,
"markers": {
"start": "^\\s*#\\s*region\\b",
"end": "^\\s*#\\s*endregion\\b"
}
},
"onEnterRules": [
{
"beforeText": "^\\s*$",
"action": {
"indent": "none"
}
}
]
}

View File

@@ -0,0 +1,25 @@
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
},
"brackets": [
["(", ")"],
["[", "]"],
["{", "}"]
],
"autoClosingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
],
"surroundingPairs": [
["'", "'"],
["\"", "\""],
["(", ")"],
["[", "]"],
["{", "}"]
]
}

1863
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "godot-tools",
"displayName": "godot-tools",
"icon": "icon.png",
"version": "1.2.0",
"version": "1.3.0",
"description": "Tools for game development with Godot Engine and GDScript",
"repository": {
"type": "git",
@@ -27,6 +27,8 @@
"activationEvents": [
"workspaceContains:project.godot",
"onLanguage:gdscript",
"onLanguage:gdshader",
"onLanguage:gdresource",
"onDebugResolve:godot"
],
"main": "./out/extension.js",
@@ -47,6 +49,10 @@
"command": "godot-tool.run_project",
"title": "Godot Tools: Run workspace as Godot project"
},
{
"command": "godot-tool.run_project_debug",
"title": "Godot Tools: Run workspace as Godot project with visible collision shapes and navigation meshes"
},
{
"command": "godot-tool.list_native_classes",
"title": "Godot Tools: List native classes of godot"
@@ -86,6 +92,14 @@
{
"command": "godot-tool.set_scene_file",
"title": "Set as Scene File"
},
{
"command": "godot-tool.copy_resource_path_context",
"title": "Copy Resource Path"
},
{
"command": "godot-tool.copy_resource_path",
"title": "Godot Tools: Copy Resource Path"
}
],
"configuration": {
@@ -126,6 +140,31 @@
"type": "string",
"default": "",
"description": "The scene file to run"
},
"godot_tools.reconnect_automatically": {
"type": "boolean",
"default": true,
"description": "Whether the plugin should attempt to reconnect"
},
"godot_tools.reconnect_cooldown": {
"type": "number",
"default": 3000,
"description": "The number of milliseconds to wait before attempting to reconnect"
},
"godot_tools.reconnect_attempts": {
"type": "number",
"default": 10,
"description": "How many times the client will attempt to reconnect"
},
"godot_tools.force_visible_collision_shapes": {
"type": "boolean",
"default": false,
"description": "Force the project to run with visible collision shapes"
},
"godot_tools.force_visible_nav_mesh": {
"type": "boolean",
"default": false,
"description": "Force the project to run with visible navigation meshes"
}
}
},
@@ -142,16 +181,30 @@
"configuration": "./configurations/gdscript-configuration.json"
},
{
"id": "properties",
"id": "gdresource",
"aliases": [
"GDResource",
"gdresource"
],
"extensions": [
"cfg",
"godot",
"tres",
"tscn",
"godot",
"import",
"gdns",
"gdnlib",
"import"
]
"gdnlib"
],
"configuration": "./configurations/gdresource-configuration.json"
},
{
"id": "gdshader",
"aliases": [
"gdshader"
],
"extensions": [
".gdshader"
],
"configuration": "./configurations/gdshader-configuration.json"
}
],
"grammars": [
@@ -159,6 +212,16 @@
"language": "gdscript",
"scopeName": "source.gdscript",
"path": "./syntaxes/GDScript.tmLanguage.json"
},
{
"language": "gdresource",
"scopeName": "source.gdresource",
"path": "./syntaxes/GDResource.tmLanguage.json"
},
{
"language": "gdshader",
"scopeName": "source.gdshader",
"path": "./syntaxes/GDShader.tmLanguage.json"
}
],
"snippets": [
@@ -296,6 +359,16 @@
{
"command": "godot-tool.set_scene_file",
"group": "2_workspace"
},
{
"command": "godot-tool.copy_resource_path_context",
"group": "6_copypath"
}
],
"editor/title/context": [
{
"command": "godot-tool.copy_resource_path_context",
"group": "1_godot"
}
]
}
@@ -314,6 +387,7 @@
"dependencies": {
"await-notify": "^1.0.1",
"global": "^4.4.0",
"klaw": "^4.0.1",
"marked": "^4.0.11",
"net": "^1.0.2",
"terminate": "^2.5.0",

View File

@@ -98,7 +98,17 @@ export class ServerController {
if (launch_instance) {
let godot_path: string = utils.get_configuration("editor_path", "godot");
let executable_line = `"${godot_path}" --path "${project_path}" --remote-debug ${address}:${port}`;
const force_visible_collision_shapes = utils.get_configuration("force_visible_collision_shapes", false);
const force_visible_nav_mesh = utils.get_configuration("force_visible_nav_mesh", false);
let visible_collision_shapes_param = "";
let visible_nav_mesh_param = "";
if (force_visible_collision_shapes) {
visible_collision_shapes_param = " --debug-collisions";
}
if (force_visible_nav_mesh) {
visible_nav_mesh_param = " --debug-navigation";
}
let executable_line = `"${godot_path}" --path "${project_path}" --remote-debug ${address}:${port}""${visible_collision_shapes_param}""${visible_nav_mesh_param}`;
if (launch_scene) {
let filename = "";
if (scene_file) {
@@ -266,9 +276,8 @@ export class ServerController {
if (breakpoints.length > 0) {
output += " --breakpoints ";
breakpoints.forEach((bp, i) => {
output += `${this.breakpoint_path(project_path, bp.file)}:${bp.line}${
i < breakpoints.length - 1 ? "," : ""
}`;
output += `${this.breakpoint_path(project_path, bp.file)}:${bp.line}${i < breakpoints.length - 1 ? "," : ""
}`;
});
}

View File

@@ -11,7 +11,7 @@ export function activate(context: ExtensionContext) {
}
export function deactivate(): Thenable<void> {
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
tools.deactivate();
resolve();
});

View File

@@ -8,11 +8,15 @@ const CONFIG_CONTAINER = "godot_tools";
const TOOL_NAME = "GodotTools";
export class GodotTools {
private reconnection_attempts = 0;
private context: vscode.ExtensionContext;
private client: GDScriptLanguageClient = null;
// deprecated, need to replace with "vscode.workspace.workspaceFolders", but
// that's an array and not a single value
private workspace_dir = vscode.workspace.rootPath;
private project_file = "project.godot";
private project_file_name = "project.godot";
private project_file = "";
private project_dir = ""
private connection_status: vscode.StatusBarItem = null;
constructor(p_context: vscode.ExtensionContext) {
@@ -20,41 +24,59 @@ export class GodotTools {
this.client = new GDScriptLanguageClient(p_context);
this.client.watch_status(this.on_client_status_changed.bind(this));
this.connection_status = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
setInterval(() => {
this.retry_callback();
}, get_configuration("reconnect_cooldown", 3000));
}
public activate() {
vscode.commands.registerCommand("godot-tool.open_editor", ()=>{
this.open_workspace_with_editor("-e").catch(err=>vscode.window.showErrorMessage(err));
vscode.commands.registerCommand("godot-tool.open_editor", () => {
this.open_workspace_with_editor("-e").catch(err => vscode.window.showErrorMessage(err));
});
vscode.commands.registerCommand("godot-tool.run_project", ()=>{
this.open_workspace_with_editor().catch(err=>vscode.window.showErrorMessage(err));
vscode.commands.registerCommand("godot-tool.run_project", () => {
this.open_workspace_with_editor().catch(err => vscode.window.showErrorMessage(err));
});
vscode.commands.registerCommand("godot-tool.run_project_debug", () => {
this.open_workspace_with_editor("--debug-collisions --debug-navigation").catch(err => vscode.window.showErrorMessage(err));
});
vscode.commands.registerCommand("godot-tool.check_status", this.check_client_status.bind(this));
vscode.commands.registerCommand("godot-tool.set_scene_file", this.set_scene_file.bind(this));
vscode.commands.registerCommand("godot-tool.copy_resource_path_context", this.copy_resource_path.bind(this));
vscode.commands.registerCommand("godot-tool.copy_resource_path", this.copy_resource_path.bind(this));
this.connection_status.text = "$(sync) Initializing";
this.connection_status.command = "godot-tool.check_status";
this.connection_status.show();
// TODO: maybe cache this result somehow
const klaw = require('klaw');
klaw(this.workspace_dir)
.on('data', item => {
if (path.basename(item.path) == this.project_file_name) {
this.project_dir = path.dirname(item.path);
this.project_file = item.path;
}
});
this.reconnection_attempts = 0;
this.client.connect_to_server();
}
public deactivate() {
this.client.stop();
}
private open_workspace_with_editor(params = "") {
return new Promise<void>((resolve, reject) => {
let valid = false;
if (this.workspace_dir) {
let cfg = path.join(this.workspace_dir, this.project_file);
if (this.project_dir) {
let cfg = this.project_file;
valid = (fs.existsSync(cfg) && fs.statSync(cfg).isFile());
}
if (valid) {
this.run_editor(`--path "${this.workspace_dir}" ${params}`).then(()=>resolve()).catch(err=>{
this.run_editor(`--path "${this.project_dir}" ${params}`).then(() => resolve()).catch(err => {
reject(err);
});
} else {
@@ -63,6 +85,22 @@ export class GodotTools {
});
}
private copy_resource_path(uri: vscode.Uri) {
if (!this.project_dir) {
return;
}
if (!uri) {
uri = vscode.window.activeTextEditor.document.uri
}
let relative_path = path.normalize(path.relative(this.project_dir, uri.fsPath));
relative_path = relative_path.split(path.sep).join(path.posix.sep);
relative_path = 'res://' + relative_path;
vscode.env.clipboard.writeText(relative_path);
}
private set_scene_file(uri: vscode.Uri) {
let right_clicked_scene_path = uri.fsPath
let scene_config = get_configuration("scene_file_config");
@@ -72,11 +110,10 @@ export class GodotTools {
else {
scene_config = right_clicked_scene_path
}
set_configuration("scene_file_config", scene_config);
}
private run_editor(params = "") {
return new Promise<void>((resolve, reject) => {
@@ -84,13 +121,13 @@ export class GodotTools {
const is_powershell_path = (path?: string) => {
const POWERSHELL = "powershell.exe";
const POWERSHELL_CORE = "pwsh.exe";
return path && (path.endsWith(POWERSHELL) || path.endsWith(POWERSHELL_CORE));
return path && (path.endsWith(POWERSHELL) || path.endsWith(POWERSHELL_CORE));
};
const escape_command = (cmd: string) => {
const cmdEsc = `"${cmd}"`;
if (process.platform === "win32") {
const shell_plugin = vscode.workspace.getConfiguration("terminal.integrated.shell");
if (shell_plugin) {
const shell = shell_plugin.get<string>("windows");
if (shell) {
@@ -101,7 +138,7 @@ export class GodotTools {
}
}
}
const POWERSHELL_SOURCE = "PowerShell"
const default_profile = vscode.workspace.getConfiguration("terminal.integrated.defaultProfile");
if (default_profile) {
@@ -111,7 +148,7 @@ export class GodotTools {
return `&${cmdEsc}`;
}
const profiles = vscode.workspace.getConfiguration("terminal.integrated.profiles.windows");
const profile = profiles.get<{source?: string, path?: string}>(profile_name);
const profile = profiles.get<{ source?: string, path?: string }>(profile_name);
if (profile) {
if (POWERSHELL_SOURCE === profile.source || is_powershell_path(profile.path)) {
return `&${cmdEsc}`;
@@ -143,19 +180,19 @@ export class GodotTools {
editorPath = editorPath.replace("${workspaceRoot}", this.workspace_dir);
if (!fs.existsSync(editorPath) || !fs.statSync(editorPath).isFile()) {
vscode.window.showOpenDialog({
openLabel: "Run",
filters: process.platform === "win32" ? {"Godot Editor Binary": ["exe", "EXE"]} : undefined
}).then((uris: vscode.Uri[])=> {
if (!uris) {
return;
}
let path = uris[0].fsPath;
if (!fs.existsSync(path) || !fs.statSync(path).isFile()) {
reject("Invalid editor path to run the project");
} else {
run_godot(path, params);
set_configuration("editor_path", path);
}
openLabel: "Run",
filters: process.platform === "win32" ? { "Godot Editor Binary": ["exe", "EXE"] } : undefined
}).then((uris: vscode.Uri[]) => {
if (!uris) {
return;
}
let path = uris[0].fsPath;
if (!fs.existsSync(path) || !fs.statSync(path).isFile()) {
reject("Invalid editor path to run the project");
} else {
run_godot(path, params);
set_configuration("editor_path", path);
}
});
} else {
run_godot(editorPath, params);
@@ -188,6 +225,7 @@ export class GodotTools {
this.connection_status.tooltip = `Connecting to the GDScript language server at ${host}:${port}`;
break;
case ClientStatus.CONNECTED:
this.retry = false;
this.connection_status.text = `$(check) Connected`;
this.connection_status.tooltip = `Connected to the GDScript language server.`;
if (!this.client.started) {
@@ -195,26 +233,55 @@ export class GodotTools {
}
break;
case ClientStatus.DISCONNECTED:
this.connection_status.text = `$(x) Disconnected`;
this.connection_status.tooltip = `Disconnected from the GDScript language server.`;
// retry
this.retry_connect_client();
if (this.retry) {
this.connection_status.text = `$(sync) Connecting ` + this.reconnection_attempts;
this.connection_status.tooltip = `Connecting to the GDScript language server...`;
} else {
this.connection_status.text = `$(x) Disconnected`;
this.connection_status.tooltip = `Disconnected from the GDScript language server.`;
}
this.retry = true;
break;
default:
break;
}
}
private retry = false;
private retry_callback() {
if (this.retry) {
this.retry_connect_client();
}
}
private retry_connect_client() {
const auto_retry = get_configuration("reconnect_automatically", true);
const max_attempts = get_configuration("reconnect_attempts", 10);
if (auto_retry && this.reconnection_attempts <= max_attempts) {
this.reconnection_attempts++;
this.client.connect_to_server();
this.connection_status.text = `Connecting ` + this.reconnection_attempts;
this.retry = true;
return;
}
this.retry = false
this.connection_status.text = `$(x) Disconnected`;
this.connection_status.tooltip = `Disconnected from the GDScript language server.`;
let host = get_configuration("gdscript_lsp_server_host", "localhost");
let port = get_configuration("gdscript_lsp_server_port", 6008);
vscode.window.showErrorMessage(`Couldn't connect to the GDScript language server at ${host}:${port}`, 'Open Godot Editor', 'Retry', 'Ignore').then(item=>{
let message = `Couldn't connect to the GDScript language server at ${host}:${port}. Is the Godot editor running?`;
vscode.window.showErrorMessage(message, 'Open Godot Editor', 'Retry', 'Ignore').then(item => {
if (item == 'Retry') {
this.reconnection_attempts = 0;
this.client.connect_to_server();
} else if (item == 'Open Godot Editor') {
this.client.status = ClientStatus.PENDING;
this.open_workspace_with_editor("-e").then(()=>{
setTimeout(()=>{
this.open_workspace_with_editor("-e").then(() => {
setTimeout(() => {
this.reconnection_attempts = 0;
this.client.connect_to_server();
}, 10 * 1000);
});

View File

@@ -0,0 +1,4 @@
{
"useTabs": false,
"tabWidth": 4
}

View File

@@ -0,0 +1,329 @@
{
"version": "v0.6.0",
"scopeName": "source.gdresource",
"uuid": "e076faa2-3c52-42fa-a8e6-9a7c453c1a5b",
"information_for_contributors": [
"aster: galaster@foxmail.com"
],
"patterns": [
{
"include": "#embedded_shader"
},
{
"include": "#embedded_gdscript"
},
{
"include": "#comment"
},
{
"include": "#heading"
},
{
"include": "#key_value"
}
],
"repository": {
"comment": {
"captures": {
"1": {
"name": "punctuation.definition.comment.gdresource"
}
},
"match": "(;).*$\\n?",
"name": "comment.line.gdresource"
},
"embedded_shader": {
"name": "meta.embedded.block.gdshader",
"begin": "(code) = \"",
"end": "\"",
"beginCaptures": {
"1": {
"name": "variable.other.property.gdresource"
}
},
"patterns": [
{
"include": "source.gdshader"
}
]
},
"embedded_gdscript": {
"comment": "meta.embedded.block.gdscript",
"begin": "(script/source) = \"",
"end": "\"",
"beginCaptures": {
"1": {
"name": "variable.other.property.gdresource"
}
},
"patterns": [
{
"include": "source.gdscript"
}
]
},
"heading": {
"begin": "\\[([a-z_]*)\\s?",
"beginCaptures": {
"1": {
"name": "keyword.control.gdresource"
}
},
"end": "\\]",
"patterns": [
{
"include": "#heading_properties"
},
{
"include": "#data"
}
]
},
"heading_properties": {
"patterns": [
{
"name": "invalid.deprecated.noValue.gdresource",
"match": "(\\s*[A-Za-z_\\-][A-Za-z0-9_\\-]*\\s*=)(?=\\s*$)"
},
{
"begin": "\\s*([A-Za-z_-][^\\s]*|\".+\"|'.+'|[0-9]+)\\s*(=)\\s*",
"beginCaptures": {
"1": {
"name": "variable.other.property.gdresource"
},
"2": {
"name": "punctuation.definition.keyValue.gdresource"
}
},
"end": "($|(?==)|\\,?|\\s*(?=\\}))",
"patterns": [
{
"include": "#data"
}
]
}
]
},
"key_value": {
"patterns": [
{
"name": "invalid.deprecated.noValue.gdresource",
"match": "(\\s*[A-Za-z_\\-][A-Za-z0-9_\\-]*\\s*=)(?=\\s*$)"
},
{
"begin": "\\s*([A-Za-z_-][^\\s]*|\".+\"|'.+'|[0-9]+)\\s*(=)\\s*",
"beginCaptures": {
"1": {
"name": "variable.other.property.gdresource"
},
"2": {
"name": "punctuation.definition.keyValue.gdresource"
}
},
"end": "($|(?==)|\\,|\\s*(?=\\}))",
"patterns": [
{
"include": "#data"
}
]
}
]
},
"data": {
"patterns": [
{
"include": "#comment"
},
{
"begin": "(?<!\\w)(\\{)\\s*",
"beginCaptures": {
"1": {
"name": "punctuation.definition.table.inline.gdresource"
}
},
"end": "\\s*(\\})(?!\\w)",
"endCaptures": {
"1": {
"name": "punctuation.definition.table.inline.gdresource"
}
},
"patterns": [
{
"include": "#key_value"
},
{
"include": "#data"
}
]
},
{
"begin": "(?<!\\w)(\\[)\\s*",
"beginCaptures": {
"1": {
"name": "punctuation.definition.array.gdresource"
}
},
"end": "\\s*(\\])(?!\\w)",
"endCaptures": {
"1": {
"name": "punctuation.definition.array.gdresource"
}
},
"patterns": [
{
"include": "#data"
}
]
},
{
"name": "string.quoted.triple.basic.block.gdresource",
"begin": "\"\"\"",
"end": "\"\"\"",
"patterns": [
{
"match": "\\\\([btnfr\"\\\\\\n/ ]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})",
"name": "constant.character.escape.gdresource"
},
{
"match": "\\\\[^btnfr/\"\\\\\\n]",
"name": "invalid.illegal.escape.gdresource"
}
]
},
{
"name": "support.function.any-method.gdresource",
"match": "\"res:\\/\\/[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\""
},
{
"name": "support.class.library.gdresource",
"match": "(?<=type=)\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\""
},
{
"name": "constant.character.escape.gdresource",
"match": "(?<=NodePath\\(|parent=|name=)\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\""
},
{
"name": "string.quoted.double.basic.line.gdresource",
"match": "\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"",
"patterns": [
{
"match": "\\\\([btnfr\"\\\\\\n/ ]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})",
"name": "constant.character.escape.gdresource"
},
{
"match": "\\\\[^btnfr/\"\\\\\\n]",
"name": "invalid.illegal.escape.gdresource"
}
]
},
{
"name": "invalid.illegal.escape.gdresource",
"begin": "'''",
"end": "'''"
},
{
"name": "string.quoted.single.literal.line.gdresource",
"match": "'.*?'"
},
{
"match": "(?<!\\w)(true|false)(?!\\w)",
"captures": {
"1": {
"name": "constant.language.gdresource"
}
}
},
{
"match": "(?<!\\w)([\\+\\-]?(0|([1-9](([0-9]|_[0-9])+)?))(?:(?:\\.(0|([1-9](([0-9]|_[0-9])+)?)))?[eE][\\+\\-]?[1-9]_?[0-9]*|(?:\\.[0-9_]*)))(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.float.gdresource"
}
}
},
{
"match": "(?<!\\w)((?:[\\+\\-]?(0|([1-9](([0-9]|_[0-9])+)?))))(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.integer.gdresource"
}
}
},
{
"match": "(?<!\\w)([\\+\\-]?inf)(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.inf.gdresource"
}
}
},
{
"match": "(?<!\\w)([\\+\\-]?nan)(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.nan.gdresource"
}
}
},
{
"match": "(?<!\\w)((?:0x(([0-9a-fA-F](([0-9a-fA-F]|_[0-9a-fA-F])+)?))))(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.hex.gdresource"
}
}
},
{
"match": "(?<!\\w)(0o[0-7](_?[0-7])*)(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.oct.gdresource"
}
}
},
{
"match": "(?<!\\w)(0b[01](_?[01])*)(?!\\w)",
"captures": {
"1": {
"name": "constant.numeric.bin.gdresource"
}
}
},
{
"begin": "(?<!\\w)(Vector2|Vector2i|Vector3|Vector3i|Color|Rect2|Rect2i|Array|Basis|Dictionary|Plane|Quat|RID|Rect3|Transform|Transform2D|Transform3D|AABB|String|Color|NodePath|Object|PoolByteArray|PoolIntArray|PoolRealArray|PoolStringArray|PoolVector2Array|PoolVector3Array|PoolColorArray|bool|int|float|StringName|Quaternion|PackedByteArray|PackedInt32Array|PackedInt64Array|PackedFloat32Array|PackedFloat64Array|PackedStringArray|PackedVector2Array|PackedVector2iArray|PackedVector3Array|PackedVector3iArray|PackedColorArray)(\\()\\s?",
"beginCaptures": {
"1": {
"name": "support.class.library.gdresource"
}
},
"end": "\\s?(\\))",
"patterns": [
{
"include": "#key_value"
},
{
"include": "#data"
}
]
},
{
"begin": "(?<!\\w)(ExtResource|SubResource)(\\()\\s?",
"beginCaptures": {
"1": {
"name": "keyword.control.gdresource"
}
},
"end": "\\s?(\\))",
"patterns": [
{
"include": "#key_value"
},
{
"include": "#data"
}
]
}
]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
{
"version": "v0.1.0",
"scopeName": "source.gdshader",
"uuid": "3a95d25d-688b-481f-a581-eee47f00e5ca",
"patterns": [
{
"include": "#shader_type"
},
{
"include": "source.glsl"
}
],
"repository": {
"shader_type": {
"match": "(shader_type)",
"name": "storage.type.glsl"
}
}
}

View File

@@ -0,0 +1,202 @@
extends Node
class_name TestClass
# ******************************************************************************
var a
remote var b = 10.0
remotesync var c := 20
master var d :int = 30
puppet var e :int
signal sig_a
signal sig_b()
signal sig_c(param1, param2)
# signal sig_d(param1: int, param2: Dictionary)
# signal sig_e(
# param1: int, # first param
# param2: Dictionary,
# )
# ------------------------------------------------------------------------------
var f = 40 setget set_f
func set_f(value):
pass
var g:int setget set_g, get_g
func set_g(value: int=0) -> void:
pass
var h:float = 1.0 setget set_h, get_h
func set_h(value: int=0) -> void:
pass
func get_g() -> int:
return 0
# ------------------------------------------------------------------------------
func func_a(param1, param2, param3):
self.test()
$Node.get_node('Foo')
$Node.has_node('Foo')
$Node.find_node('Foo')
$Node.get_node_or_null('Foo')
print($Node.has_node('Foo'))
print(NodePath('Foo'))
print(NodePath("Foo"))
pass
func func_b(param1, param2=func_a(10, 1.0, 'test')) -> void:
pass
func func_b1(param1 = false, param2: bool = false, param3 := false):
pass
func func_b2(param1 = 10, param2: int = 100, param3 := 1000):
pass
func func_b3(param1 = 1.0, param2: float = 10.0, param3 := 100.001):
pass
func func_b4(param1 = 'foo', param2: String = 'bar', param3 := 'foobar'):
pass
func func_b5(
param1 = 'foo', # comment
param2: String = 'bar',
param3: float = 3.14159,
param4:='foobar',
param5:=1000,
param6:=[],
param7:={},
param8:=func_a(),
param9:=Vector2(0, 1),
param10:=Vector2(0, 0),
param11:=Color(1, 1, 1, 0.5),
param12:=NodePath('Foo')
) -> void:
pass
var dict = {
a = 0,
b = 0.0,
c = 'test',
}
func func_c(
param1: int = 10,
param2 := 1.0,
param3: String = 'string',
param4 := {a=0, b=0.0, c='test'}
):
pass
# ------------------------------------------------------------------------------
var q = "double quotes"
var r = 'single quotes'
var s = """
triple double quotes
"""
var t = '''triple single quotes''' # this should be red because it's invalid
# ------------------------------------------------------------------------------
var IS_CONSTANT
var not_CONSTANT
var ALSO_NOT_constant
var CONSTANT_not
# ------------------------------------------------------------------------------
onready var node_a = $Child
onready var node_b = $Child/GrandChild
onready var node_bb = $Child/GrandChild/GreatGrandChild
onready var node_bbb = $Child/GrandChild/GreatGrandChild/GreatGreatGrandChild
onready var node_c = $"../Sibling"
onready var node_cc = $'../Sibling'
onready var node_d = $'..' # parent
onready var node_e = $"../.." # grandparent
onready var node_f = get_node('Child')
onready var node_g = get_node("Child/GrandChild")
onready var node_h = get_node("../Sibling")
if has_node('Child') and get_node('Child').has_node('GrandChild'):
pass
onready var node_i = $badlyNamedChild
onready var node_j = $badlyNamedChild/badly_named_grandchild
var node_path_a = NodePath("Child")
var node_path_b = NodePath('Child/GrandChild')
var node_path_c = NodePath('../Sibling')
# ------------------------------------------------------------------------------
var _script = GDScript.new()
var directions = [
Vector2.UP,
Vector2.DOWN,
Vector2.LEFT,
Vector2.RIGHT,
]
enum test_enum {
VALUE_1,
VALUE_2,
VALUE_3,
}
export(test_enum) var enum_variable = test_enum.VALUE_1
# ------------------------------------------------------------------------------
func if_test():
var some_bool := true
while some_bool:
pass
while (some_bool):
pass
if some_bool:
return some_bool
if (some_bool):
return (some_bool)
elif !some_bool:
return !some_bool
elif !(some_bool):
return !(some_bool)
elif (some_bool):
pass
else:
pass
# ------------------------------------------------------------------------------
class InnerClass:
var some_var = 100
var dict = {
'key_a': some_var,
'key_b': str(10),
key_c = some_var,
key_d = int('10'),
key_e = Color(1, 1, 1),
key_f = Vector2(10, -10)
}
func _ready():
if true and true:
pass
elif false:
while true:
pass
else:
pass
pass