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 24, 2023
1 parent 53a54c3 commit 0ab5255
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 5 deletions.
12 changes: 12 additions & 0 deletions decoder/expr_list_or_set_elem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package decoder

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

type listOrSetElem struct {
expr *hclsyntax.TupleConsExpr
elemCons schema.Constraint
pathCtx *PathContext
}
57 changes: 57 additions & 0 deletions decoder/expr_list_or_set_elem_completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package decoder

import (
"context"
"strings"

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

func (los listOrSetElem) CompletionAtPos(ctx context.Context, pos hcl.Pos) []lang.Candidate {
betweenBraces := hcl.Range{
Filename: los.expr.Range().Filename,
Start: los.expr.OpenRange.End,
End: hcl.Pos{
// account for the brace as the last character
Line: los.expr.Range().End.Line,
Column: los.expr.Range().End.Column - 1,
Byte: los.expr.Range().End.Byte - 1,
},
}

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

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

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

fileBytes := los.pathCtx.Files[los.expr.Range().Filename].Bytes
b := rng.SliceBytes(fileBytes)
if strings.TrimSpace(string(b)) != "," {
return []lang.Candidate{}
}

expr := newEmptyExpressionAtPos(los.expr.Range().Filename, pos)
elemCons := newExpression(los.pathCtx, expr, los.elemCons)
return elemCons.CompletionAtPos(ctx, pos)
}

return []lang.Candidate{}
}
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
57 changes: 57 additions & 0 deletions decoder/expr_set_completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package decoder

import (
"context"
"fmt"

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

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

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

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

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

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

suspectElem := listOrSetElem{
expr: eType,
elemCons: s.cons.Elem,
pathCtx: s.pathCtx,
}
return suspectElem.CompletionAtPos(ctx, pos)
}

0 comments on commit 0ab5255

Please sign in to comment.