Support for expressions (literal, tuple, map, keyword) #16
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This (big 😅 ) PR introduces support for some expression constraints, specifically:
LiteralTypeExpr
- any literal value of specificcty.Type
LiteralValue
- specific (static)cty.Value
TupleConsExpr
- HCL's representation ofcty.List/Set/Tuple
. For the time being we treat it as "list" in the sense that we set the same constraints for any/all elements of the tuple. This will likely need to be revisited to support in-expression completion (so that e.g. we know whether to provide completion candidates for values which are already declared).MapExpr
- one of HCL's representation ofcty.Map
. In reality{ }
is always parsed ashclsyntax.ObjectConsExpr
though. I don't know of a use case forObjectConsExpr
yet, but I assume we can add it later. The map is assumed to havestring
keys, which for the purposes of completion is IMO reasonable limitation.KeywordExpr
- keywords, usually represented as unquoted strings, e.g.provider_sensitive_attrs
inexperiments
of theterraform
block in TerraformCompletion
The completion implementation was simplified in finding matching constraints. It just finds any first match and uses it. This may be naive, but works just fine for the above simple types which are hardly ever going to be combined in a single expression/position. This would most likely need to be revisited before adding address/traversal support, depending on how we express such expressions in the schema.
While LSP doesn't (yet?) have item kind for every type, but there is IMO no harm in returning such granular kinds (e.g. string, bool, number, map, ...). The language server can translate these into what LSP support today and if support improves, we can just update the translation logic there.
Semantic Tokens
Initially I was tempted to expose structural tokens, such as whole maps, lists etc. or somehow expose the location of braces/brackets, but according to what I saw being rendered in the client and what token types are natively supported in LSP, such tokens are not meant to be reported, at least not at this current stage. One of the problems I ran into was overlapping token ranges which the client wasn't able to handle well.
Therefore only primitive types within structures are recognized, such as map/object keys and type of the value.
Expression Types
List, set or tuple can practically be represented as
LiteralTypeExpr{cty.List/Set/Tuple}
orTupleConsExpr{}
, with some limitations:TupleConsExpr
(represented as[ ]
) but not forLiteralTypeExpr
. This is mostly a temporary limitation to allow shipping an MVP.TupleConsExpr
can be used to express collection of non-literal expressions, such as keywordsTupleConsExpr
can have its ownName
(used in contexts where we'd typically usecty.Type.FriendlyName()
)TupleConsExpr
can have its ownDescription
(used in completion)Map can practically be represented as
LiteralTypeExpr{cty.Map}
orMapExpr{}
, with some limitations:MapExpr
can be used to express a map of non-literal expressions, such as keywordsMapExpr
can have its ownName
(used in contexts where we'd typically usecty.Type.FriendlyName()
)MapExpr
can have its ownDescription
(used in completion)