Skip to content

Commit

Permalink
schema: Implement EmptyCompletionData for LiteralValue
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Jan 4, 2023
1 parent 738dd80 commit c219ee4
Showing 1 changed file with 141 additions and 2 deletions.
143 changes: 141 additions & 2 deletions schema/constraint_literal_value.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package schema

import (
"fmt"
"sort"
"strconv"
"strings"

"github.com/hashicorp/hcl-lang/lang"
"github.com/zclconf/go-cty/cty"
)
Expand All @@ -15,6 +20,10 @@ type LiteralValue struct {

// Description defines description of the value
Description lang.MarkupContent

// nestingLvl represents current level of nesting
// used for correctly indenting complex types.
nestingLvl int
}

func (LiteralValue) isConstraintImpl() constraintSigil {
Expand All @@ -34,6 +43,136 @@ func (lv LiteralValue) Copy() Constraint {
}

func (lv LiteralValue) EmptyCompletionData(nextPlaceholder int) CompletionData {
// TODO
return CompletionData{}
// primitive types
switch lv.Value.Type() {
case cty.String:
return CompletionData{
NewText: fmt.Sprintf("%q", lv.Value.AsString()),
Snippet: fmt.Sprintf(`"${%d:%s}"`, nextPlaceholder, lv.Value.AsString()),
LastPlaceholder: nextPlaceholder,
}
case cty.Bool:
return CompletionData{
NewText: fmt.Sprintf("%t", lv.Value.True()),
Snippet: fmt.Sprintf(`${%d:%t}`, nextPlaceholder, lv.Value.True()),
LastPlaceholder: nextPlaceholder,
}
case cty.Number:
return CompletionData{
NewText: formatNumberVal(lv.Value),
Snippet: fmt.Sprintf(`${%d:%s}`, nextPlaceholder, formatNumberVal(lv.Value)),
LastPlaceholder: nextPlaceholder,
}
}

// complex types typically span multiple lines, so indenting matters
indent := strings.Repeat(" ", lv.nestingLvl+1)
endBraceIndent := strings.Repeat(" ", lv.nestingLvl)

// TODO: Why do we not indent NewText same way as Snippet?

if lv.Value.Type().IsMapType() {
newText := "{\n"
snippet := "{\n"

valueMap := lv.Value.AsValueMap()
mapKeys := sortedKeysOfValueMap(valueMap)
for _, key := range mapKeys {
elCons := LiteralValue{
Value: valueMap[key],
nestingLvl: lv.nestingLvl + 1,
}
elCd := elCons.EmptyCompletionData(nextPlaceholder)

newText += fmt.Sprintf(" %q = %s\n", key, elCd.NewText)
snippet += fmt.Sprintf("%s%q = %s\n", indent, key, elCd.Snippet)
}
newText += "}"
snippet += fmt.Sprintf("%s}", endBraceIndent)

return CompletionData{
NewText: newText,
Snippet: snippet,
LastPlaceholder: nextPlaceholder,
}
}

if lv.Value.Type().IsObjectType() {
newText := "{\n"
snippet := "{\n"

attrNames := sortedObjectAttrNames(lv.Value.Type())

for _, name := range attrNames {
elCons := LiteralValue{
Value: lv.Value.GetAttr(name),
nestingLvl: lv.nestingLvl + 1,
}
elCd := elCons.EmptyCompletionData(nextPlaceholder)

newText += fmt.Sprintf(" %s = %s\n", name, elCd.NewText)
snippet += fmt.Sprintf("%s%s = %s\n", indent, name, elCd.Snippet)
}

newText += "}"
snippet += fmt.Sprintf("%s}", endBraceIndent)

return CompletionData{
NewText: newText,
Snippet: snippet,
LastPlaceholder: nextPlaceholder,
}
}

if lv.Value.Type().IsListType() || lv.Value.Type().IsSetType() || lv.Value.Type().IsTupleType() {
newText := "[\n"
snippet := "[\n"

for _, elem := range lv.Value.AsValueSlice() {
elCons := LiteralValue{
Value: elem,
nestingLvl: lv.nestingLvl + 1,
}
elCd := elCons.EmptyCompletionData(nextPlaceholder)

newText += fmt.Sprintf(" %s,\n", elCd.NewText)
snippet += fmt.Sprintf("%s%s,\n", indent, elCd.Snippet)
}

newText += "]"
snippet += fmt.Sprintf("%s]", endBraceIndent)

return CompletionData{
NewText: newText,
Snippet: snippet,
LastPlaceholder: nextPlaceholder,
}
}

return CompletionData{
NewText: "",
Snippet: "",
LastPlaceholder: nextPlaceholder,
}
}

func sortedKeysOfValueMap(m map[string]cty.Value) []string {
keys := make([]string, 0)
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}

func formatNumberVal(val cty.Value) string {
bf := val.AsBigFloat()

if bf.IsInt() {
intNum, _ := bf.Int64()
return fmt.Sprintf("%d", intNum)
}

fNum, _ := bf.Float64()
return strconv.FormatFloat(fNum, 'f', -1, 64)
}

0 comments on commit c219ee4

Please sign in to comment.