terraform: Extract to zed-extensions/terraform repository (#26475)

This PR extracts the Terraform extension to the
[zed-extensions/terraform](https://github.com/zed-extensions/terraform)
repository.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-03-11 15:10:51 -04:00 committed by GitHub
parent 9cce5a650e
commit efdb769f9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 1 additions and 861 deletions

View file

@ -1,16 +0,0 @@
[package]
name = "zed_terraform"
version = "0.1.2"
edition.workspace = true
publish.workspace = true
license = "Apache-2.0"
[lints]
workspace = true
[lib]
path = "src/terraform.rs"
crate-type = ["cdylib"]
[dependencies]
zed_extension_api = "0.1.0"

View file

@ -1 +0,0 @@
../../LICENSE-APACHE

View file

@ -1,19 +0,0 @@
id = "terraform"
name = "Terraform"
description = "Terraform support."
version = "0.1.2"
schema_version = 1
authors = ["Caius Durling <dev@caius.name>", "Daniel Banck <dbanck@users.noreply.github.com>"]
repository = "https://github.com/zed-industries/zed"
[language_servers.terraform-ls]
name = "Terraform Language Server"
languages = ["Terraform", "Terraform Vars"]
language_ids = { Terraform = "terraform", "Terraform Vars" = "terraform-vars" }
# TODO: file issue for server supported code actions
# TODO: reenable default actions / delete override
code_action_kinds = []
[grammars.hcl]
repository = "https://github.com/MichaHoffmann/tree-sitter-hcl"
commit = "e936d3fef8bac884661472dce71ad82284761eb1"

View file

@ -1,5 +0,0 @@
("(" @open ")" @close)
("[" @open "]" @close)
("{" @open "}" @close)
((block_start) @open (block_end) @close)
((tuple_start) @open (tuple_end) @close)

View file

@ -1,15 +0,0 @@
name = "HCL"
grammar = "hcl"
path_suffixes = ["hcl"]
line_comments = ["# ", "// "]
block_comment = ["/*", "*/"]
autoclose_before = ",}])"
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] },
]
tab_size = 2

View file

@ -1,117 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/cb79d2446196d25607eb1d982c96939abdf67b8e/queries/hcl/highlights.scm
; highlights.scm
[
"!"
"\*"
"/"
"%"
"\+"
"-"
">"
">="
"<"
"<="
"=="
"!="
"&&"
"||"
] @operator
[
"{"
"}"
"["
"]"
"("
")"
] @punctuation.bracket
[
"."
".*"
","
"[*]"
] @punctuation.delimiter
[
(ellipsis)
"\?"
"=>"
] @punctuation.special
[
":"
"="
] @punctuation
[
"for"
"endfor"
"in"
"if"
"else"
"endif"
] @keyword
[
(quoted_template_start) ; "
(quoted_template_end) ; "
(template_literal) ; non-interpolation/directive content
] @string
[
(heredoc_identifier) ; END
(heredoc_start) ; << or <<-
] @punctuation.delimiter
[
(template_interpolation_start) ; ${
(template_interpolation_end) ; }
(template_directive_start) ; %{
(template_directive_end) ; }
(strip_marker) ; ~
] @punctuation.special
(numeric_lit) @number
(bool_lit) @boolean
(null_lit) @constant
(comment) @comment
(identifier) @variable
(body
(block
(identifier) @keyword))
(body
(block
(body
(block
(identifier) @type))))
(function_call
(identifier) @function)
(attribute
(identifier) @variable)
; { key: val }
;
; highlight identifier keys as though they were block attributes
(object_elem
key:
(expression
(variable_expr
(identifier) @variable)))
; var.foo, data.bar
;
; first element in get_attr is a variable.builtin or a reference to a variable.builtin
(expression
(variable_expr
(identifier) @variable)
(get_attr
(identifier) @variable))

View file

@ -1,13 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/indents.scm
[
(block)
(object)
(tuple)
(function_call)
] @indent
[
"]"
"}"
")"
] @outdent

View file

