From ee3e9f4dc0e5ee9e2bfb1ee47638375840b8fe0f Mon Sep 17 00:00:00 2001 From: Michael Hoffmann Date: Fri, 2 Dec 2022 23:47:19 +0100 Subject: feat(hcl,terraform): split terraform from hcl, add specialized queries for tf This enables us to have different queries for terraform and general hcl. It solve the situation where other dialects of hcl (nomad, packer, etc) might use a terraform keyword and get highlighted out of place. --- README.md | 1 + lockfile.json | 3 ++ lua/nvim-treesitter/parsers.lua | 12 +++++++- queries/hcl/highlights.scm | 15 ++++------ queries/terraform/folds.scm | 1 + queries/terraform/highlights.scm | 21 +++++++++++++ queries/terraform/indents.scm | 1 + queries/terraform/injections.scm | 1 + tests/indent/hcl/function_call.tf | 6 ---- tests/indent/hcl/indent-in-multiline-objects.tf | 6 ---- tests/indent/hcl/indent-in-multiline-tuples.tf | 6 ---- tests/indent/hcl/multiline-comments.tf | 7 ----- tests/indent/hcl/multiple-attributes.tf | 4 --- tests/indent/hcl/multiple-blocks.tf | 6 ---- tests/indent/hcl/nested_blocks.tf | 5 ---- tests/indent/hcl/no-indent-after-brace.tf | 4 --- tests/indent/hcl_spec.lua | 35 ---------------------- tests/indent/terraform/function_call.tf | 6 ++++ .../terraform/indent-in-multiline-objects.tf | 6 ++++ .../indent/terraform/indent-in-multiline-tuples.tf | 6 ++++ tests/indent/terraform/multiline-comments.tf | 7 +++++ tests/indent/terraform/multiple-attributes.tf | 4 +++ tests/indent/terraform/multiple-blocks.tf | 6 ++++ tests/indent/terraform/nested_blocks.tf | 5 ++++ tests/indent/terraform/no-indent-after-brace.tf | 4 +++ tests/indent/terraform_spec.lua | 35 ++++++++++++++++++++++ 26 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 queries/terraform/folds.scm create mode 100644 queries/terraform/highlights.scm create mode 100644 queries/terraform/indents.scm create mode 100644 queries/terraform/injections.scm delete mode 100644 tests/indent/hcl/function_call.tf delete mode 100644 tests/indent/hcl/indent-in-multiline-objects.tf delete mode 100644 tests/indent/hcl/indent-in-multiline-tuples.tf delete mode 100644 tests/indent/hcl/multiline-comments.tf delete mode 100644 tests/indent/hcl/multiple-attributes.tf delete mode 100644 tests/indent/hcl/multiple-blocks.tf delete mode 100644 tests/indent/hcl/nested_blocks.tf delete mode 100644 tests/indent/hcl/no-indent-after-brace.tf delete mode 100644 tests/indent/hcl_spec.lua create mode 100644 tests/indent/terraform/function_call.tf create mode 100644 tests/indent/terraform/indent-in-multiline-objects.tf create mode 100644 tests/indent/terraform/indent-in-multiline-tuples.tf create mode 100644 tests/indent/terraform/multiline-comments.tf create mode 100644 tests/indent/terraform/multiple-attributes.tf create mode 100644 tests/indent/terraform/multiple-blocks.tf create mode 100644 tests/indent/terraform/nested_blocks.tf create mode 100644 tests/indent/terraform/no-indent-after-brace.tf create mode 100644 tests/indent/terraform_spec.lua diff --git a/README.md b/README.md index 40aa11d6a..2f210f718 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,7 @@ We are looking for maintainers to add more parsers and to write query files for - [x] [swift](https://github.com/alex-pinkus/tree-sitter-swift) (maintained by @alex-pinkus) - [x] [sxhkdrc](https://github.com/RaafatTurki/tree-sitter-sxhkdrc) (maintained by @RaafatTurki) - [x] [teal](https://github.com/euclidianAce/tree-sitter-teal) (maintained by @euclidianAce) +- [x] [terraform](https://github.com/MichaHoffmann/tree-sitter-hcl) (maintained by @MichaHoffmann) - [x] [tiger](https://github.com/ambroisie/tree-sitter-tiger) (maintained by @ambroisie) - [x] [tlaplus](https://github.com/tlaplus-community/tree-sitter-tlaplus) (maintained by @ahelwer, @susliko) - [x] [todotxt](https://github.com/arnarg/tree-sitter-todotxt.git) (experimental, maintained by @arnarg) diff --git a/lockfile.json b/lockfile.json index bb4e18ade..97aad4ec5 100644 --- a/lockfile.json +++ b/lockfile.json @@ -374,6 +374,9 @@ "teal": { "revision": "1ae8c68e90523b26b93af56feb7868fe4214e2b2" }, + "terraform": { + "revision": "0ff887f2a60a147452d52db060de6b42f42f1441" + }, "tiger": { "revision": "a233ebe360a73a92c50978e5c4e9e471bc59ff42" }, diff --git a/lua/nvim-treesitter/parsers.lua b/lua/nvim-treesitter/parsers.lua index f4e13974b..6bd94f93b 100644 --- a/lua/nvim-treesitter/parsers.lua +++ b/lua/nvim-treesitter/parsers.lua @@ -8,7 +8,6 @@ local filetype_to_parsername = { PKGBUILD = "bash", html_tags = "html", ["typescript.tsx"] = "tsx", - terraform = "hcl", ["html.handlebars"] = "glimmer", systemverilog = "verilog", cls = "latex", @@ -618,6 +617,17 @@ list.hcl = { filetype = "hcl", } +list.terraform = { + install_info = { + url = "https://github.com/MichaHoffmann/tree-sitter-hcl", + files = { "src/parser.c", "src/scanner.cc" }, + branch = "main", + location = "dialects/terraform", + }, + maintainers = { "@MichaHoffmann" }, + filetype = "terraform", +} + list.markdown = { install_info = { url = "https://github.com/MDeiml/tree-sitter-markdown", diff --git a/queries/hcl/highlights.scm b/queries/hcl/highlights.scm index 658369292..4f2eb2300 100644 --- a/queries/hcl/highlights.scm +++ b/queries/hcl/highlights.scm @@ -81,7 +81,8 @@ (comment) @comment @spell (identifier) @variable -(block (identifier) @type) +(body (block (identifier) @keyword)) +(body (block (body (block (identifier) @type)))) (function_call (identifier) @function) (attribute (identifier) @field) @@ -90,13 +91,9 @@ ; highlight identifier keys as though they were block attributes (object_elem key: (expression (variable_expr (identifier) @field))) -((identifier) @keyword (#any-of? @keyword "module" "root" "cwd" "resource" "variable" "data" "locals" "terraform" "provider" "output")) -((identifier) @type.builtin (#any-of? @type.builtin "bool" "string" "number" "object" "tuple" "list" "map" "set" "any")) -(variable_expr (identifier) @variable.builtin (#any-of? @variable.builtin "var" "local" "path")) -(get_attr (identifier) @variable.builtin (#any-of? @variable.builtin "root" "cwd" "module")) - -(object_elem val: (expression - (variable_expr - (identifier) @type.builtin (#any-of? @type.builtin "bool" "string" "number" "object" "tuple" "list" "map" "set" "any")))) +; var.foo, data.bar +; +; first element in get_attr is a keyword or a reference to a keyword +(expression (variable_expr (identifier) @keyword) (get_attr (identifier) @field)) (ERROR) @error diff --git a/queries/terraform/folds.scm b/queries/terraform/folds.scm new file mode 100644 index 000000000..0e5ffc2db --- /dev/null +++ b/queries/terraform/folds.scm @@ -0,0 +1 @@ +; inherits: hcl diff --git a/queries/terraform/highlights.scm b/queries/terraform/highlights.scm new file mode 100644 index 000000000..d31b83c82 --- /dev/null +++ b/queries/terraform/highlights.scm @@ -0,0 +1,21 @@ +; inherits: hcl + +; Terraform specific references +; +; +; local/module/data/var/output +(expression (variable_expr (identifier) @type.builtin (#any-of? @type.builtin "data" "var" "local" "module" "output")) (get_attr (identifier) @field)) + +; path.root/cwd/module +(expression (variable_expr (identifier) @type.builtin (#eq? @type.builtin "path")) (get_attr (identifier) @variable.builtin (#any-of? @variable.builtin "root" "cwd" "module"))) + +; terraform.workspace +(expression (variable_expr (identifier) @type.builtin (#eq? @type.builtin "terraform")) (get_attr (identifier) @variable.builtin (#any-of? @variable.builtin "workspace"))) + +; Terraform specific keywords + +; FIXME: ideally only for identifiers under a `variable` block to minimize false positives +((identifier) @type.builtin (#any-of? @type.builtin "bool" "string" "number" "object" "tuple" "list" "map" "set" "any")) +(object_elem val: (expression + (variable_expr + (identifier) @type.builtin (#any-of? @type.builtin "bool" "string" "number" "object" "tuple" "list" "map" "set" "any")))) diff --git a/queries/terraform/indents.scm b/queries/terraform/indents.scm new file mode 100644 index 000000000..0e5ffc2db --- /dev/null +++ b/queries/terraform/indents.scm @@ -0,0 +1 @@ +; inherits: hcl diff --git a/queries/terraform/injections.scm b/queries/terraform/injections.scm new file mode 100644 index 000000000..0e5ffc2db --- /dev/null +++ b/queries/terraform/injections.scm @@ -0,0 +1 @@ +; inherits: hcl diff --git a/tests/indent/hcl/function_call.tf b/tests/indent/hcl/function_call.tf deleted file mode 100644 index 44c477e48..000000000 --- a/tests/indent/hcl/function_call.tf +++ /dev/null @@ -1,6 +0,0 @@ -test { - x = f( - a, - b, - ) -} diff --git a/tests/indent/hcl/indent-in-multiline-objects.tf b/tests/indent/hcl/indent-in-multiline-objects.tf deleted file mode 100644 index 00ee9c958..000000000 --- a/tests/indent/hcl/indent-in-multiline-objects.tf +++ /dev/null @@ -1,6 +0,0 @@ -test { - x = { - 1: "foo", - 2: "bar", - } -} diff --git a/tests/indent/hcl/indent-in-multiline-tuples.tf b/tests/indent/hcl/indent-in-multiline-tuples.tf deleted file mode 100644 index 402487890..000000000 --- a/tests/indent/hcl/indent-in-multiline-tuples.tf +++ /dev/null @@ -1,6 +0,0 @@ -test { - x = [ - 1, - 2, - ] -} diff --git a/tests/indent/hcl/multiline-comments.tf b/tests/indent/hcl/multiline-comments.tf deleted file mode 100644 index 494aaba9c..000000000 --- a/tests/indent/hcl/multiline-comments.tf +++ /dev/null @@ -1,7 +0,0 @@ -test { - /* - foo - bar - baz - */ -} diff --git a/tests/indent/hcl/multiple-attributes.tf b/tests/indent/hcl/multiple-attributes.tf deleted file mode 100644 index da6a85fb0..000000000 --- a/tests/indent/hcl/multiple-attributes.tf +++ /dev/null @@ -1,4 +0,0 @@ -test { - x = ["foo", "bar"] - y = {"fizz": "buzz"} -} diff --git a/tests/indent/hcl/multiple-blocks.tf b/tests/indent/hcl/multiple-blocks.tf deleted file mode 100644 index b9826c889..000000000 --- a/tests/indent/hcl/multiple-blocks.tf +++ /dev/null @@ -1,6 +0,0 @@ -test { - x = "foo" -} -test { - y = "bar" -} diff --git a/tests/indent/hcl/nested_blocks.tf b/tests/indent/hcl/nested_blocks.tf deleted file mode 100644 index 7be6492cc..000000000 --- a/tests/indent/hcl/nested_blocks.tf +++ /dev/null @@ -1,5 +0,0 @@ -test { - nest { - x = "bar" - } -} diff --git a/tests/indent/hcl/no-indent-after-brace.tf b/tests/indent/hcl/no-indent-after-brace.tf deleted file mode 100644 index e670ad8d7..000000000 --- a/tests/indent/hcl/no-indent-after-brace.tf +++ /dev/null @@ -1,4 +0,0 @@ -# Issue #2590 -locals { - titles = ["test0", "test1"] -} diff --git a/tests/indent/hcl_spec.lua b/tests/indent/hcl_spec.lua deleted file mode 100644 index ee53d89fc..000000000 --- a/tests/indent/hcl_spec.lua +++ /dev/null @@ -1,35 +0,0 @@ -local Runner = require("tests.indent.common").Runner ---local XFAIL = require("tests.indent.common").XFAIL - -local run = Runner:new(it, "tests/indent/hcl", { - tabstop = 2, - shiftwidth = 2, - expandtab = true, -}) - -describe("indent HCL:", function() - describe("whole file:", function() - run:whole_file(".", { - expected_failures = {}, - }) - end) - - describe("new line:", function() - run:new_line("no-indent-after-brace.tf", { on_line = 4, text = "# Wow, no indent here please", indent = 0 }) - run:new_line("indent-in-multiline-tuples.tf", { on_line = 4, text = "3,", indent = 4 }) - run:new_line("indent-in-multiline-tuples.tf", { on_line = 3, text = "# as elements", indent = 4 }) - run:new_line("indent-in-multiline-tuples.tf", { on_line = 5, text = "# as outer block", indent = 2 }) - run:new_line("indent-in-multiline-tuples.tf", { on_line = 1, text = "# as outer block", indent = 2 }) - run:new_line("indent-in-multiline-objects.tf", { on_line = 4, text = '3: "baz",', indent = 4 }) - run:new_line("indent-in-multiline-objects.tf", { on_line = 3, text = "# as elements", indent = 4 }) - run:new_line("indent-in-multiline-objects.tf", { on_line = 5, text = "# as outer block", indent = 2 }) - run:new_line("indent-in-multiline-objects.tf", { on_line = 1, text = "# as outer block", indent = 2 }) - run:new_line("multiple-attributes.tf", { on_line = 2, text = "a = 1", indent = 2 }) - run:new_line("multiple-attributes.tf", { on_line = 3, text = "a = 1", indent = 2 }) - run:new_line("multiple-attributes.tf", { on_line = 4, text = "a = 1", indent = 0 }) - run:new_line("nested_blocks.tf", { on_line = 3, text = "a = 1", indent = 4 }) - run:new_line("nested_blocks.tf", { on_line = 4, text = "a = 1", indent = 2 }) - run:new_line("function_call.tf", { on_line = 4, text = "c,", indent = 4 }) - run:new_line("function_call.tf", { on_line = 5, text = "a = 1", indent = 2 }) - end) -end) diff --git a/tests/indent/terraform/function_call.tf b/tests/indent/terraform/function_call.tf new file mode 100644 index 000000000..44c477e48 --- /dev/null +++ b/tests/indent/terraform/function_call.tf @@ -0,0 +1,6 @@ +test { + x = f( + a, + b, + ) +} diff --git a/tests/indent/terraform/indent-in-multiline-objects.tf b/tests/indent/terraform/indent-in-multiline-objects.tf new file mode 100644 index 000000000..00ee9c958 --- /dev/null +++ b/tests/indent/terraform/indent-in-multiline-objects.tf @@ -0,0 +1,6 @@ +test { + x = { + 1: "foo", + 2: "bar", + } +} diff --git a/tests/indent/terraform/indent-in-multiline-tuples.tf b/tests/indent/terraform/indent-in-multiline-tuples.tf new file mode 100644 index 000000000..402487890 --- /dev/null +++ b/tests/indent/terraform/indent-in-multiline-tuples.tf @@ -0,0 +1,6 @@ +test { + x = [ + 1, + 2, + ] +} diff --git a/tests/indent/terraform/multiline-comments.tf b/tests/indent/terraform/multiline-comments.tf new file mode 100644 index 000000000..494aaba9c --- /dev/null +++ b/tests/indent/terraform/multiline-comments.tf @@ -0,0 +1,7 @@ +test { + /* + foo + bar + baz + */ +} diff --git a/tests/indent/terraform/multiple-attributes.tf b/tests/indent/terraform/multiple-attributes.tf new file mode 100644 index 000000000..da6a85fb0 --- /dev/null +++ b/tests/indent/terraform/multiple-attributes.tf @@ -0,0 +1,4 @@ +test { + x = ["foo", "bar"] + y = {"fizz": "buzz"} +} diff --git a/tests/indent/terraform/multiple-blocks.tf b/tests/indent/terraform/multiple-blocks.tf new file mode 100644 index 000000000..b9826c889 --- /dev/null +++ b/tests/indent/terraform/multiple-blocks.tf @@ -0,0 +1,6 @@ +test { + x = "foo" +} +test { + y = "bar" +} diff --git a/tests/indent/terraform/nested_blocks.tf b/tests/indent/terraform/nested_blocks.tf new file mode 100644 index 000000000..7be6492cc --- /dev/null +++ b/tests/indent/terraform/nested_blocks.tf @@ -0,0 +1,5 @@ +test { + nest { + x = "bar" + } +} diff --git a/tests/indent/terraform/no-indent-after-brace.tf b/tests/indent/terraform/no-indent-after-brace.tf new file mode 100644 index 000000000..e670ad8d7 --- /dev/null +++ b/tests/indent/terraform/no-indent-after-brace.tf @@ -0,0 +1,4 @@ +# Issue #2590 +locals { + titles = ["test0", "test1"] +} diff --git a/tests/indent/terraform_spec.lua b/tests/indent/terraform_spec.lua new file mode 100644 index 000000000..49fa22c20 --- /dev/null +++ b/tests/indent/terraform_spec.lua @@ -0,0 +1,35 @@ +local Runner = require("tests.indent.common").Runner +--local XFAIL = require("tests.indent.common").XFAIL + +local run = Runner:new(it, "tests/indent/terraform", { + tabstop = 2, + shiftwidth = 2, + expandtab = true, +}) + +describe("indent Terraform:", function() + describe("whole file:", function() + run:whole_file(".", { + expected_failures = {}, + }) + end) + + describe("new line:", function() + run:new_line("no-indent-after-brace.tf", { on_line = 4, text = "# Wow, no indent here please", indent = 0 }) + run:new_line("indent-in-multiline-tuples.tf", { on_line = 4, text = "3,", indent = 4 }) + run:new_line("indent-in-multiline-tuples.tf", { on_line = 3, text = "# as elements", indent = 4 }) + run:new_line("indent-in-multiline-tuples.tf", { on_line = 5, text = "# as outer block", indent = 2 }) + run:new_line("indent-in-multiline-tuples.tf", { on_line = 1, text = "# as outer block", indent = 2 }) + run:new_line("indent-in-multiline-objects.tf", { on_line = 4, text = '3: "baz",', indent = 4 }) + run:new_line("indent-in-multiline-objects.tf", { on_line = 3, text = "# as elements", indent = 4 }) + run:new_line("indent-in-multiline-objects.tf", { on_line = 5, text = "# as outer block", indent = 2 }) + run:new_line("indent-in-multiline-objects.tf", { on_line = 1, text = "# as outer block", indent = 2 }) + run:new_line("multiple-attributes.tf", { on_line = 2, text = "a = 1", indent = 2 }) + run:new_line("multiple-attributes.tf", { on_line = 3, text = "a = 1", indent = 2 }) + run:new_line("multiple-attributes.tf", { on_line = 4, text = "a = 1", indent = 0 }) + run:new_line("nested_blocks.tf", { on_line = 3, text = "a = 1", indent = 4 }) + run:new_line("nested_blocks.tf", { on_line = 4, text = "a = 1", indent = 2 }) + run:new_line("function_call.tf", { on_line = 4, text = "c,", indent = 4 }) + run:new_line("function_call.tf", { on_line = 5, text = "a = 1", indent = 2 }) + end) +end) -- cgit v1.2.3-70-g09d2