Repository: JoranHonig/tree-sitter-solidity (language: python)

Issue:
Add highlights.scm and minor grammar change
Hi @JoranHonig ! Thanks for your work.

I tried to use this package to add syntax highlight to neovim [nvim-treesitter/issues/1168](https://github.com/nvim-treesitter/nvim-treesitter/issues/1168) and it turned out that to support that we should add `queries/highlights.scm`. I tinkered a little bit and managed to produce something that I consider to be usable. 
You can see example here https://p13nty.xyz/tree-sitter-solidity-sample.html

There are some minor issues there but that can be changed later. For example, it does not detect built-ins properly. 


In order to do that I had to do one change to grammar (primitive_type is public now) so this piece of code is highlighted properly:
(line 689).
Without it I did not manage to separate e.g. `address` and `salt` from each other.
```solidity
contract C {
    function createDSalted(bytes32 salt, uint arg) public {
        /// This complicated expression just tells you how the address
        /// can be pre-computed. It is just there for illustration.
        /// You actually only need ``new D{salt: salt}(arg)``.
        address predictedAddress = address(bytes20(keccak256(abi.encodePacked(
            byte(0xff),
            address(this),
            salt,
            keccak256(abi.encodePacked(
                type(D).creationCode,
                arg
            ))
        ))));

        D d = new D{salt: salt}(arg);
        require(address(d) == predictedAddress);
    }
}
```

* `queries/highlights.scm` added and `package.json` changed to support
  syntax highlight
* primitive_type node made public for specific highlight case
* typo fixed in grammar definition
* grammar renamed 'Solidity' -> 'solidity' for consistency with other
  packages
* tree-sitter 0.19.4 is used to generate bindings for rust and node (can you publish package please?)
Add highlights.scm and minor grammar change
Hi @JoranHonig ! Thanks for your work.

I tried to use this package to add syntax highlight to neovim [nvim-treesitter/issues/1168](https://github.com/nvim-treesitter/nvim-treesitter/issues/1168) and it turned out that to support that we should add `queries/highlights.scm`. I tinkered a little bit and managed to produce something that I consider to be usable. 
You can see example here https://p13nty.xyz/tree-sitter-solidity-sample.html

There are some minor issues there but that can be changed later. For example, it does not detect built-ins properly. 


In order to do that I had to do one change to grammar (primitive_type is public now) so this piece of code is highlighted properly:
(line 689).
Without it I did not manage to separate e.g. `address` and `salt` from each other.
```solidity
contract C {
    function createDSalted(bytes32 salt, uint arg) public {
        /// This complicated expression just tells you how the address
        /// can be pre-computed. It is just there for illustration.
        /// You actually only need ``new D{salt: salt}(arg)``.
        address predictedAddress = address(bytes20(keccak256(abi.encodePacked(
            byte(0xff),
            address(this),
            salt,
            keccak256(abi.encodePacked(
                type(D).creationCode,
                arg
            ))
        ))));

        D d = new D{salt: salt}(arg);
        require(address(d) == predictedAddress);
    }
}
```

* `queries/highlights.scm` added and `package.json` changed to support
  syntax highlight
* primitive_type node made public for specific highlight case
* typo fixed in grammar definition
* grammar renamed 'Solidity' -> 'solidity' for consistency with other
  packages
* tree-sitter 0.19.4 is used to generate bindings for rust and node (can you publish package please?)


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
new file mode 100644
index 0000000..ca8dd78
--- /dev/null
+++ b/.github/workflows/rust.yml
@@ -0,0 +1,46 @@
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+name: 🦀  Build and Test rust bindings
+
+jobs:
+  build_and_test:
+    name: Rust project
+    runs-on: ubuntu-latest
+    steps:
+      
+      - name: 📥 Download the repository
+        uses: actions/checkout@v2
+      - name: 🦀 Install rust 
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+
+      - name: 📥  Setup node
+        uses: actions/setup-node@v1
+        with:
+          node-version: 12
+
+      - name: 📥  Install js dependencies
+        run: |
+          npm install yarn
+          npm install tree-sitter-cli -g
+          yarn
+
+      - name: 🌲 Generate the parser
+        run: tree-sitter generate
+
+      - name: 🛠 Build rust bindings
+        uses: actions-rs/cargo@v1
+        with:
+          command: build
+          args: --release --all-features
+
+      # Run the tests
+      - name: 🧪 Now run the rust tests
+        uses: actions-rs/cargo@v1
+        with:
+          command: test
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b699932..fe7bcd3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,9 @@ node_modules/
 src/
 .vscode/
 binding.gyp
-index.js
\ No newline at end of file
+index.js
+
+# Rust
+Cargo.lock
+target
+build
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
index 4daa3eb..5a3c546 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,4 +1,8 @@
 corpus
 examples
 build
-script
\ No newline at end of file
+script
+
+# Rust 
+target
+Cargo.lock
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d83c19a
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "tree-sitter-solidity"
+description = "Solidity grammar for the tree-sitter parsing library"
+version = "0.0.2"
+keywords = ["incremental", "parsing", "Solidity"]
+categories = ["parsing", "text-editors"]
+repository = "https://github.com/JoranHonig/tree-sitter-solidity"
+edition = "2018"
+license = "MIT"
+
+build = "bindings/rust/build.rs"
+include = [
+  "bindings/rust/*",
+  "grammar.js",
+  "queries/*",
+  "src/*",
+]
+
+[lib]
+path = "bindings/rust/lib.rs"
+
+[dependencies]
+tree-sitter = "0.19.5"
+
+[build-dependencies]
+cc = "1.0"
diff --git a/bindings/node/binding.cc b/bindings/node/binding.cc
new file mode 100644
index 0000000..51f7e48
--- /dev/null
+++ b/bindings/node/binding.cc
@@ -0,0 +1,28 @@
+#include "tree_sitter/parser.h"
+#include <node.h>
+#include "nan.h"
+
+using namespace v8;
+
+extern "C" TSLanguage * tree_sitter_Solidity();
+
+namespace {
+
+NAN_METHOD(New) {}
+
+void Init(Local<Object> exports, Local<Object> module) {
+  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
+  tpl->SetClassName(Nan::New("Language").ToLocalChecked());
+  tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+  Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
+  Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
+  Nan::SetInternalFieldPointer(instance, 0, tree_sitter_Solidity());
+
+  Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("Solidity").ToLocalChecked());
+  Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
+}
+
+NODE_MODULE(tree_sitter_Solidity_binding, Init)
+
+}  // namespace
diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs
new file mode 100644
index 0000000..c6061f0
--- /dev/null
+++ b/bindings/rust/build.rs
@@ -0,0 +1,40 @@
+fn main() {
+    let src_dir = std::path::Path::new("src");
+
+    let mut c_config = cc::Build::new();
+    c_config.include(&src_dir);
+    c_config
+        .flag_if_supported("-Wno-unused-parameter")
+        .flag_if_supported("-Wno-unused-but-set-variable")
+        .flag_if_supported("-Wno-trigraphs");
+    let parser_path = src_dir.join("parser.c");
+    c_config.file(&parser_path);
+
+    // If your language uses an external scanner written in C,
+    // then include this block of code:
+
+    /*
+    let scanner_path = src_dir.join("scanner.c");
+    c_config.file(&scanner_path);
+    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
+    */
+
+    c_config.compile("parser");
+    println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
+
+    // If your language uses an external scanner written in C++,
+    // then include this block of code:
+
+    /*
+    let mut cpp_config = cc::Build::new();
+    cpp_config.cpp(true);
+    cpp_config.include(&src_dir);
+    cpp_config
+        .flag_if_supported("-Wno-unused-parameter")
+        .flag_if_supported("-Wno-unused-but-set-variable");
+    let scanner_path = src_dir.join("scanner.cc");
+    cpp_config.file(&scanner_path);
+    cpp_config.compile("scanner");
+    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
+    */
+}
diff --git a/bindings/rust/lib.rs b/bindings/rust/lib.rs
new file mode 100644
index 0000000..41411f2
--- /dev/null
+++ b/bindings/rust/lib.rs
@@ -0,0 +1,58 @@
+//! This crate provides Solidity language support for the [tree-sitter][] parsing library.
+//!
+//! The bindings in https://github.com/tree-sitter/tree-sitter-javascript/blob/master/bindings/rust were used
+//! as a template for the tree-sitter-solidity rust bindings.
+//!
+//! Typically, you will use the [language][language func] function to add this language to a
+//! tree-sitter [Parser][], and then use the parser to parse some code:
+//!
+//! ```
+//! let code = "";
+//! let mut parser = tree_sitter::Parser::new();
+//! parser.set_language(tree_sitter_solidity::language()).expect("Error loading Solidity grammar");
+//! let tree = parser.parse(code, None).unwrap();
+//! ```
+//!
+//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
+//! [language func]: fn.language.html
+//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
+//! [tree-sitter]: https://tree-sitter.github.io/
+
+use tree_sitter::Language;
+
+extern "C" {
+    fn tree_sitter_solidity() -> Language;
+}
+
+/// Get the tree-sitter [Language][] for this grammar.
+///
+/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
+pub fn language() -> Language {
+    unsafe { tree_sitter_solidity() }
+}
+
+/// The source of the Solidity tree-sitter grammar description.
+pub const GRAMMAR: &'static str = include_str!("../../grammar.js");
+
+/// The content of the [`node-types.json`][] file for this grammar.
+///
+/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
+pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
+
+// Uncomment these to include any queries that this grammar contains
+
+pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
+// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
+// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
+// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn test_can_load_grammar() {
+        let mut parser = tree_sitter::Parser::new();
+        parser
+            .set_language(super::language())
+            .expect("Error loading Solidity language");
+    }
+}
diff --git a/grammar.js b/grammar.js
index 52bd640..109c7ac 100644
--- a/grammar.js
+++ b/grammar.js
@@ -29,7 +29,7 @@ const PREC = {
 
 // The following is the core grammar for Solidity. It accepts Solidity smart contracts between the versions 0.4.x and 0.7.x.
 module.exports = grammar({
-    name: 'Solidity',
+    name: 'solidity',
 
     // Extras is an array of tokens that is allowed anywhere in the document.
     extras: $ => [
@@ -644,7 +644,7 @@ module.exports = grammar({
             $.binary_expression,
             $.unary_expression,
             $.update_expression,
-            $.call_expresion,
+            $.call_expression,
             // TODO: $.function_call_options_expression,
             $.payable_conversion_expression,
             $.meta_type_expression,
@@ -660,7 +660,7 @@ module.exports = grammar({
             $.member_expression,
             $.array_access,
             $.slice_access,
-            $._primitive_type,
+            $.primitive_type,
             $.assignment_expression,
             $.augmented_assignment_expression,
             $._user_defined_type,
@@ -671,8 +671,8 @@ module.exports = grammar({
             $.new_expression,
         ),
 
-        // TODO: back this up with official dcumentation
-        type_cast_expression: $ => prec.left(seq($._primitive_type, '(', $._expression,')')),
+        // TODO: back this up with official documentation
+        type_cast_expression: $ => prec.left(seq($.primitive_type, '(', $._expression,')')),
 
         ternary_expression: $ => prec.left(seq($._expression, "?", $._expression, ':', $._expression)),
 
@@ -811,7 +811,7 @@ module.exports = grammar({
             field('right', $._expression)
         )),
           
-        call_expresion: $ => seq(
+        call_expression: $ => seq(
             seq($._expression, $._call_arguments),
         ),
 
@@ -819,7 +819,7 @@ module.exports = grammar({
         meta_type_expression: $ => seq('type', '(', $.type_name, ')'),
         
         type_name: $ => prec(0, choice(
-            $._primitive_type,
+            $.primitive_type,
             $._user_defined_type,
             $._mapping,
             $._array_type,
@@ -871,11 +871,11 @@ module.exports = grammar({
         ),
 
         _mapping_key: $ => choice(
-            $._primitive_type,
+            $.primitive_type,
             $._user_defined_type
         ),
 
-        _primitive_type: $ => prec.left(choice(
+        primitive_type: $ => prec.left(choice(
             seq('address', optional('payable')),
             'bool',
             'string',
@@ -1045,4 +1045,4 @@ function optionalDashSeparation(rule) {
         ),
     );  
 }
-  
\ No newline at end of file
+  
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..6591432
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,19 @@
+{
+  "name": "tree-sitter-solidity",
+  "version": "1.0.5",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "nan": {
+      "version": "2.14.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+      "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
+    },
+    "tree-sitter-cli": {
+      "version": "0.16.9",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.16.9.tgz",
+      "integrity": "sha512-Aguz2Ns7qG6t71MP9odhh4t9q3+f29BAmZq8XsTDMtoi5o/e9k+Umeqz6brNngCAz3vMBl1OX95ozdnYzhJWIA==",
+      "dev": true
+    }
+  }
+}
diff --git a/package.json b/package.json
index c7c8c62..c80ac33 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "tree-sitter-solidity",
   "version": "1.0.5",
   "description": "A tree sitter parser for Solidity",
-  "main": "index.js",
+  "main": "bindings/node",
   "scripts": {
     "test": "tree-sitter generate && tree-sitter test"
   },
@@ -13,5 +13,17 @@
   },
   "devDependencies": {
     "tree-sitter-cli": "^0.16.9"
-  }
+  },
+  "tree-sitter": [
+    {
+      "scope": "source.sol",
+      "file-types": [
+        "sol"
+      ],
+      "highlights": [
+        "queries/highlights.scm"
+      ],
+      "injection-regex": "^(sol|solidity)$"
+    }
+  ]
 }
diff --git a/queries/highlights.scm b/queries/highlights.scm
new file mode 100644
index 0000000..d02ac68
--- /dev/null
+++ b/queries/highlights.scm
@@ -0,0 +1,189 @@
+(comment) @comment
+
+; Pragma
+(pragma_directive) @tag
+(pragma_directive ">=" @tag)
+(pragma_directive "<=" @tag)
+(pragma_directive "=" @tag)
+(pragma_directive "~" @tag)
+(pragma_directive "^" @tag)
+
+
+; Literals
+[
+ (string)
+ (hex_string_literal)
+ (unicode_string_literal)
+ (yul_string_literal)
+] @string
+[
+ (number_literal)
+ (yul_decimal_number)
+ (yul_hex_number)
+] @number
+[
+ (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
+  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) @property)
+(property_identifier) @property
+(struct_expression ((identifier) @property . ":"))
+(enum_value) @property
+
+
+; 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


Test patch:
diff --git a/test/corpus/constructor.txt b/test/corpus/constructor.txt
index 0211411..3cd0340 100644
--- a/test/corpus/constructor.txt
+++ b/test/corpus/constructor.txt
@@ -30,7 +30,7 @@ contract Example {
     name: (identifier)
     body: (contract_body 
         (constructor_definition 
-            type: (type_name) name: (identifier)
+            type: (type_name (primitive_type)) name: (identifier)
             type: (type_name (identifier) (identifier)) name: (identifier)
             body: (function_body)))))
 
@@ -50,7 +50,7 @@ contract Example {
     name: (identifier)
     body: (contract_body 
         (constructor_definition 
-            type: (type_name) name: (identifier)
+            type: (type_name (primitive_type)) name: (identifier)
             type: (type_name (identifier) (identifier)) name: (identifier)
             (modifier_invocation (identifier))
             body: (function_body)))))
@@ -88,4 +88,4 @@ contract Example {
     name: (identifier)
     body: (contract_body 
         (constructor_definition 
-            body: (function_body)))))
\ No newline at end of file
+            body: (function_body)))))
diff --git a/test/corpus/event.txt b/test/corpus/event.txt
index 1ccfefd..aa81b71 100644
--- a/test/corpus/event.txt
+++ b/test/corpus/event.txt
@@ -49,7 +49,7 @@ contract Example {
     body: (contract_body
         (event_definition
             name: (identifier)
-            (event_paramater type: (type_name))))))
+            (event_paramater type: (type_name (primitive_type)))))))
 
 ====================
 Event parameters
@@ -68,14 +68,14 @@ contract Example {
         (event_definition
             name: (identifier)
 
-            (event_paramater type: (type_name))
+            (event_paramater type: (type_name (primitive_type)))
             
             (event_paramater 
-              type: (type_name)
+              type: (type_name (primitive_type))
               name: (identifier))
 
-            (event_paramater type: (type_name))
+            (event_paramater type: (type_name (primitive_type)))
             
             (event_paramater 
-              type: (type_name)
-              name: (identifier))))))
\ No newline at end of file
+              type: (type_name (primitive_type))
+              name: (identifier))))))
diff --git a/test/corpus/expressions.txt b/test/corpus/expressions.txt
index 1a82c00..be3754d 100644
--- a/test/corpus/expressions.txt
+++ b/test/corpus/expressions.txt
@@ -18,7 +18,7 @@ contract Example {
         (function_definition
          function_name: (identifier)
          body: (function_body 
-            (variable_declaration_statement (variable_declaration (type_name) name: (identifier)))
+            (variable_declaration_statement (variable_declaration (type_name (primitive_type)) name: (identifier)))
             (expression_statement (member_expression object: (identifier) property: (property_identifier))))))))
 
 ====================