@ -1,6 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/injections.scm
(heredoc_template
(template_literal) @injection.content
(heredoc_identifier) @injection.language
(#downcase! @injection.language))

View file

@ -1,74 +0,0 @@
; HCL Outline Scheme
; Comments
(comment) @annotation
; Block with and without string_lit
; Example:
; terraform { ... }
; module "vpc" { ... }
; resource "resource" "name" { ... }
(config_file
(body
(block
(identifier) @context
) @item
)
)
; Inside block with identifier
(config_file
(body
(block
(identifier)
(body
(attribute
(identifier) @context
) @item
)
)
)
)
; Inside block with identifier and string_lit
(config_file
(body
(block
(identifier)
(body
(block
(identifier) @context
(string_lit)? @name
) @item
)
)
)
)
; Root Attribute block
; Example:
; inputs = { ... }
(config_file
(body
(attribute
(identifier) @context
) @item
)
)
; Inside Root Attribute block
(config_file
(body
(attribute
(identifier)
(expression
(collection_value
(object
(object_elem
key: (expression (variable_expr (identifier) @context))
) @item
)
)
)
)
)
)

View file

@ -1,5 +0,0 @@
("(" @open ")" @close)
("[" @open "]" @close)
("{" @open "}" @close)
((block_start) @open (block_end) @close)
((tuple_start) @open (tuple_end) @close)

View file

@ -1,15 +0,0 @@
name = "Terraform Vars"
grammar = "hcl"
path_suffixes = ["tfvars"]
line_comments = ["# ", "// "]
block_comment = ["/*", "*/"]
autoclose_before = ",}])"
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] },
]
tab_size = 2

View file

