Skip to content

Commit

Permalink
update Function TokensForListTokens to TokensForTuple
Browse files Browse the repository at this point in the history
remove Function `TokensForListTraversal`
update Function `TokensForObject` and add new struct
add Function `TokensForFunctionCall`
  • Loading branch information
incubator4 committed Dec 23, 2021
1 parent fcbba7b commit fdcfd19
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 87 deletions.
73 changes: 38 additions & 35 deletions hclwrite/generate.go
Expand Up @@ -39,22 +39,22 @@ func TokensForTraversal(traversal hcl.Traversal) Tokens {
return toks
}

// TokensForListTraversal returns a sequence of tokens that represents the given
// TokensForTuple returns a sequence of tokens that represents the given
// traversal list.
func TokensForListTraversal(traversalList []hcl.Traversal) Tokens {
func TokensForTuple(elems []Tokens) Tokens {
var toks Tokens
toks = append(toks, &Token{
Type: hclsyntax.TokenOBrack,
Bytes: []byte{'['},
})
for index, traversal := range traversalList {
for index, elem := range elems {
if index > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenComma,
Bytes: []byte{','},
})
}
toks = appendTokensForTraversal(traversal, toks)
toks = appendTokensForTokens(elem, toks)
}

toks = append(toks, &Token{
Expand All @@ -65,56 +65,36 @@ func TokensForListTraversal(traversalList []hcl.Traversal) Tokens {
return toks
}

// TokensForListTokens returns a sequence of tokens that represents the given
// traversal list.
func TokensForListTokens(tokensList []Tokens) Tokens {
var toks Tokens
toks = append(toks, &Token{
Type: hclsyntax.TokenOBrack,
Bytes: []byte{'['},
})
for index, t := range tokensList {
if index > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenComma,
Bytes: []byte{','},
})
}
toks = appendTokensForTokens(t, toks)
func TokensForIdentifier(name string) Tokens {
return Tokens{
&Token{
Type: hclsyntax.TokenIdent,
Bytes: []byte(name),
},
}

toks = append(toks, &Token{
Type: hclsyntax.TokenCBrack,
Bytes: []byte{']'},
})

return toks
}

// TokensForObject returns a sequence of tokens that represents the given
// object contains traversal.
func TokensForObject(tokensMap map[string]Tokens) Tokens {
func TokensForObject(attrs []ObjectAttrTokens) Tokens {
var toks Tokens
toks = append(toks, &Token{
Type: hclsyntax.TokenOBrace,
Bytes: []byte{'{'},
})
if len(tokensMap) > 0 {
if len(attrs) > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
})
}
for key, value := range tokensMap {
toks = append(toks, &Token{
Type: hclsyntax.TokenIdent,
Bytes: []byte(key),
})
for _, attr := range attrs {
toks = appendTokensForTokens(attr.Name, toks)
toks = append(toks, &Token{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
})
toks = appendTokensForTokens(value, toks)
toks = appendTokensForTokens(attr.Value, toks)
toks = append(toks, &Token{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
Expand All @@ -127,6 +107,29 @@ func TokensForObject(tokensMap map[string]Tokens) Tokens {
return toks
}

func TokensForFunctionCall(funcName string, args ...Tokens) Tokens {
var toks Tokens
toks = appendTokensForTokens(TokensForIdentifier(funcName), toks)
toks = append(toks, &Token{
Type: hclsyntax.TokenOParen,
Bytes: []byte{'('},
})
for index, arg := range args {
if index > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenComma,
Bytes: []byte{','},
})
}
toks = appendTokensForTokens(arg, toks)
}
toks = append(toks, &Token{
Type: hclsyntax.TokenCParen,
Bytes: []byte{')'},
})
return toks
}

func appendTokensForValue(val cty.Value, toks Tokens) Tokens {
switch {

Expand Down
106 changes: 54 additions & 52 deletions hclwrite/generate_test.go
Expand Up @@ -537,38 +537,35 @@ func TestTokensForTraversal(t *testing.T) {
}
}

func TestTokensForListTraversal(t *testing.T) {
func TestTokensForTuple(t *testing.T) {
tests := []struct {
Val []hcl.Traversal
Val []Tokens
Want Tokens
}{
{
[]hcl.Traversal{
{
[]Tokens{
TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "root"},
hcl.TraverseAttr{Name: "attr"},
},
{
hcl.TraverseRoot{Name: "second"},
hcl.TraverseAttr{Name: "attr"},
},
}),
TokensForValue(cty.StringVal("foo")),
},
Tokens{
{Type: hclsyntax.TokenOBrack, Bytes: []byte{'['}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("root")},
{Type: hclsyntax.TokenDot, Bytes: []byte(".")},
{Type: hclsyntax.TokenIdent, Bytes: []byte("attr")},
{Type: hclsyntax.TokenComma, Bytes: []byte{','}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("second")},
{Type: hclsyntax.TokenDot, Bytes: []byte(".")},
{Type: hclsyntax.TokenIdent, Bytes: []byte("attr")},
{Type: hclsyntax.TokenOQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte("foo")},
{Type: hclsyntax.TokenCQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenCBrack, Bytes: []byte{']'}},
},
},
}

for _, test := range tests {
got := TokensForListTraversal(test.Val)
got := TokensForTuple(test.Val)

if !cmp.Equal(got, test.Want) {
diff := cmp.Diff(got, test.Want, cmp.Comparer(func(a, b []byte) bool {
Expand All @@ -585,35 +582,51 @@ func TestTokensForListTraversal(t *testing.T) {
}
}

func TestTokensForListToken(t *testing.T) {
func TestTokensForObject(t *testing.T) {
tests := []struct {
Val []Tokens
Val []ObjectAttrTokens
Want Tokens
}{
{
[]Tokens{
TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "root"},
hcl.TraverseAttr{Name: "attr"},
}),
TokensForValue(cty.StringVal("foo")),
[]ObjectAttrTokens{
{
Name: TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "foo"},
}),
Value: TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "root"},
hcl.TraverseAttr{Name: "attr"},
}),
},
{
Name: TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "bar"},
}),
Value: TokensForValue(cty.StringVal("baz")),
},
},
Tokens{
{Type: hclsyntax.TokenOBrack, Bytes: []byte{'['}},
{Type: hclsyntax.TokenOBrace, Bytes: []byte{'{'}},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("foo")},
{Type: hclsyntax.TokenEqual, Bytes: []byte{'='}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("root")},
{Type: hclsyntax.TokenDot, Bytes: []byte(".")},
{Type: hclsyntax.TokenIdent, Bytes: []byte("attr")},
{Type: hclsyntax.TokenComma, Bytes: []byte{','}},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("bar")},
{Type: hclsyntax.TokenEqual, Bytes: []byte{'='}},
{Type: hclsyntax.TokenOQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte("foo")},
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte("baz")},
{Type: hclsyntax.TokenCQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenCBrack, Bytes: []byte{']'}},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenCBrace, Bytes: []byte{'}'}},
},
},
}