@@ -139,7 +139,7 @@ contract Example {
         (function_definition
          function_name: (identifier)
          body: (function_body 
-            (expression_statement (call_expresion 
+            (expression_statement (call_expression 
             (identifier) 
             (identifier))))))))
 
@@ -296,7 +296,8 @@ contract Example {
     (expression_statement (inline_array_expression  (number_literal) (number_literal)))
     (expression_statement (identifier)) 
     (expression_statement (number_literal))
-    (expression_statement (member_expression (identifier) (property_identifier))) (expression_statement))))))
+    (expression_statement (member_expression (identifier) (property_identifier)))
+    (expression_statement (primitive_type)))))))
 
 
 ====================
@@ -337,4 +338,4 @@ contract Example {
 ---
         
 (source_file (contract_declaration (identifier) (contract_body (function_definition (identifier) (function_body 
-    (expression_statement (type_cast_expression (number_literal ))))))))
\ No newline at end of file
+    (expression_statement (type_cast_expression (primitive_type) (number_literal ))))))))
diff --git a/test/corpus/function.txt b/test/corpus/function.txt
index 4b867d5..bfd045a 100644
--- a/test/corpus/function.txt
+++ b/test/corpus/function.txt
@@ -33,7 +33,7 @@ contract Example {
     body: (contract_body 
         (function_definition
             function_name: (identifier) 
-            type: (type_name)
+            type: (type_name (primitive_type))
             name: (identifier)
             body: (function_body)))))
 
