Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for expressions (literal, tuple, map, keyword) #16

Merged
merged 1 commit into from
Feb 25, 2021

Conversation

radeksimko
Copy link
Member

@radeksimko radeksimko commented Feb 19, 2021

This (big 😅 ) PR introduces support for some expression constraints, specifically:

  • LiteralTypeExpr - any literal value of specific cty.Type
  • LiteralValue - specific (static) cty.Value
  • TupleConsExpr - HCL's representation of cty.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 of cty.Map. In reality { } is always parsed as hclsyntax.ObjectConsExpr though. I don't know of a use case for ObjectConsExpr yet, but I assume we can add it later. The map is assumed to have string keys, which for the purposes of completion is IMO reasonable limitation.
  • KeywordExpr - keywords, usually represented as unquoted strings, e.g. provider_sensitive_attrs in experiments of the terraform block in Terraform

Completion

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} or TupleConsExpr{}, with some limitations:

  • We provide completion inside an empty TupleConsExpr (represented as [ ]) but not for LiteralTypeExpr. This is mostly a temporary limitation to allow shipping an MVP.
  • TupleConsExpr can be used to express collection of non-literal expressions, such as keywords
  • TupleConsExpr can have its own Name (used in contexts where we'd typically use cty.Type.FriendlyName())
  • TupleConsExpr can have its own Description (used in completion)

Map can practically be represented as LiteralTypeExpr{cty.Map} or MapExpr{}, with some limitations:

  • MapExpr can be used to express a map of non-literal expressions, such as keywords
  • MapExpr can have its own Name (used in contexts where we'd typically use cty.Type.FriendlyName())
  • MapExpr can have its own Description (used in completion)

@radeksimko radeksimko added the enhancement New feature or request label Feb 19, 2021
@radeksimko radeksimko changed the title Add expression support for literal values Support for expressions (literal, tuple, map, keyword) Feb 19, 2021
@radeksimko radeksimko force-pushed the f-expressions branch 10 times, most recently from 998237c to 521751f Compare February 22, 2021 18:00
@radeksimko radeksimko marked this pull request as ready for review February 22, 2021 18:25
@radeksimko radeksimko force-pushed the f-expressions branch 4 times, most recently from 512ed6b to c8b1a98 Compare February 23, 2021 12:18
@@ -1013,7 +1015,7 @@ func TestDecoder_CandidatesAtPos_multipleTypes(t *testing.T) {
expectedCandidates := lang.CompleteCandidates([]lang.Candidate{
{
Label: "for_each",
Detail: "Optional, set of dynamic or map of dynamic",
Detail: "Optional, set of any single type or map of any single type",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just improving the experience here as this is presumably more correct and easier to understand for the end-user.

Copy link

@aeschright aeschright left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@radeksimko radeksimko merged commit 01f0b45 into main Feb 25, 2021
@radeksimko radeksimko deleted the f-expressions branch February 25, 2021 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants