Skip to content

Commit

Permalink
decoder: Implement completion for Set
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Jan 25, 2023
1 parent 53a54c3 commit 6075158
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 5 deletions.
5 changes: 0 additions & 5 deletions decoder/expr_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ type Set struct {
pathCtx *PathContext
}

func (s Set) CompletionAtPos(ctx context.Context, pos hcl.Pos) []lang.Candidate {
// TODO
return nil
}

func (s Set) HoverAtPos(ctx context.Context, pos hcl.Pos) *lang.HoverData {
// TODO
return nil
Expand Down
95 changes: 95 additions & 0 deletions decoder/expr_set_completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package decoder

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)

func (set Set) CompletionAtPos(ctx context.Context, pos hcl.Pos) []lang.Candidate {
if isEmptyExpression(set.expr) {
label := "[ ]"
triggerSuggest := false

if set.cons.Elem != nil {
label = fmt.Sprintf("[ %s ]", set.cons.Elem.FriendlyName())
triggerSuggest = true
}

return []lang.Candidate{
{
Label: label,
Detail: set.cons.FriendlyName(),
Kind: lang.SetCandidateKind,
Description: set.cons.Description,
TextEdit: lang.TextEdit{
NewText: "[ ]",
Snippet: "[ ${0} ]",
Range: hcl.Range{
Filename: set.expr.Range().Filename,
Start: pos,
End: pos,
},
},
TriggerSuggest: triggerSuggest,
},
}
}

eType, ok := set.expr.(*hclsyntax.TupleConsExpr)
if !ok {
return []lang.Candidate{}
}

if set.cons.Elem == nil {
return []lang.Candidate{}
}

fileBytes := set.pathCtx.Files[set.expr.Range().Filename].Bytes

betweenBraces := hcl.Range{
Filename: eType.Range().Filename,
Start: eType.OpenRange.End,
End: eType.Range().End,
}

if betweenBraces.ContainsPos(pos) {
if len(eType.Exprs) == 0 {
expr := newEmptyExpressionAtPos(eType.Range().Filename, pos)
return newExpression(set.pathCtx, expr, set.cons.Elem).CompletionAtPos(ctx, pos)
}

// TODO: depending on set.cons.Elem (Keyword, LiteralValue, Reference),
// filter out declared elements to provide uniqueness as that is the nature of set

var lastElemEndPos hcl.Pos
for _, elemExpr := range eType.Exprs {
if elemExpr.Range().ContainsPos(pos) || elemExpr.Range().End.Byte == pos.Byte {
return newExpression(set.pathCtx, elemExpr, set.cons.Elem).CompletionAtPos(ctx, pos)
}
lastElemEndPos = elemExpr.Range().End
}

rng := hcl.Range{
Filename: eType.Range().Filename,
Start: lastElemEndPos,
End: pos,
}

// TODO: test with multi-line element expressions

b := rng.SliceBytes(fileBytes)
if strings.TrimSpace(string(b)) != "," {
return []lang.Candidate{}
}

expr := newEmptyExpressionAtPos(eType.Range().Filename, pos)
return newExpression(set.pathCtx, expr, set.cons.Elem).CompletionAtPos(ctx, pos)
}

return []lang.Candidate{}
}

0 comments on commit 6075158

Please sign in to comment.