@@ -54,8 +54,8 @@ contract Example {
     body: (contract_body 
         (function_definition
             function_name: (identifier) 
-            type: (type_name)
-            type: (type_name)
+            type: (type_name (primitive_type))
+            type: (type_name (primitive_type))
             name: (identifier)
             body: (function_body)))))
 
@@ -81,8 +81,8 @@ contract Example {
             (visibility)
             (modifier_invocation (identifier))
             (virtual)
-            type: (type_name)
-            type: (type_name)
+            type: (type_name (primitive_type))
+            type: (type_name (primitive_type))
             name: (identifier)
             body: (function_body)))))
 
diff --git a/test/corpus/modifier.txt b/test/corpus/modifier.txt
index 56fb34b..d3bda3e 100644
--- a/test/corpus/modifier.txt
+++ b/test/corpus/modifier.txt
@@ -31,7 +31,7 @@ contract Example {
     body: (contract_body 
         (modifier_definition 
             name: (identifier)
-            type: (type_name)
+            type: (type_name (primitive_type))
             name: (identifier)
             body: (function_body)))))
 
@@ -88,4 +88,4 @@ contract Example {
     body: (contract_body 
         (modifier_definition 
             name: (identifier)
-            ))))
\ No newline at end of file
+            ))))
diff --git a/test/corpus/state_variable.txt b/test/corpus/state_variable.txt
index 75f8d76..7ec7be4 100644
--- a/test/corpus/state_variable.txt
+++ b/test/corpus/state_variable.txt
@@ -13,7 +13,7 @@ contract StateVariable {
     name: (identifier)
     body: (contract_body 
         (state_variable_declaration 
-            type: (type_name)
+            type: (type_name (primitive_type))
             name: (identifier)))))
 
 ====================
