Skip to content

Commit

Permalink
Add type declarations for variable type
Browse files Browse the repository at this point in the history
So that completion, hover and semantic-tokens work for variable `type`.

Related to hashicorp/terraform-ls#490
  • Loading branch information
beandrad committed Jun 7, 2021
1 parent 283182c commit 09c4e3d
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 0 deletions.
22 changes: 22 additions & 0 deletions decoder/expression_candidates.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
160 changes: 160 additions & 0 deletions decoder/expression_candidates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions decoder/expression_constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
8 changes: 8 additions & 0 deletions decoder/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ 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.TemplateExpr:
if e.IsStringLiteral() {
data, err := d.hoverDataForExpr(e.Parts[0], constraints, nestingLvl, pos)
Expand Down
14 changes: 14 additions & 0 deletions schema/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
}

0 comments on commit 09c4e3d

Please sign in to comment.