From 47260b279327755e39ae0bcca988b4216903ea4f Mon Sep 17 00:00:00 2001 From: Isabel Andrade Date: Mon, 7 Jun 2021 09:39:25 +0100 Subject: [PATCH] Add type declarations for variable `type` So that completion, hover and semantic-tokens work for variable `type`. Related to hashicorp/terraform-ls#490 --- decoder/expression_candidates.go | 22 ++++ decoder/expression_candidates_test.go | 160 ++++++++++++++++++++++++++ decoder/expression_constraints.go | 9 ++ decoder/hover.go | 16 +++ schema/expressions.go | 14 +++ 5 files changed, 221 insertions(+) diff --git a/decoder/expression_candidates.go b/decoder/expression_candidates.go index 38736b48..5b2dda41 100644 --- a/decoder/expression_candidates.go +++ b/decoder/expression_candidates.go @@ -287,6 +287,28 @@ func (d *Decoder) constraintToCandidates(constraint schema.ExprConstraint, outer }, }) } + case schema.TypeDeclarationExpr: + for _, t := range []string{ + "bool", + "number", + "string", + "list()", + "set()", + "tuple()", + "map()", + "object()", + } { + candidates = append(candidates, lang.Candidate{ + Label: t, + Detail: t, + Kind: lang.AttributeCandidateKind, + TextEdit: lang.TextEdit{ + NewText: t, + Snippet: t, + Range: editRng, + }, + }) + } } return candidates diff --git a/decoder/expression_candidates_test.go b/decoder/expression_candidates_test.go index bd8fb45c..2e3a4443 100644 --- a/decoder/expression_candidates_test.go +++ b/decoder/expression_candidates_test.go @@ -1281,6 +1281,166 @@ func TestDecoder_CandidateAtPos_expressions(t *testing.T) { hcl.Pos{Line: 1, Column: 8, Byte: 7}, lang.ZeroCandidates(), }, + { + "type declaration", + map[string]*schema.AttributeSchema{ + "attr": { + Expr: schema.ExprConstraints{ + schema.TypeDeclarationExpr{}, + }, + }, + }, + `attr = +`, + hcl.Pos{Line: 1, Column: 8, Byte: 7}, + lang.CompleteCandidates([]lang.Candidate{ + { + Label: "bool", + Detail: "bool", + TextEdit: lang.TextEdit{ + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "bool", Snippet: "bool"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "number", + Detail: "number", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "number", Snippet: "number"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "string", + Detail: "string", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "string", Snippet: "string"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "list()", + Detail: "list()", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "list()", Snippet: "list()"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "set()", + Detail: "set()", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "set()", Snippet: "set()"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "tuple()", + Detail: "tuple()", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "tuple()", Snippet: "tuple()"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "map()", + Detail: "map()", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "map()", Snippet: "map()"}, + Kind: lang.AttributeCandidateKind, + }, + { + Label: "object()", + Detail: "object()", + TextEdit: lang.TextEdit{Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + End: hcl.Pos{ + Line: 1, + Column: 8, + Byte: 7, + }, + }, NewText: "object()", Snippet: "object()"}, + Kind: lang.AttributeCandidateKind, + }, + }), + }, } for i, tc := range testCases { diff --git a/decoder/expression_constraints.go b/decoder/expression_constraints.go index d86026d6..407cbc04 100644 --- a/decoder/expression_constraints.go +++ b/decoder/expression_constraints.go @@ -219,3 +219,12 @@ func (ec ExprConstraints) LiteralValueOfObjectConsExpr(expr *hclsyntax.ObjectCon return schema.LiteralValue{}, false } + +func (ec ExprConstraints) TypeDeclarationExpr() (schema.TypeDeclarationExpr, bool) { + for _, c := range ec { + if td, ok := c.(schema.TypeDeclarationExpr); ok { + return td, ok + } + } + return schema.TypeDeclarationExpr{}, false +} diff --git a/decoder/hover.go b/decoder/hover.go index 89c8fcd9..5ffdc0f7 100644 --- a/decoder/hover.go +++ b/decoder/hover.go @@ -246,6 +246,22 @@ func (d *Decoder) hoverDataForExpr(expr hcl.Expression, constraints ExprConstrai Range: expr.Range(), }, nil } + + _, ok = constraints.TypeDeclarationExpr() + if ok { + return &lang.HoverData{ + Content: lang.Markdown("Type declaration"), + Range: expr.Range(), + }, nil + } + case *hclsyntax.FunctionCallExpr: + _, ok := constraints.TypeDeclarationExpr() + if ok { + return &lang.HoverData{ + Content: lang.Markdown("Type declaration"), + Range: expr.Range(), + }, nil + } case *hclsyntax.TemplateExpr: if e.IsStringLiteral() { data, err := d.hoverDataForExpr(e.Parts[0], constraints, nestingLvl, pos) diff --git a/schema/expressions.go b/schema/expressions.go index 0a2884ae..aea25739 100644 --- a/schema/expressions.go +++ b/schema/expressions.go @@ -384,3 +384,17 @@ func LiteralTypeOnly(t cty.Type) ExprConstraints { LiteralTypeExpr{Type: t}, } } + +type TypeDeclarationExpr struct{} + +func (TypeDeclarationExpr) isExprConstraintImpl() exprConstrSigil { + return exprConstrSigil{} +} + +func (td TypeDeclarationExpr) FriendlyName() string { + return "type" +} + +func (td TypeDeclarationExpr) Copy() ExprConstraint { + return TypeDeclarationExpr{} +}