@@ -31,7 +31,7 @@ contract StateVariable {
     name: (identifier)
     body: (contract_body 
         (state_variable_declaration 
-            type: (type_name)
+            type: (type_name (primitive_type))
             name:  (identifier) 
             value: (number_literal)))))
 
@@ -50,7 +50,7 @@ contract StateVariable {
     name: (identifier)
     body: (contract_body 
         (state_variable_declaration 
-            type: (type_name)
+            type: (type_name (primitive_type))
             (override_specifier (identifier) (identifier)) 
             name: (identifier) 
-            value: (number_literal)))))
\ No newline at end of file
+            value: (number_literal)))))
diff --git a/test/corpus/statements.txt b/test/corpus/statements.txt
index 071ca19..1b8ce2b 100644
--- a/test/corpus/statements.txt
+++ b/test/corpus/statements.txt
@@ -18,7 +18,7 @@ contract Example {
          function_name: (identifier)
          body: (function_body 
             (variable_declaration_statement (variable_declaration 
-                    (type_name (type_name)) 
+                    (type_name (type_name (primitive_type))) 
                     name: (identifier))))))))
 
 
@@ -78,7 +78,7 @@ contract Example {
 (source_file (contract_declaration (identifier) (contract_body (function_definition (identifier) 
     (function_body 
         (for_statement 
-            (variable_declaration_statement (variable_declaration (type_name) (identifier)) (number_literal)) 
+            (variable_declaration_statement (variable_declaration (type_name (primitive_type)) (identifier)) (number_literal)) 
             (expression_statement (update_expression (identifier)))
             (binary_expression (identifier) (number_literal)) 
             (expression_statement (update_expression (identifier))))
@@ -141,8 +141,8 @@ contract Example {
 
 ---
 (source_file (contract_declaration (identifier) (contract_body (function_definition (identifier) (function_body 
-    (try_statement (call_expresion (identifier)) (type_name) (identifier) (block_statement (expression_statement (update_expression (identifier))))
-    (catch_clause (identifier) (type_name) (identifier) (block_statement (expression_statement (update_expression (identifier)))))))))))
+    (try_statement (call_expression (identifier)) (type_name (primitive_type)) (identifier) (block_statement (expression_statement (update_expression (identifier))))
+    (catch_clause (identifier) (type_name (primitive_type)) (identifier) (block_statement (expression_statement (update_expression (identifier)))))))))))
 
 ====================
 Return statement
@@ -181,4 +181,13 @@ contract Example {
         emit logmessage();
     }
 }
----
\ No newline at end of file
+---
+(source_file 
+    (contract_declaration 
+        (identifier) 
+        (contract_body 
+            (function_definition 
+                (identifier) 
+                (function_body 
+                    (emit_statement 
+                    (identifier)))))))
diff --git a/test/corpus/struct.txt b/test/corpus/struct.txt
index e044a90..5392088 100644
--- a/test/corpus/struct.txt
+++ b/test/corpus/struct.txt
@@ -12,5 +12,5 @@ struct example {
 (source_file
     (struct_declaration 
         (identifier)
-        (struct_member (type_name) (identifier))
-        (struct_member (type_name) (identifier)))) 
+        (struct_member (type_name (primitive_type)) (identifier))
+        (struct_member (type_name (primitive_type)) (identifier)))) 
diff --git a/test/corpus/using.txt b/test/corpus/using.txt
index 39087d4..19105b8 100644
--- a/test/corpus/using.txt
+++ b/test/corpus/using.txt
@@ -31,4 +31,4 @@ contract Example {
     body: (contract_body 
       (using_directive 
         (type_alias (identifier) (identifier))
-        source: (type_name)))))
\ No newline at end of file
+        source: (type_name (primitive_type))))))