@ -1,159 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/cb79d2446196d25607eb1d982c96939abdf67b8e/queries/hcl/highlights.scm
; highlights.scm
[
"!"
"\*"
"/"
"%"
"\+"
"-"
">"
">="
"<"
"<="
"=="
"!="
"&&"
"||"
] @operator
[
"{"
"}"
"["
"]"
"("
")"
] @punctuation.bracket
[
"."
".*"
","
"[*]"
] @punctuation.delimiter
[
(ellipsis)
"\?"
"=>"
] @punctuation.special
[
":"
"="
] @punctuation
[
"for"
"endfor"
"in"
"if"
"else"
"endif"
] @keyword
[
(quoted_template_start) ; "
(quoted_template_end) ; "
(template_literal) ; non-interpolation/directive content
] @string
[
(heredoc_identifier) ; END
(heredoc_start) ; << or <<-
] @punctuation.delimiter
[
(template_interpolation_start) ; ${
(template_interpolation_end) ; }
(template_directive_start) ; %{
(template_directive_end) ; }
(strip_marker) ; ~
] @punctuation.special
(numeric_lit) @number
(bool_lit) @boolean
(null_lit) @constant
(comment) @comment
(identifier) @variable
(body
(block
(identifier) @keyword))
(body
(block
(body
(block
(identifier) @type))))
(function_call
(identifier) @function)
(attribute
(identifier) @variable)
; { key: val }
;
; highlight identifier keys as though they were block attributes
(object_elem
key:
(expression
(variable_expr
(identifier) @variable)))
; var.foo, data.bar
;
; first element in get_attr is a variable.builtin or a reference to a variable.builtin
(expression
(variable_expr
(identifier) @variable)
(get_attr
(identifier) @variable))
; https://github.com/nvim-treesitter/nvim-treesitter/blob/cb79d2446196d25607eb1d982c96939abdf67b8e/queries/terraform/highlights.scm
; Terraform specific references
;
;
; local/module/data/var/output
(expression
(variable_expr
(identifier) @variable
(#any-of? @variable "data" "var" "local" "module" "output"))
(get_attr
(identifier) @variable))
; path.root/cwd/module
(expression
(variable_expr
(identifier) @type
(#eq? @type "path"))
(get_attr
(identifier) @variable
(#any-of? @variable "root" "cwd" "module")))
; terraform.workspace
(expression
(variable_expr
(identifier) @type
(#eq? @type "terraform"))
(get_attr
(identifier) @variable
(#any-of? @variable "workspace")))
; Terraform specific keywords
; TODO: ideally only for identifiers under a `variable` block to minimize false positives
((identifier) @type
(#any-of? @type "bool" "string" "number" "object" "tuple" "list" "map" "set" "any"))
(object_elem
val:
(expression
(variable_expr
(identifier) @type
(#any-of? @type "bool" "string" "number" "object" "tuple" "list" "map" "set" "any"))))

View file

@ -1,16 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/indents.scm
[
(block)
(object)
(tuple)
(function_call)
] @indent
[
"]"
"}"
")"
] @outdent
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/terraform/indents.scm
; inherits: hcl

View file

@ -1,9 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/injections.scm
(heredoc_template
(template_literal) @injection.content
(heredoc_identifier) @injection.language
(#downcase! @injection.language))
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/terraform/injections.scm
; inherits: hcl

View file

@ -1,5 +0,0 @@
("(" @open ")" @close)
("[" @open "]" @close)
("{" @open "}" @close)
((block_start) @open (block_end) @close)
((tuple_start) @open (tuple_end) @close)

View file

@ -1,15 +0,0 @@
name = "Terraform"
grammar = "hcl"
path_suffixes = ["tf"]
line_comments = ["# ", "// "]
block_comment = ["/*", "*/"]
autoclose_before = ",}])"
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] },
{ start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] },
]
tab_size = 2

View file

@ -1,159 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/cb79d2446196d25607eb1d982c96939abdf67b8e/queries/hcl/highlights.scm
; highlights.scm
[
"!"
"\*"
"/"
"%"
"\+"
"-"
">"
">="
"<"
"<="
"=="
"!="
"&&"
"||"
] @operator
[
"{"
"}"
"["
"]"
"("
")"
] @punctuation.bracket
[
"."
".*"
","
"[*]"
] @punctuation.delimiter
[
(ellipsis)
"\?"
"=>"
] @punctuation.special
[
":"
"="
] @punctuation
[
"for"
"endfor"
"in"
"if"
"else"
"endif"
] @keyword
[
(quoted_template_start) ; "
(quoted_template_end) ; "
(template_literal) ; non-interpolation/directive content
] @string
[
(heredoc_identifier) ; END
(heredoc_start) ; << or <<-
] @punctuation.delimiter
[
(template_interpolation_start) ; ${
(template_interpolation_end) ; }
(template_directive_start) ; %{
(template_directive_end) ; }
(strip_marker) ; ~
] @punctuation.special
(numeric_lit) @number
(bool_lit) @boolean
(null_lit) @constant
(comment) @comment
(identifier) @variable
(body
(block
(identifier) @keyword))
(body
(block
(body
(block
(identifier) @type))))
(function_call
(identifier) @function)
(attribute
(identifier) @variable)
; { key: val }
;
; highlight identifier keys as though they were block attributes
(object_elem
key:
(expression
(variable_expr
(identifier) @variable)))
; var.foo, data.bar
;
; first element in get_attr is a variable.builtin or a reference to a variable.builtin
(expression
(variable_expr
(identifier) @variable)
(get_attr
(identifier) @variable))
; https://github.com/nvim-treesitter/nvim-treesitter/blob/cb79d2446196d25607eb1d982c96939abdf67b8e/queries/terraform/highlights.scm
; Terraform specific references
;
;
; local/module/data/var/output
(expression
(variable_expr
(identifier) @variable
(#any-of? @variable "data" "var" "local" "module" "output"))
(get_attr
(identifier) @variable))
; path.root/cwd/module
(expression
(variable_expr
(identifier) @type
(#eq? @type "path"))
(get_attr
(identifier) @variable
(#any-of? @variable "root" "cwd" "module")))
; terraform.workspace
(expression
(variable_expr
(identifier) @type
(#eq? @type "terraform"))
(get_attr
(identifier) @variable
(#any-of? @variable "workspace")))
; Terraform specific keywords
; TODO: ideally only for identifiers under a `variable` block to minimize false positives
((identifier) @type
(#any-of? @type "bool" "string" "number" "object" "tuple" "list" "map" "set" "any"))
(object_elem
val:
(expression
(variable_expr
(identifier) @type
(#any-of? @type "bool" "string" "number" "object" "tuple" "list" "map" "set" "any"))))

View file

@ -1,16 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/indents.scm
[
(block)
(object)
(tuple)
(function_call)
] @indent
[
"]"
"}"
")"
] @outdent
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/terraform/indents.scm
; inherits: hcl

View file

@ -1,9 +0,0 @@
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/hcl/injections.scm
(heredoc_template
(template_literal) @injection.content
(heredoc_identifier) @injection.language
(#downcase! @injection.language))
; https://github.com/nvim-treesitter/nvim-treesitter/blob/ce4adf11cfe36fc5b0e5bcdce0c7c6e8fbc9798a/queries/terraform/injections.scm
; inherits: hcl

View file

@ -1,76 +0,0 @@
; HCL Outline Scheme
; Comments
(comment) @annotation
; Block with and without string_lit
; Example:
; terraform { ... }
; module "vpc" { ... }
; resource "resource" "name" { ... }
(config_file
(body
(block
(identifier) @context
(string_lit)? @name
(string_lit)? @name
) @item
)
)
; Inside block with identifier
(config_file
(body
(block
(identifier)
(body
(attribute
(identifier) @context
) @item
)
)
)
)
; Inside block with identifier and string_lit
(config_file
(body
(block
(identifier)
(body
(block
(identifier) @context
(string_lit)? @name
) @item
)
)
)
)
; Root Attribute block
; Example:
; inputs = { ... }
(config_file
(body
(attribute
(identifier) @context
) @item
)
)
; Inside Root Attribute block
(config_file
(body
(attribute
(identifier)
(expression
(collection_value
(object
(object_elem
key: (expression (variable_expr (identifier) @context))
) @item
)
)
)
)
)
)

View file

@ -1,102 +0,0 @@
use std::fs;
use zed::LanguageServerId;
use zed_extension_api::{self as zed, Result};
struct TerraformExtension {
cached_binary_path: Option<String>,
}
impl TerraformExtension {
fn language_server_binary_path(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<String> {
if let Some(path) = worktree.which("terraform-ls") {
return Ok(path);
}
if let Some(path) = &self.cached_binary_path {
if fs::metadata(path).map_or(false, |stat| stat.is_file()) {
return Ok(path.clone());
}
}
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);
let release = zed::latest_github_release(
"hashicorp/terraform-ls",
zed::GithubReleaseOptions {
require_assets: false,
pre_release: false,
},
)?;
let (platform, arch) = zed::current_platform();
let download_url = format!(
"https://releases.hashicorp.com/terraform-ls/{version}/terraform-ls_{version}_{os}_{arch}.zip",
version = release.version.strip_prefix('v').unwrap_or(&release.version),
os = match platform {
zed::Os::Mac => "darwin",
zed::Os::Linux => "linux",
zed::Os::Windows => "windows",
},
arch = match arch {
zed::Architecture::Aarch64 => "arm64",
zed::Architecture::X86 => "386",
zed::Architecture::X8664 => "amd64",
},
);
let version_dir = format!("terraform-ls-{}", release.version);
let binary_path = format!("{version_dir}/terraform-ls");
if !fs::metadata(&binary_path).map_or(false, |stat| stat.is_file()) {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);
zed::download_file(&download_url, &version_dir, zed::DownloadedFileType::Zip)
.map_err(|e| format!("failed to download file: {e}"))?;
zed::make_file_executable(&binary_path)?;
let entries =
fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?;
for entry in entries {
let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?;
if entry.file_name().to_str() != Some(&version_dir) {
fs::remove_dir_all(entry.path()).ok();
}
}
}
self.cached_binary_path = Some(binary_path.clone());
Ok(binary_path)
}
}
impl zed::Extension for TerraformExtension {
fn new() -> Self {
Self {
cached_binary_path: None,
}
}
fn language_server_command(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
Ok(zed::Command {
command: self.language_server_binary_path(language_server_id, worktree)?,
args: vec!["serve".to_string()],
env: Default::default(),
})
}
}
zed::register_extension!(TerraformExtension);