From 78e37e8016b7d653b0c9ba3902f216e3ed8fb9c6 Mon Sep 17 00:00:00 2001 From: Daelon Suzuka Date: Mon, 11 Apr 2022 09:33:16 -0700 Subject: [PATCH] Overhaul syntax highlighting (#342) Co-authored-by: Hugo Locurcio --- configurations/gdresource-configuration.json | 24 + configurations/gdshader-configuration.json | 25 + package.json | 40 +- syntaxes/GDResource.tmLanguage.json | 329 +++++++ syntaxes/GDScript.tmLanguage.json | 898 ++++++++++++------- syntaxes/GDShader.tmLanguage.json | 19 + syntaxes/examples/gdscript1.gd | 143 +++ 7 files changed, 1130 insertions(+), 348 deletions(-) create mode 100644 configurations/gdresource-configuration.json create mode 100644 configurations/gdshader-configuration.json create mode 100644 syntaxes/GDResource.tmLanguage.json create mode 100644 syntaxes/GDShader.tmLanguage.json create mode 100644 syntaxes/examples/gdscript1.gd diff --git a/configurations/gdresource-configuration.json b/configurations/gdresource-configuration.json new file mode 100644 index 0000000..61fbaad --- /dev/null +++ b/configurations/gdresource-configuration.json @@ -0,0 +1,24 @@ +{ + "comments": { + "lineComment": ";" + }, + "brackets": [ + ["(", ")"], + ["[", "]"], + ["{", "}"] + ], + "autoClosingPairs": [ + ["'", "'"], + ["\"", "\""], + ["(", ")"], + ["[", "]"], + ["{", "}"] + ], + "surroundingPairs": [ + ["'", "'"], + ["\"", "\""], + ["(", ")"], + ["[", "]"], + ["{", "}"] + ] +} diff --git a/configurations/gdshader-configuration.json b/configurations/gdshader-configuration.json new file mode 100644 index 0000000..e2fb479 --- /dev/null +++ b/configurations/gdshader-configuration.json @@ -0,0 +1,25 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["(", ")"], + ["[", "]"], + ["{", "}"] + ], + "autoClosingPairs": [ + ["'", "'"], + ["\"", "\""], + ["(", ")"], + ["[", "]"], + ["{", "}"] + ], + "surroundingPairs": [ + ["'", "'"], + ["\"", "\""], + ["(", ")"], + ["[", "]"], + ["{", "}"] + ] +} diff --git a/package.json b/package.json index 5d1f8a2..e5941f5 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,8 @@ "activationEvents": [ "workspaceContains:project.godot", "onLanguage:gdscript", + "onLanguage:gdshader", + "onLanguage:gdresource", "onDebugResolve:godot" ], "main": "./out/extension.js", @@ -171,23 +173,47 @@ "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": [ { "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": [ diff --git a/syntaxes/GDResource.tmLanguage.json b/syntaxes/GDResource.tmLanguage.json new file mode 100644 index 0000000..cb62604 --- /dev/null +++ b/syntaxes/GDResource.tmLanguage.json @@ -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": "(?=|==|<|>|!=", + "name": "keyword.operator.comparison.gdscript" + }, + "arithmetic_op": { + "match": "\\+=|-=|\\*=|/=|%=|&=|\\|=|\\*|/|%|\\+|-|<<|>>|&|\\||\\^|~", + "name": "keyword.operator.arithmetic.gdscript" + }, + "assignment_op": { + "match": "=", + "name": "keyword.operator.assignment.gdscript" + }, + "control_flow": { + "match": "\\b(?i:if|elif|else|for|while|break|continue|pass|return|match|in|yield)\\b", + "name": "keyword.control.gdscript" + }, + "keywords": { + "match": "\\b(?i:class|class_name|extends|is|onready|tool|static|export|setget|const|as|void|enum|preload|assert|breakpoint|rpc|sync|remote|master|puppet|slave|remotesync|mastersync|puppetsync)\\b", + "name": "keyword.language.gdscript" + }, + "letter": { + "match": "\\b(?i:true|false|null)\\b", + "name": "constant.language.gdscript" + }, + "numbers": { + "patterns": [ + { + "match": "\\b(?i:0x\\h*)\\b", + "name": "constant.numeric.integer.hexadecimal.gdscript" + }, + { + "match": "\\b(?i:(\\d+\\.\\d*(e[\\-\\+]?\\d+)?))\\b", + "name": "constant.numeric.float.gdscript" + }, + { + "match": "\\b(?i:(\\.\\d+(e[\\-\\+]?\\d+)?))\\b", + "name": "constant.numeric.float.gdscript" + }, + { + "match": "\\b(?i:(\\d+e[\\-\\+]?\\d+))\\b", + "name": "constant.numeric.float.gdscript" + }, + { + "match": "\\b\\d+\\b", + "name": "constant.numeric.integer.gdscript" + } + ] + }, + "const_def": { + "match": "\\b(?i:(const))\\s+([a-zA-Z_][a-zA-Z_0-9]*)", + "captures": { + "1": { + "name": "storage.type.const.gdscript" + }, + "2": { + "name": "constant.language.gdscript" + } } - ], - "name": "string.quoted.double.gdscript" }, - { - "begin": "'", - "end": "'", - "patterns": [ - { "name": "constant.character.escape.untitled", - "match": "\\\\." + "var_def": { + "match": "\\b(?i:(var))\\s+(?=[a-zA-Z_][a-zA-Z_0-9]*)", + "captures": { + "1": { + "name": "storage.type.var.gdscript" + } } - ], - "name": "string.quoted.single.gdscript" }, - { - "begin": "@\"", - "end": "\"", - "patterns": [ - { "name": "constant.character.escape.untitled", - "match": "\\." + "type_hint": { + "match": "\\:\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*(?=[=\\n]|setget)", + "captures": { + "1": { + "name": "entity.name.type.class.gdscript" + } } - ], - "name": "string.nodepath.gdscript" + }, + "class_def": { + "captures": { + "1": { + "name": "entity.name.type.class.gdscript" + }, + "2": { + "name": "class.other.gdscript" + } + }, + "match": "(?<=^class)\\s+([a-zA-Z_]\\w*)\\s*(?=:)" + }, + "class_new": { + "captures": { + "1": { + "name": "entity.name.type.class.gdscript" + }, + "2": { + "name": "storage.type.new.gdscript" + } + }, + "match": "\\b([a-zA-Z_][a-zA-Z_0-9]*).(new)\\(" + }, + "class_is": { + "captures": { + "1": { + "name": "storage.type.is.gdscript" + }, + "2": { + "name": "entity.name.type.class.gdscript" + } + }, + "match": "\\s+(is)\\s+([a-zA-Z_][a-zA-Z_0-9]*)" + }, + "class_enum": { + "captures": { + "1": { + "name": "entity.name.type.class.gdscript" + }, + "2": { + "name": "constant.language.gdscript" + } + }, + "match": "\\b([A-Z][a-zA-Z_0-9]*)\\.([A-Z_0-9]+)" + }, + "class_name": { + "captures": { + "1": { + "name": "entity.name.type.class.gdscript" + }, + "2": { + "name": "class.other.gdscript" + } + }, + "match": "(?<=class_name)\\s+([a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?)" + }, + "extends": { + "match": "(?<=extends)\\s+[a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?", + "name": "entity.other.inherited-class.gdscript" + }, + "builtin_func": { + "match": "(?)\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", + "captures": { + "1": {}, + "2": { + "name": "entity.name.type.class.gdscript" + } + } + } + ] + }, + "function-declaration": { + "name": "meta.function.gdscript", + "begin": "(?x) \\s*\n (func) \\s+\n ([a-zA-Z_][a-zA-Z_0-9]*) \\s*\n (?=\\()", + "end": "(:|(?=[#'\"\\n]))", + "beginCaptures": { + "1": { + "name": "storage.type.function.gdscript" + }, + "2": { + "name": "entity.name.function.gdscript" + } + }, + "patterns": [ + { + "include": "#parameters" + }, + { + "include": "#line-continuation" + }, + { + "match": "\\s*(\\-\\>)\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", + "captures": { + "1": {}, + "2": { + "name": "entity.name.type.class.gdscript" + } + } + } + ] + }, + "parameters": { + "name": "meta.function.parameters.gdscript", + "begin": "(\\()", + "end": "(\\))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.begin.gdscript" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.gdscript" + } + }, + "patterns": [ + { + "include": "#annotated-parameter" + }, + { + "match": "(?x)\n ([[:alpha:]_]\\w*)\n \\s* (?: (,) | (?=[)#\\n=]))\n", + "captures": { + "1": { + "name": "variable.parameter.function.language.gdscript" + }, + "2": { + "name": "punctuation.separator.parameters.gdscript" + } + } + }, + { + "include": "#comment" + }, + { + "include": "#loose-default" + } + ] + }, + "loose-default": { + "begin": "(=)", + "end": "(,)|(?=\\))", + "beginCaptures": { + "1": { + "name": "keyword.operator.gdscript" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.separator.parameters.gdscript" + } + }, + "patterns": [ + { + "include": "#base_expression" + } + ] + }, + "annotated-parameter": { + "begin": "(?x)\n \\b\n ([[:alpha:]_]\\w*) \\s* (:) \\s* ([[:alpha:]_]\\w*)? \\s* (=)? \\s* ([[:alpha:].0-9\\'\\\"_]*)?\n", + "end": "(,)|(?=\\))", + "beginCaptures": { + "1": { + "name": "variable.parameter.function.language.gdscript" + }, + "2": { + "name": "punctuation.separator.annotation.gdscript" + }, + "3": { + "patterns": [ + { + "include": "#builtin_classes" + }, + { + "include": "#pascal_case_class" + } + ] + }, + "4": { + "name": "keyword.operator.assignment.gdscript" + }, + "5": { + "patterns": [ + { + "include": "#numbers" + }, + { + "include": "#strings" + } + ] + } + }, + "endCaptures": { + "1": { + "name": "punctuation.separator.parameters.gdscript" + } + } + }, + "line-continuation": { + "patterns": [ + { + "match": "(\\\\)\\s*(\\S.*$\\n?)", + "captures": { + "1": { + "name": "punctuation.separator.continuation.line.gdscript" + }, + "2": { + "name": "invalid.illegal.line.continuation.gdscript" + } + } + }, + { + "begin": "(\\\\)\\s*$\\n?", + "end": "(?x)\n (?=^\\s*$)\n |\n (?! (\\s* [rR]? (\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))\n |\n (\\G $) (?# '\\G' is necessary for ST)\n )\n", + "beginCaptures": { + "1": { + "name": "punctuation.separator.continuation.line.gdscript" + } + }, + "patterns": [ + { + "include": "#base_expression" + } + ] + } + ] + }, + "any-method": { + "match": "\\b([A-Za-z_]\\w*)\\b(?=\\s*(?:[(]))", + "name": "support.function.any-method.gdscript" + }, + "any-property": { + "match": "(?<=[^.]\\.)\\b([A-Za-z_]\\w*)\\b(?![(])", + "name": "variable.other.property.gdscript" } - ] - }, - "self": { - "match": "\\bself\\b", - "name": "variable.language.gdscript" - }, - "base_expression": { - "patterns": [ - { "include": "#strings"}, - { "include": "#comment"}, - { "include": "#letter"}, - { "include": "#numbers"}, - { "include": "#line-continuation"} - ] - }, - "logic_op": { - "match": "\\b(and|or|not)\\b", - "name": "keyword.operator.wordlike.gdscript" - }, - "compare_op": { - "match": "<=|>=|==|<|>|!=", - "name": "keyword.operator.comparison.gdscript" - }, - "arithmetic_op": { - "match": "\\+=|-=|\\*=|/=|%=|&=|\\|=|\\*|/|%|\\+|-|<<|>>|&|\\||\\^|~", - "name": "keyword.operator.arithmetic.gdscript" - }, - "assignment_op": { - "match": "=", - "name": "keyword.operator.assignment.gdscript" - }, - - "keywords": { - "patterns": [ - { - "match": "\\b(?i:func|class|class_name|extends|is|in|onready|tool|static|export|setget|const|var|as|void|enum|preload|assert|yield|signal|breakpoint|rpc|sync|remote|master|puppet|slave|remotesync|mastersync|puppetsync|in)\\b", - "name": "keyword.language.gdscript" - }, - { - "match": "\\b(?i:if|elif|else|for|while|break|continue|pass|return|match)\\b", - "name": "keyword.control" - } - ] - }, - "letter": { - "match": "\\b(?i:true|false|null)\\b", - "name": "constant.language.gdscript" - }, - "numbers": { - "patterns": [{ - "match": "\\b(?i:0x\\h*)\\b", - "name": "constant.numeric.integer.hexadecimal.gdscript" - }, - { - "match": "\\b(?i:(\\d+\\.\\d*(e[\\-\\+]?\\d+)?))\\b", - "name": "constant.numeric.float.gdscript" - }, - { - "match": "\\b(?i:(\\.\\d+(e[\\-\\+]?\\d+)?))\\b", - "name": "constant.numeric.float.gdscript" - }, - { - "match": "\\b(?i:(\\d+e[\\-\\+]?\\d+))\\b", - "name": "constant.numeric.float.gdscript" - }, - { - "match": "\\b\\d+\\b", - "name": "constant.numeric.integer.gdscript" - } - ] - }, - "const_def": { - "match": "\\b(?i:(const))\\s+([a-zA-Z_][a-zA-Z_0-9]*)", - "captures": { - "1": { "name": "storage.type.const.gdscript" }, - "2": { "name": "constant.language.gdscript" } - } - }, - "var_def": { - "match": "\\b(?i:(var))\\s+([a-zA-Z_][a-zA-Z_0-9]*)", - "captures": { - "1": { "name": "storage.type.var.gdscript" }, - "2": { "name": "variable.language.gdscript" } - } - }, - "type_declear": { - "match": "\\:\\s*([a-zA-Z_][a-zA-Z_0-9]*)", - "captures": { - "1": { "name": "entity.name.type.class.gdscript" } - } - }, - "function-return-type": { - "match": "\\)\\s*\\-\\>\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", - "captures": { - "1": { "name": "entity.name.type.class.gdscript" } - } - }, - "class_def": { - "captures": { - "1": { "name": "entity.name.type.class.gdscript" }, - "2": { "name": "class.other.gdscript" } - }, - "match": "(?<=^class)\\s+([a-zA-Z_]\\w*)\\s*(?=:)" - }, - "class_new": { - "captures": { - "1": { "name": "entity.name.type.class.gdscript" }, - "2": { "name": "storage.type.new.gdscript" } - }, - "match": "\\b([a-zA-Z_][a-zA-Z_0-9]*).(new)\\(" - }, - "class_is": { - "captures": { - "1": { "name": "storage.type.is.gdscript" }, - "2": { "name": "entity.name.type.class.gdscript" } - }, - "match": "\\s+(is)\\s+([a-zA-Z_][a-zA-Z_0-9]*)" - }, - "class_enum": { - "captures": { - "1": { "name": "entity.name.type.class.gdscript" }, - "2": { "name": "constant.language.gdscript" } - }, - "match": "\\b([A-Z][a-zA-Z_0-9]*)\\.([A-Z_0-9]+)" - }, - "class_name": { - "captures": { - "1": { "name": "entity.name.type.class.gdscript" }, - "2": { "name": "class.other.gdscript" } - }, - "match": "(?<=class_name)\\s+([a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?)" - }, - "extends": { - "match": "(?<=extends)\\s+[a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?", - "name": "entity.other.inherited-class.gdscript" - }, - "builtin_func": { - "match": "(?\"|')((\\.\\.\\/)+|\\/)?)[0-9A-Za-z_ ]+(\\/[0-9A-Za-z_ ]+)*\\k|[0-9A-Za-z_]+(\\/[0-9A-Za-z_]+)*)", - "name": "support.function.builtin.shorthand.gdscript" - }, - "builtin_classes": { - "match": "(? 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(): + pass + +func func_b(param1, param2): + pass + +var dict = { + a = 0, + b = 0.0, + c = 'test', +} + +func func_c( + param1: int = 10, + param11, + param2 := 1.0, + param3: String = 'string', + param4 := {a=0, b=0.0, c='test'}, + ): + pass + +# ------------------------------------------------------------------------------ + +var h = "double quotes" +var i = 'single quotes' +var j = """ +triple double quotes +""" +# var k = '''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 + +# ------------------------------------------------------------------------------ + +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