GithubHelp home page GithubHelp logo

hashicorp / syntax Goto Github PK

View Code? Open in Web Editor NEW
25.0 8.0 11.0 624 KB

TextMate grammars for highlighting HCL, HCL-based languages and Sentinel.

License: Mozilla Public License 2.0

HCL 70.56% Go 22.37% TypeScript 7.07%
hcl2 grammar textmate highlighting

syntax's Introduction

HashiCorp Syntax

TextMate grammars for highlighting configuration used by HashiCorp software, primarily HCL (HashiCorp Configuration Language) and HCL-based languages.

How do I use this?

As end-user

Generally you should never need to interact with this repository directly.

Instead you can use the grammar through editors, editor extensions, or highlighting libraries which in turn may use this repository, for example:

As maintainer enabling end-users

If your editor or other syntax highlighting engine supports TextMate, you can introduce a build-time dependency along these lines:

VERSION=0.1.0
URL="https://github.com/hashicorp/syntax/raw/v${VERSION}/syntaxes/hcl.tmGrammar.json"
curl -fL $URL > ./hcl.tmGrammar.json

We may consider distributing the grammars via a packaging system in the future.

Grammar Mapping

Most highlighting engines match files based on filename patterns. Matched files are then mapped to language IDs. With that in mind we recommend the following mapping.

Pattern Language ID Language
*.hcl hcl HCL
*.tf terraform Terraform (configuration)
*.tfvars terraform-vars Terraform (variables)
*.sentinel sentinel Sentinel (policies)

Language IDs are also often used in highlighting Markdown code blocks. Picking the right language IDs is key to enable accurate and consistent highlighting everywhere and to enable IntelliSense (such as completion) in editors.

As explained below you can use the HCL grammar to highlight e.g. Terraform files but you should still assign schema-specific language IDs (such as terraform or terraform-vars) to these files.

How do I contribute?

See instructions in DEVELOPMENT.md.

Non-TextMate grammars

We do not accept contributions of non-TextMate grammars at this point as we do not have any established strategy for testability and sustainable maintenance of multiple grammars.

In the meantime you can use other available grammars and highlighting solutions, e.g.

You may take inspiration from the regular expressions used in our TextMate grammar, assuming your highlighting engine is regex-based.

Product X grammar

HashiCorp Products

We welcome contributions of other product-based grammars (such as Packer) and fixes for any existing grammars.

Bear in mind that TextMate grammars may generally not provide perfectly accurate product-specific highlighting given the complexity of how HCL schemas are applied in various products. Editors are expected to use LSP semantic tokens to compensate for this. We also generally aim to reflect the latest version of the product as TextMate grammars have no way of communicating product versions.

3rd Parties

This repository is intended for grammars of HashiCorp-maintained products. Therefore we do not accept contributions of grammars for HCL-based languages used by 3rd party products. These can be maintained in their own repositories.

Maintainers of such 3rd party grammars are however welcomed to use the provided HCL grammar or take inspiration from any provided product grammar to build their own. Namely we recommend the use of "include": "source.hcl#pattern-name" in such a 3rd party product grammar to take advantage of the HCL grammar and treat it as an upstream dependency.

Also make sure to pick a unique language ID (that is different from the ones above) where applicable.

HCL vs (Terraform / Packer / ...)

In Short: Can I use grammar X for file Y?

  • Do not use product grammar (e.g. Terraform) for other products (e.g. Packer)
  • Do not use product grammar (e.g. Terraform) for "generic" HCL
  • Do use HCL grammar to highlight any HCL-based language (incl. Terraform or Packer) where no alternatives exist.
Long version

HCL is a schema-based language. Schema is an integral part of any HCL-based language as it declares the names of blocks, names of attributes, expected expressions and data types etc. You can think of it as similar to JSON schemas in JSON.

The language itself (HCL) cannot and should not imply any schema, i.e. does not imply any block or attribute names. Schema is what makes the language product-specific.

To put it simply:

HCL + Schema (e.g. Terraform or Packer) = Product-specific language (Terraform language or Packer language).

To provide any product-specific feature, either more precise product-specific highlighting or any IntelliSense, such as completion, hover, go-to-definition etc., editors need to know what schema to use.

