From 3e78b8fdad953a14c9a4f815295dfc6ed75d409f Mon Sep 17 00:00:00 2001 From: Slin Lee Date: Tue, 22 Mar 2022 09:38:49 -0700 Subject: [PATCH] Add syntax highlighting for Solidity (#1854) --- book/src/generated/lang-support.md | 2 +- languages.toml | 5 +- runtime/queries/solidity/highlights.scm | 189 ++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 runtime/queries/solidity/highlights.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 83ea8dac..03a96952 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -54,7 +54,7 @@ | ruby | ✓ | | ✓ | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | -| solidity | | | | `solc` | +| solidity | ✓ | | | `solc` | | svelte | ✓ | | ✓ | `svelteserver` | | tablegen | ✓ | ✓ | ✓ | | | toml | ✓ | | | | diff --git a/languages.toml b/languages.toml index f81b0c4e..265f462d 100644 --- a/languages.toml +++ b/languages.toml @@ -992,10 +992,13 @@ source = { git = "https://github.com/milisims/tree-sitter-org", rev = "1c3eb533a [[language]] name = "solidity" scope = "source.sol" -injection-regex = "sol" +injection-regex = "^(sol|solidity)$" file-types = ["sol"] roots = [] comment-token = "//" indent = { tab-width = 4, unit = " " } language-server = { command = "solc", args = ["--lsp"] } +[[grammar]] +name = "solidity" +source = { git = "https://github.com/slinlee/tree-sitter-solidity", rev = "f3a002274744e859bf64cf3524985f8c31ea84fd" } diff --git a/runtime/queries/solidity/highlights.scm b/runtime/queries/solidity/highlights.scm new file mode 100644 index 00000000..61c89ac8 --- /dev/null +++ b/runtime/queries/solidity/highlights.scm @@ -0,0 +1,189 @@ +(comment) @comment + +; Pragma +(pragma_directive) @tag +(solidity_version_comparison_operator ">=" @tag) +(solidity_version_comparison_operator "<=" @tag) +(solidity_version_comparison_operator "=" @tag) +(solidity_version_comparison_operator "~" @tag) +(solidity_version_comparison_operator "^" @tag) + + +; Literals +[ + (string) + (hex_string_literal) + (unicode_string_literal) + (yul_string_literal) +] @string +[ + (number_literal) + (yul_decimal_number) + (yul_hex_number) +] @constant.numeric +[ + (true) + (false) +] @constant.builtin + + +; Type +(type_name) @type +(primitive_type) @type +(struct_declaration struct_name: (identifier) @type) +(enum_declaration enum_type_name: (identifier) @type) +; Color payable in payable address conversion as type and not as keyword +(payable_conversion_expression "payable" @type) +(emit_statement . (identifier) @type) +; Handles ContractA, ContractB in function foo() override(ContractA, contractB) {} +(override_specifier (identifier) @type) +; Ensures that delimiters in mapping( ... => .. ) are not colored like types +(type_name "(" @punctuation.bracket "=>" @punctuation.delimiter ")" @punctuation.bracket) + + + +; Functions and parameters + +(function_definition + function_name: (identifier) @function) +(modifier_definition + name: (identifier) @function) +(yul_evm_builtin) @function.builtin + +; Use contructor coloring for special functions +(constructor_definition "constructor" @constructor) +(fallback_receive_definition "receive" @constructor) +(fallback_receive_definition "fallback" @constructor) + +(modifier_invocation (identifier) @function) + +; Handles expressions like structVariable.g(); +(call_expression . (member_expression (property_identifier) @function.method)) + +; Handles expressions like g(); +(call_expression . (identifier) @function) + +; Function parameters +(event_paramater name: (identifier) @variable.parameter) +(function_definition + function_name: (identifier) @variable.parameter) + +; Yul functions +(yul_function_call function: (yul_identifier) @function) + +; Yul function parameters +(yul_function_definition . (yul_identifier) @function (yul_identifier) @variable.parameter) + +(meta_type_expression "type" @keyword) + +(member_expression (property_identifier) @variable.other.member) +(property_identifier) @variable.other.member +(struct_expression ((identifier) @variable.other.member . ":")) +(enum_value) @variable.other.member + + +; Keywords +[ + "pragma" + "import" + "contract" + "interface" + "library" + "is" + "struct" + "enum" + "event" + "using" + "assembly" + "switch" + "case" + "default" + "break" + "continue" + "if" + "else" + "for" + "while" + "do" + "try" + "catch" + "return" + "emit" + "public" + "internal" + "private" + "external" + "pure" + "view" + "payable" + "modifier" + "returns" + "memory" + "storage" + "calldata" + "function" + "var" + (constant) + (virtual) + (override_specifier) + (yul_leave) +] @keyword + +(import_directive "as" @keyword) +(import_directive "from" @keyword) +(event_paramater "indexed" @keyword) + +; Punctuation + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + + +[ + "." + "," +] @punctuation.delimiter + + +; Operators + +[ + "&&" + "||" + ">>" + ">>>" + "<<" + "&" + "^" + "|" + "+" + "-" + "*" + "/" + "%" + "**" + "<" + "<=" + "==" + "!=" + "!==" + ">=" + ">" + "!" + "~" + "-" + "+" + "delete" + "new" + "++" + "--" +] @operator + +(identifier) @variable +(yul_identifier) @variable