for _, test := range tests {
got := TokensForListTokens(test.Val)
got := TokensForObject(test.Val)

if !cmp.Equal(got, test.Want) {
diff := cmp.Diff(got, test.Want, cmp.Comparer(func(a, b []byte) bool {
Expand All @@ -630,42 +643,31 @@ func TestTokensForListToken(t *testing.T) {
}
}

func TestTokensForObject(t *testing.T) {
func TestTokensForFunctionCall(t *testing.T) {
tests := []struct {
Val map[string]Tokens
Want Tokens
FuncName string
Val []Tokens
Want Tokens
}{
{
map[string]Tokens{
"foo": TokensForTraversal(hcl.Traversal{
hcl.TraverseRoot{Name: "root"},
hcl.TraverseAttr{Name: "attr"},
}),
"bar": TokensForValue(cty.StringVal("baz")),
"list",
[]Tokens{
TokensForIdentifier("string"),
TokensForIdentifier("int"),
},
Tokens{
{Type: hclsyntax.TokenOBrace, Bytes: []byte{'{'}},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("foo")},
{Type: hclsyntax.TokenEqual, Bytes: []byte{'='}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("root")},
{Type: hclsyntax.TokenDot, Bytes: []byte(".")},
{Type: hclsyntax.TokenIdent, Bytes: []byte("attr")},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("bar")},
{Type: hclsyntax.TokenEqual, Bytes: []byte{'='}},
{Type: hclsyntax.TokenOQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte("baz")},
{Type: hclsyntax.TokenCQuote, Bytes: []byte(`"`)},
{Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}},
{Type: hclsyntax.TokenCBrace, Bytes: []byte{'}'}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("list")},
{Type: hclsyntax.TokenOParen, Bytes: []byte{'('}},
{Type: hclsyntax.TokenIdent, Bytes: []byte("string")},
{Type: hclsyntax.TokenComma, Bytes: []byte(",")},
{Type: hclsyntax.TokenIdent, Bytes: []byte("int")},
{Type: hclsyntax.TokenCParen, Bytes: []byte(")")},
},
},
}

for _, test := range tests {
got := TokensForObject(test.Val)
t.Log(got)
got := TokensForFunctionCall(test.FuncName, test.Val...)

if !cmp.Equal(got, test.Want) {
diff := cmp.Diff(got, test.Want, cmp.Comparer(func(a, b []byte) bool {
Expand Down
7 changes: 7 additions & 0 deletions hclwrite/tokens.go
Expand Up @@ -23,6 +23,13 @@ type Token struct {
SpacesBefore int
}

// ObjectAttrTokens is a composite type which contains name and value for
// key/value pair, which converted to raw tokens so any type can be used
type ObjectAttrTokens struct {
Name Tokens
Value Tokens
}

// asHCLSyntax returns the receiver expressed as an incomplete hclsyntax.Token.
// A complete token is not possible since we don't have source location
// information here, and so this method is unexported so we can be sure it will
Expand Down

0 comments on commit fdcfd19

Please sign in to comment.