For example, to understand the meaning of resource block in Terraform when user hovers over it, the editor needs to know the file is a Terraform configuration file. Unlike terraform, hcl does not convey that information.

Schemas may also differ even in the context of a single product (e.g. terraform vs terraform-vars). This is why it's essential to use documented language IDs.

Why does the TextMate grammar use scope X instead of Y?

Picking the right scope is a balancing act between the following:

  1. TextMate's own documented naming conventions
  2. meaningful semantic mapping between naming conventions and DSL (HCL) constructs
  3. resulting UX when chosen scopes are rendered via common/default themes in editors (which may or may not reflect 1. and 2.)

This has a potential downside for authors of custom themes who may want to be more specific, or generally expect the scopes to more intuitively reflect names of HCL constructs, such as "block", "attribute" etc.

We plan to address these needs via custom semantic tokens and modifiers within VSCode (see hashicorp/vscode-terraform#958 for more details) and remain open to feedback how this works in other editors and contexts.

What about HCL JSON?

We recommend HCL JSON configuration files to be highlighted as plain JSON at this time, for which there should be existing grammars maintained by the community. We do not have an established convention for language IDs for these files as it is unclear whether and how language servers should interact with these files.

LSP Semantic Token Based Highlighting

LSP (Language Server Protocol) 3.16 introduced language server-driven highlighting. Language server is typically better equipped to provide more contextual and accurate highlighting as it can parse the whole AST, unlike a TextMate grammar operating on regex-basis.

Is LSP the way forward?

LSP 3.17 does support use cases where semantic highlighting is the only way to highlight a file (through augmentsSyntaxTokens client capability). However in the context of HCL we recommend semantic highlighting to be used as an addition to highlight product-specific pieces of an HCL-based language (such as Terraform) and improve any inaccuracies of product-specific static grammars, rather than to semantically highlight generic HCL.

Note there are also environments outside of editors in which LSP is not a suitable way of highlighting code - e.g. code rendered on websites such as GitHub or terraform.io.

syntax's People

Contributors

aeschright avatar ansgarm avatar calebalbers avatar dbanck avatar dependabot[bot] avatar glennsarti avatar hashicorp-copywrite[bot] avatar hashicorp-tsccr[bot] avatar jpogran avatar kamilturek avatar paultyng avatar radeksimko avatar sestegra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

syntax's Issues

Mark repo as public

When the vscode-terraform and vscode-hcl repos have been successfully setup to pull grammar from this repo, mark public

syntax: Broken highlighting of nested complex types within `object({ ... })`

Issue Description

variable "test" {
  type = object({
    test_object = map( # here
      object({ # here
        test_map = string
      })
    )
  })
}

Currently the above snippet fails to highlight the nested map and object types.

Screenshot 2022-03-02 at 09 15 30

Interestingly, nested types under map are highlighted correctly:

Screenshot 2022-03-02 at 09 17 24

Environment Information

Terraform Information

Version: 1.1.5
Platform: darwin_arm64
Outdated: true

Visual Studio Code

Name Version
Operating System Darwin arm64 21.3.0
VSCode 1.64.2

Visual Studio Code Extensions

Visual Studio Code Extensions(Click to Expand)
Extension Author Version
azure-account ms-vscode 0.10.0
codetour vsls-contrib 0.0.58
esbuild-problem-matchers connor4312 0.0.2
go golang 0.31.1
json ZainChen 2.0.2
remote-containers ms-vscode-remote 0.217.4
terraform-preview hashicorp 2022.3.115
vscode-docker ms-azuretools 1.20.0
vscode-eslint dbaeumer 2.2.2

Extension Logs

Find this from the first few lines of the relevant Output pane:
View -> Output -> 'HashiCorp Terraform'

Highlight static segments of address (e.g. `var`) differently

Hi,

Terraform extension v2.13.0

See the screenshot, note how sometimes the text var is in blue and not white.

I think this happens when the terraform VSC extension knows the value should be a boolean or number rather than a string.

I am sure this has only started to happen in the last few days/weeks.

image

Copy HCL grammar patterns to Terraform grammar

The goal is to mainly ensure that we don't "downgrade" users from the existing https://github.com/hashicorp/vscode-terraform/blob/main/syntaxes/terraform.tmGrammar.json

Specifically the copy pasting is intending to address

and unblock any automation downstream in vscode-terraform and continued releasing of the extension with improved syntax, while we work on #TODO

Problem parsing block with dash in name

If the name of a block contains a dash, the parsing is incorrect.

For instance, using Packer post-processor block, the name isn't well parsed.

build {
  sources = ["source.docker.sysbox"]

  post-processor "docker-tag" {
    repository = var.repository
    tags       = var.tags
  }
}

See the current snapshot for the post-processor block

>post-processor "docker-tag" {}
#^^^^ source.hcl meta.block.hcl entity.name.type.hcl
#    ^^^^^^^^^^ source.hcl meta.block.hcl variable.other.enummember.hcl
#              ^ source.hcl meta.block.hcl
#               ^^^^^^^^^^^^ source.hcl meta.block.hcl variable.other.enummember.hcl
#                           ^ source.hcl meta.block.hcl
#                            ^ source.hcl meta.block.hcl punctuation.section.block.begin.hcl
#                             ^ source.hcl meta.block.hcl punctuation.section.block.end.hcl

The parsing should be the following.

>post-processor "docker-tag" {}
#^^^^^^^^^^^^^^ source.hcl meta.block.hcl entity.name.type.hcl
#              ^ source.hcl meta.block.hcl
#               ^^^^^^^^^^^^ source.hcl meta.block.hcl variable.other.enummember.hcl
#                           ^ source.hcl meta.block.hcl
#                            ^ source.hcl meta.block.hcl punctuation.section.block.begin.hcl
#                             ^ source.hcl meta.block.hcl punctuation.section.block.end.hcl

Improve highlighting of built-in functions

The current version of the Terraform language grammar contains a list of built-in functions. However, as we don't know which version of Terraform a user uses, it is highly possible that the list is either incomplete or contains removed functions.

https://github.com/hashicorp/vscode-terraform/blob/562c7cd7b27b5599b4fb1d4ae21b4fc63639dd91/syntaxes/terraform.tmGrammar.json#L750

To improve the syntax highlighting of built-in functions, we should remove the static list from the grammar file and use semantic token highlighting via the LS. The language server has a better understanding of which Terraform version is used and which functions are available in this version.

Support provider-defined functions syntax

Background

We currently only have a static list of valid function names in the Terraform grammar. Provider-defined functions introduce a new syntax for function calls, provider::aws::noop(). Also, it's impossible to compile all function names as a static list in the grammar, so we'll just assume that any function call with this new snytax is valid.

Proposal

  • Update Terraforms functions grammar block, e.g.
  functions:
    begin: ([:\w]+)(\()
    name: meta.function-call.hcl
    comment: Built-in and provider defined function calls
    beginCaptures:
      "1":
        patterns:
          - match: \b(abs|abspath|...|zipmap)\b
            name: support.function.builtin.terraform
          - match: \b(provider::\w+::\w+)\b
            name: support.function.provider
      "2":
        name: punctuation.section.parens.begin.hcl
    end: \)
  • Add some tests for the new syntax

Document use of grammars in template/expression context

History

The main context in which we expect HCL/Terraform grammars to be used is to highlight whole HCL "bodies". For example

attr = "foobar"
block "label" {
  another = 42
}
ref = data.aws_instance.foo.tags["noot"]

The "expression" on the RHS after the = is part of the existing grammars and we happen to treat standalone expressions, such as

42
"foobar"
data.aws_instance.foo.tags["noot"]

The decision to treat standalone expressions as valid was mostly pragmatic, where it was easier to do it than not to, due to the way TextMate grammars and nesting inside works.

To date however, this was a rather "hidden feature".

Potential

There are context in which this can be genuinely useful. For example:

Proposal

  • Ensure we have this use case covered by tests
  • Document this use case clearly in the Readme

First segment of references and object contents mis-highlighted

Extension Version

v2.26.20230511

VS Code Version

Version: 1.79.1 (user setup)
Commit: 4cb974a7aed77a74c7813bdccd99ee0d04901215
Date: 2023-06-12T16:14:05.102Z
Electron: 22.5.7
Chromium: 108.0.5359.215
Node.js: 16.17.1
V8: 10.8.168.25-electron.0
OS: Windows_NT x64 10.0.19044

Operating System

Windows 10

Steps to Reproduce

Setup files as below - note the colours in the main.pkr.hcl file for:

    repo          = var.GITHUB_REPOSITORY
    branch        = var.REF_NAME
    event_type    = var.EVENT_NAME

Expected Behavior

Colours should be correct.

Actual Behavior

Colours incorrect on lines 12/13/14.

image

Configuration

file.pkr.hcl

source "amazon-ebs" "nat-ubuntu" {
  ami_name      = "digital-images-nat-ubuntu-${local.timestamp}"
  source_ami    = data.amazon-ami.nat-ubuntu.id
  instance_type = "t4g.micro"
  region        = "eu-west-1"
  ssh_username  = "ubuntu"
  ami_regions   = var.ami_regions

  tags = {
    base_ami_id   = "{{ .SourceAMI }}"
    base_ami_name = "{{ .SourceAMIName }}"
    repo          = var.GITHUB_REPOSITORY
    branch        = var.REF_NAME
    event_type    = var.EVENT_NAME
    production    = var.REF_NAME == "main" ? "true" : "false"
  }

  vpc_filter {
    filters = {
      "isDefault" : "false"
    }
  }
  subnet_filter {
    filters = {
      "tag:Name" : "primary*"
    }
    random = true
  }

  ami_users = var.accounts
}

variable.pkr.hcl

variable "accounts" {
  type = list(string)

  default = []
}

variable "ami_regions" {
  type = list(string)

  default = [
    "us-east-1",
    "eu-central-1",
    "eu-west-2",
    "sa-east-1",
  ]
}

variable "GITHUB_REPOSITORY" {
  description = "GitHub repo"

  type = string

  default = "Hogarth-Worldwide/terraform-aws-amis-digital"
}

variable "REF_NAME" {
  description = "GitHub branch"

  type = string

  default = "local_running"
}

variable "EVENT_NAME" {
  description = "GitHub event name"

  type = string

  default = "local_running"
}

Switch GitHub highlighting to `hashicorp/syntax`

Background

Currently GitHub uses https://github.com/alexlouden/Terraform.tmLanguage for highlighting HCL:

https://github.com/github/linguist/blob/cddf7476af4c95d1572956ffc5c0cb84f7e431c5/lib/linguist/languages.yml#L2384-L2399

That project is primarily used for highlighting in Sublime Text and has also limited maintenance capacity as per SublimeText/Terraform#36

Proposal

Raise PR to github/linguist to:

  • switch GitHub's highlighting of HCL to hcl grammar in this repo
  • add GitHub's highlighting of Sentinel via grammar in this repo

Adjust highlighting of "constants" like `var` and `locale`

The current grammar defines keywords for referencing other configuration parts as constants.

https://github.com/hashicorp/vscode-terraform/blob/59174bd3e9a66c177a0f2de5751595d3f1cec838/syntaxes/terraform.tmGrammar.json#L39-L43

For example, the grammar highlights the var keyword different from the .variable_name.
CleanShot 2022-02-15 at 17 51 29

When the language server is done processing all files, we have more information about the available variables and semantic tokens adjust highlighting accordingly.
CleanShot 2022-02-15 at 17 54 09

This behavior is confusing, as seen in hashicorp/vscode-terraform#938

It is proposed to update the grammar to highlight the keywords with the same scope as the following names. Then in a separate language server issue (hashicorp/terraform-ls#805), improve the highlighting of invalid references with the help of semantic tokens.

Related to #25

Mis-highlighting after `for` expression

While comparing different grammars, I discovered that we don't handle multi-line for-expressions correctly.

After line 3, the highlighting breaks (theme: GitHub Dark Default)
CleanShot 2024-03-21 at 11 12 18@2x

Bad highlighting when resource dot number notation is used in template string

Server Version

0.27.0

Terraform Version

Terraform v1.1.9
on windows_amd64

Client Version

VS Code

Terraform Configuration Files

locals {
  a = ["foo"]
}
output "foo" {
  value = {
    foo = "${local.a.0}a"
    bar = "This is not highlighted as a string"
  }
}

Log Output

https://gist.github.com/orgads/9e2edc3d4ab85de5beaeba113077ae63

Expected Behavior

a after the closing brace should be highlighted as a string, and bar should be highlighted as a symbol

Actual Behavior

image

Steps to Reproduce

Open VS Code and paste the code above.

Notice that changing local.a.0 to local.a[0] solves the issue.

Migrate terraform grammar to syntax repo

  • Copy terraform.tmGrammar.json from vscode-terraform to syntax repo
  • Copy tmgrammar tests from vscode-terraform to syntax repo
  • Copy tmgrammar GitHub Action test yaml to syntax repo
  • Release artifact

Improve highlighting of primitive type declarations

Problem Statement

This is to follow up on hashicorp/terraform-ls#827 which introduces semantic highlighting of type declarations.

Type declarations are highlighted by the server as keyword.

Our grammar currently highlights them as storage.type which seems to result in a different association in the default VSCode themes.

https://github.com/hashicorp/vscode-terraform/blob/c8b0154b8d2cc4cd67b4e68065ad6b85f8e133a8/syntaxes/terraform.tmGrammar.json#L49-L53

Grammar (only) Highlighting

Screenshot 2022-03-07 at 12 26 20

Semantic Highlighting

Screenshot 2022-03-07 at 12 27 53

Expected User Experience

Grammar and semantic highlighting are more aligned, i.e. type declarations are highlighted as keywords in the grammar too.

Proposal

Update terraform_type_keywords matcher?

Incorrect highlighting for `=>`

We highlight => with two different scopes when it's not part of a single-line for-expression

CleanShot 2024-03-21 at 11 16 24@2x

Proposal: Introduce => as separate keyword.operator.hcl

Reflect 1.4 / 1.5 Terraform language changes in grammar

New blocks may need to be introduced here

- match: \bresource|provider|variable|output|locals|module|data|terraform\b

and new functions here

- match: abspath|abs|ceil|floor|log|max|min|pow|signum|chomp|formatlist|indent|join|lower|regexall|regex|replace|split|strrev|substr|title|trimspace|upper|chunklist|coalescelist|coalesce|compact|concat|contains|distinct|element|flatten|index|keys|length|lookup|matchkeys|merge|range|reverse|setintersection|setproduct|setunion|slice|sort|transpose|values|zipmap|base64decode|base64encode|base64gzip|csvdecode|jsondecode|jsonencode|urlencode|yamldecode|yamlencode|dirname|pathexpand|basename|fileexists|fileset|filebase64|templatefile|formatdate|timeadd|timestamp|base64sha256|base64sha512|bcrypt|filebase64sha256|filebase64sha512|filemd5|filemd1|filesha256|filesha512|md5|rsadecrypt|sha1|sha256|sha512|uuidv5|uuid|cidrhost|cidrnetmask|cidrsubnet|tobool|tolist|tomap|tonumber|toset|tostring|file|format

Create an accurate Terraform & HCL grammar for PrismJS

Background

HCL and Terraform languages evolve over time and the existing community-maintained PrismJS grammar doesn't accurately capture the state of these languages or relationship between HCL and Terraform.

In particular they seem to be treated as the same language, where any HCL config (such as Packer) highlights Terraform keywords:
https://github.com/PrismJS/prism/blob/c2f6a64426f44497a675cb32dccb079b3eff1609/components/prism-hcl.js

Proposal

Decouple Readme based on use cases

I'm not tied to filenames, but from your response we appear to be in agreement that this README should be a landing page and not a catalogue of all the different sets of knowledge required to use the files in this repo.

Extrapolating from your thoughts, I think we need:

  • README.md with sections briefly explaining the repo and the different types of uses cases. Each with links to get users/contributors where they need to go.
  • USAGE.md document outlining expected ways to consume these files
  • CONTRIBUTING.md document outlining what content we accept.

Originally posted by @jpogran in #11 (comment)

Consider highlighting grammar for function signatures

Context

As part of hashicorp/terraform-ls#37 we discovered that there's need for rendering function signatures in a markdown hover popup. Because signatures aren't technically valid HCL, the existing grammar(s) do not highlight it particularly well. Specifically, the grammar cannot distinguish between type declaration and parameter name.

Screenshot 2023-03-23 at 09 17 01

Screenshot 2023-03-23 at 09 18 16

Proposal

  • Explore the option of a separate small grammar to highlight just function signatures
  • Discuss and agree on a stable/predictable way of rendering the signatures - e.g. how to present types (set(string) vs set of string; any single type vs dynamic etc.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.