Recognize individual expressions when nested
Background (current state)
Through the logic in hcl-lang/schema and related schema in terraform-schema we currently provide completion, hover and semantic highlighting for the outermost expression (with a few exceptions for HCL objects and tuples) and generally don't take into account (potentially infinite) nesting.
Completion
resource "aws_instance" "example" {
ami = # HERE
depends_on = [ HERE ]
}
For ami we can provide completion of any string candidates, for completion within depends_on brackets we can provide references to other resources and data sources.
Hover
resource "aws_instance" "example" {
ami = "test"
depends_on = [ aws_vpc.test ]
}
When hovering over "test" we can match the string constant against schema (string type) and show relevant popup ("test" string). Similarly when hovering over [ aws_vpc.test ] we can match it against schema (set of references) and show relevant popup (set of references).
Semantic Tokens
resource "aws_instance" "example" {
ami = "test"
depends_on = [ aws_vpc.test ]
}
Here "test" is expected to be string (per schema) and aws_vpc.test is expected to be a reference (per schema), so LS will report relevant semantic tokens in both cases.
Use-cases
User would benefit from recognition of arbitrarily nested expressions in all relevant functions of the LS, as described in more detail below.
Completion
resource "aws_instance" "example" {
ami = "ami-${HERE}"
depends_on = [
aws_vpc.test,
# HERE
]
}
within ${} we should provide any compatible expressions (presumably all primitive types).
for the second position we should provide any available references other than aws_vpc.test.
Hover
resource "aws_instance" "example" {
ami = "ami-${data.aws_ami.example.test.image_id}"
depends_on = [
aws_vpc.test,
]
}
when hovering over data.aws_ami.example.test.id we display popup with details about the reference (string The ID of the AMI.)
when hover over aws_vpc.test we display popup with details about the reference (resource).
Semantic Tokens
resource "aws_instance" "example" {
ami = "ami-${data.aws_ami.example.test.image_id}"
cpu_core_count = 2 * var.core_count
}
"ami-${data.aws_ami.example.test.image_id}" is highlighted as a template expression with ami- highlighted as string and data.aws_ami.example.test.image_id as reference.
2 * var.core_count is highlighted as multiplication expression with 2 highlighted as number and var.core_count as a reference.
Proposal
-
hashicorp/hcl-lang- [ ] Deprecate
schema.TupleConsExpr - [ ] Create
Expression interfaceindecodersuch that completion for any expression type can be delegated and each type can also delegate completion of nested expressions to other expression types - [ ] Implement
decoder.NewExpression(expr hcl.Expression, cons schema.ExprConstraints) Expression - [ ] Implement
schema.ObjectTypeDeclItemExpr - [ ] Implement new completion candidate kinds?
- [ ]
lang.PrimitiveTypeDeclExpr - [ ]
lang.ComplexTypeDeclExpr - [ ]
lang.ObjectTypeDeclItemExpr
- [ ]
- [ ] Implement
schema.AnyExprOfType{Type: cty.Type}to act as an alias to-
schema.LiteralTypeExpr -
schema.TraversalExpr - (future) dynamically express function calls which return the
Type - (future) dynamically express templates which return the
Type - (future) dynamically express conditional expressions which return the
Type - (future) dynamically express operator expressions which return the
Type
-
- [ ] Implement
LiteralValueExprasdecoder.Expression - [ ] Implement
ScopeTraversalExprasdecoder.Expression(for type declarations, references and keywords) - [ ] Implement
TupleConsExprasdecoder.Expression - [ ] Implement
ObjectConsExprasdecoder.Expression - [ ] Implement (basic)
FunctionCallExprasdecoder.Expression(for type declarations) - [ ] Implement (basic)
TemplateExprasdecoder.Expression - [ ] Implement (basic)
TemplateWrapExprasdecoder.Expression - [ ] Plumb all new
decoder.Expressiontypes intoPathDecoder-CandidatesAtPos - [ ] Plumb all new
decoder.Expressiontypes intoPathDecoder-HoverAtPos - [ ] Plumb all new
decoder.Expressiontypes intoPathDecoder-SemanticTokensInFile
- [ ] Deprecate
type Expression interface {
CandidatesAtPos(ctx context.Context, pos hcl.Pos) []lang.Candidate
HoverAtPos(ctx context.Context, pos hcl.Pos) *lang.HoverData
SemanticTokens(ctx context.Context) []lang.SemanticToken
// TODO: Validate()
}
Prototype WIP: https://github.com/hashicorp/hcl-lang/commit/d21a86326111de083c8adea196252d7bc55d42c5