2024-09-09 12:05:45 +00:00
|
|
|
// Copyright 2020-2024, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
package syntax
|
|
|
|
|
|
|
|
import (
|
2020-07-07 20:46:26 +00:00
|
|
|
"bytes"
|
2020-04-03 03:01:14 +00:00
|
|
|
"fmt"
|
2020-04-14 02:11:56 +00:00
|
|
|
"math/big"
|
2023-12-12 12:19:42 +00:00
|
|
|
"strconv"
|
2020-07-07 20:46:26 +00:00
|
|
|
"unicode"
|
|
|
|
"unicode/utf8"
|
2020-04-03 03:01:14 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
)
|
|
|
|
|
|
|
|
var tokenStrings = map[hclsyntax.TokenType]string{
|
|
|
|
hclsyntax.TokenOBrace: "{",
|
|
|
|
hclsyntax.TokenCBrace: "}",
|
|
|
|
hclsyntax.TokenOBrack: "[",
|
|
|
|
hclsyntax.TokenCBrack: "]",
|
|
|
|
hclsyntax.TokenOParen: "(",
|
|
|
|
hclsyntax.TokenCParen: ")",
|
|
|
|
hclsyntax.TokenOQuote: `"`,
|
|
|
|
hclsyntax.TokenCQuote: `"`,
|
|
|
|
|
|
|
|
hclsyntax.TokenStar: "*",
|
|
|
|
hclsyntax.TokenSlash: "/",
|
|
|
|
hclsyntax.TokenPlus: "+",
|
|
|
|
hclsyntax.TokenMinus: "-",
|
|
|
|
hclsyntax.TokenPercent: "%",
|
|
|
|
|
|
|
|
hclsyntax.TokenEqual: "=",
|
|
|
|
hclsyntax.TokenEqualOp: "==",
|
|
|
|
hclsyntax.TokenNotEqual: "!=",
|
|
|
|
hclsyntax.TokenLessThan: "<",
|
|
|
|
hclsyntax.TokenLessThanEq: "<=",
|
|
|
|
hclsyntax.TokenGreaterThan: ">",
|
|
|
|
hclsyntax.TokenGreaterThanEq: ">=",
|
|
|
|
|
|
|
|
hclsyntax.TokenAnd: "&&",
|
|
|
|
hclsyntax.TokenOr: "||",
|
|
|
|
hclsyntax.TokenBang: "!",
|
|
|
|
|
|
|
|
hclsyntax.TokenDot: ".",
|
|
|
|
hclsyntax.TokenComma: ",",
|
|
|
|
|
|
|
|
hclsyntax.TokenEllipsis: "...",
|
|
|
|
hclsyntax.TokenFatArrow: "=>",
|
|
|
|
|
|
|
|
hclsyntax.TokenQuestion: "?",
|
|
|
|
hclsyntax.TokenColon: ":",
|
|
|
|
|
|
|
|
hclsyntax.TokenTemplateInterp: "${",
|
|
|
|
hclsyntax.TokenTemplateControl: "%{",
|
|
|
|
hclsyntax.TokenTemplateSeqEnd: "}",
|
|
|
|
|
|
|
|
hclsyntax.TokenNewline: "\n",
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trivia represents bytes in a source file that are not syntactically meaningful. This includes whitespace and
|
|
|
|
// comments.
|
|
|
|
type Trivia interface {
|
|
|
|
// Range returns the range of the trivia in the source file.
|
|
|
|
Range() hcl.Range
|
|
|
|
// Bytes returns the raw bytes that comprise the trivia.
|
|
|
|
Bytes() []byte
|
|
|
|
|
|
|
|
isTrivia()
|
|
|
|
}
|
|
|
|
|
|
|
|
// TriviaList is a list of trivia.
|
|
|
|
type TriviaList []Trivia
|
|
|
|
|
2020-04-16 23:44:34 +00:00
|
|
|
func (trivia TriviaList) LeadingWhitespace() TriviaList {
|
|
|
|
end := 0
|
|
|
|
for i, t := range trivia {
|
|
|
|
if _, ok := t.(Whitespace); !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
end = i
|
|
|
|
}
|
|
|
|
if end == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return append(TriviaList(nil), trivia[0:end]...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (trivia TriviaList) TrailingWhitespace() TriviaList {
|
|
|
|
start := len(trivia)
|
|
|
|
for i := len(trivia) - 1; i >= 0; i-- {
|
|
|
|
if _, ok := trivia[i].(Whitespace); !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
start = i
|
|
|
|
}
|
|
|
|
if start == len(trivia) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return append(TriviaList(nil), trivia[start:]...)
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
func (trivia TriviaList) CollapseWhitespace() TriviaList {
|
|
|
|
result := make(TriviaList, 0, len(trivia))
|
|
|
|
for _, t := range trivia {
|
|
|
|
if ws, ok := t.(Whitespace); ok {
|
|
|
|
if len(result) != 0 {
|
|
|
|
ws.bytes = []byte{' '}
|
|
|
|
result = append(result, ws)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result = append(result, t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-07-07 20:46:26 +00:00
|
|
|
func (trivia TriviaList) EndsOnNewLine() bool {
|
|
|
|
for _, trivia := range trivia {
|
|
|
|
b := trivia.Bytes()
|
|
|
|
for len(b) > 0 {
|
|
|
|
r, sz := utf8.DecodeLastRune(b)
|
|
|
|
if r == '\n' {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if !unicode.IsSpace(r) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
b = b[:len(b)-sz]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (trivia TriviaList) Index(sep string) (Trivia, int) {
|
|
|
|
s := []byte(sep)
|
|
|
|
for _, trivia := range trivia {
|
|
|
|
if i := bytes.Index(trivia.Bytes(), s); i != -1 {
|
|
|
|
return trivia, i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, -1
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
func (trivia TriviaList) Format(f fmt.State, c rune) {
|
|
|
|
for _, trivia := range trivia {
|
|
|
|
_, err := f.Write(trivia.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comment is a piece of trivia that represents a line or block comment in a source file.
|
|
|
|
type Comment struct {
|
|
|
|
// Lines contains the lines of the comment without leading comment characters or trailing newlines.
|
|
|
|
Lines []string
|
|
|
|
|
|
|
|
rng hcl.Range
|
|
|
|
bytes []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// Range returns the range of the comment in the source file.
|
|
|
|
func (c Comment) Range() hcl.Range {
|
|
|
|
return c.rng
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bytes returns the raw bytes that comprise the comment.
|
|
|
|
func (c Comment) Bytes() []byte {
|
|
|
|
return c.bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Comment) isTrivia() {}
|
|
|
|
|
|
|
|
// Whitespace is a piece of trivia that represents a sequence of whitespace characters in a source file.
|
|
|
|
type Whitespace struct {
|
|
|
|
rng hcl.Range
|
|
|
|
bytes []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewWhitespace returns a new piece of whitespace trivia with the given contents.
|
|
|
|
func NewWhitespace(bytes ...byte) Whitespace {
|
|
|
|
return Whitespace{bytes: bytes}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Range returns the range of the whitespace in the source file.
|
|
|
|
func (w Whitespace) Range() hcl.Range {
|
|
|
|
return w.rng
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bytes returns the raw bytes that comprise the whitespace.
|
|
|
|
func (w Whitespace) Bytes() []byte {
|
|
|
|
return w.bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Whitespace) isTrivia() {}
|
|
|
|
|
|
|
|
// TemplateDelimiter is a piece of trivia that represents a token that demarcates an interpolation or control sequence
|
|
|
|
// inside of a template.
|
|
|
|
type TemplateDelimiter struct {
|
|
|
|
// Type is the type of the delimiter (e.g. hclsyntax.TokenTemplateInterp)
|
|
|
|
Type hclsyntax.TokenType
|
|
|
|
|
|
|
|
rng hcl.Range
|
|
|
|
bytes []byte
|
|
|
|
}
|
|
|
|
|
2020-07-14 19:07:44 +00:00
|
|
|
// NewTemplateDelimiter creates a new TemplateDelimiter value with the given delimiter type. If the token type is not a
|
|
|
|
// template delimiter, this function will panic.
|
|
|
|
func NewTemplateDelimiter(typ hclsyntax.TokenType) TemplateDelimiter {
|
|
|
|
var s string
|
turn on the golangci-lint exhaustive linter (#15028)
Turn on the golangci-lint exhaustive linter. This is the first step
towards catching more missing cases during development rather than
in tests, or in production.
This might be best reviewed commit-by-commit, as the first commit turns
on the linter with the `default-signifies-exhaustive: true` option set,
which requires a lot less changes in the current codebase.
I think it's probably worth doing the second commit as well, as that
will get us the real benefits, even though we end up with a little bit
more churn. However it means all the `switch` statements are covered,
which isn't the case after the first commit, since we do have a lot of
`default` statements that just call `assert.Fail`.
Fixes #14601
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-01-17 16:50:41 +00:00
|
|
|
//nolint:exhaustive // Only some tokens are template delimiters.
|
2020-07-14 19:07:44 +00:00
|
|
|
switch typ {
|
|
|
|
case hclsyntax.TokenTemplateInterp:
|
|
|
|
s = "${"
|
|
|
|
case hclsyntax.TokenTemplateControl:
|
|
|
|
s = "%{"
|
|
|
|
case hclsyntax.TokenTemplateSeqEnd:
|
|
|
|
s = "}"
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("%v is not a template delimiter", typ))
|
|
|
|
}
|
|
|
|
return TemplateDelimiter{
|
|
|
|
Type: typ,
|
|
|
|
bytes: []byte(s),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
// Range returns the range of the delimiter in the source file.
|
|
|
|
func (t TemplateDelimiter) Range() hcl.Range {
|
|
|
|
return t.rng
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bytes returns the raw bytes that comprise the delimiter.
|
|
|
|
func (t TemplateDelimiter) Bytes() []byte {
|
|
|
|
return t.bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (TemplateDelimiter) isTrivia() {}
|
|
|
|
|
|
|
|
// Token represents an HCL2 syntax token with attached leading trivia.
|
|
|
|
type Token struct {
|
|
|
|
Raw hclsyntax.Token
|
|
|
|
LeadingTrivia TriviaList
|
|
|
|
TrailingTrivia TriviaList
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Token) Format(f fmt.State, c rune) {
|
|
|
|
if t.LeadingTrivia != nil {
|
|
|
|
t.LeadingTrivia.Format(f, c)
|
|
|
|
} else if f.Flag(' ') {
|
|
|
|
if _, err := f.Write([]byte{' '}); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bytes := t.Raw.Bytes
|
|
|
|
if str, ok := tokenStrings[t.Raw.Type]; ok {
|
|
|
|
bytes = []byte(str)
|
|
|
|
}
|
|
|
|
if _, err := f.Write(bytes); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
t.TrailingTrivia.Format(f, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Token) AllTrivia() TriviaList {
|
|
|
|
result := make(TriviaList, len(t.LeadingTrivia)+len(t.TrailingTrivia))
|
gosimple: Simplify loops
This replaces for loops and slice appends reported by gosimple
with simpler variants.
Specifically,
for _, x := range src {
dst = append(dst, x)
}
// can be replaced with
dst = append(dst, src...)
And,
for i, x := range src {
dst[i] = x
}
// can be replaced with
copy(dst, src)
And,
for true { ... }
// can be replaced with
for { ... }
And, given a string `s`,
for _, r := range []rune(s) { .. }
// can be replaced with
for _, r := range s { .. }
Lastly, this fixes in ineffective break statement
also reported by the linter.
Inside a switch block,
`break` affects the current `case` only.
The outer loop needs a label.
2023-01-11 15:58:17 +00:00
|
|
|
copy(result, t.LeadingTrivia)
|
|
|
|
copy(result[len(t.LeadingTrivia):], t.TrailingTrivia)
|
2020-04-03 03:01:14 +00:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// Range returns the total range covered by this token and any leading trivia.
|
|
|
|
func (t Token) Range() hcl.Range {
|
|
|
|
start := t.Raw.Range.Start
|
|
|
|
if len(t.LeadingTrivia) > 0 {
|
|
|
|
start = t.LeadingTrivia[0].Range().Start
|
|
|
|
}
|
|
|
|
end := t.Raw.Range.End
|
|
|
|
if len(t.TrailingTrivia) > 0 {
|
|
|
|
end = t.TrailingTrivia[len(t.TrailingTrivia)-1].Range().End
|
|
|
|
}
|
|
|
|
return hcl.Range{Filename: t.Raw.Range.Filename, Start: start, End: end}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t Token) withIdent(s string) Token {
|
|
|
|
if string(t.Raw.Bytes) == s {
|
|
|
|
return t
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
t.Raw.Bytes = []byte(s)
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Token) withOperation(operation *hclsyntax.Operation) Token {
|
|
|
|
typ := OperationTokenType(operation)
|
|
|
|
if t.Raw.Type == typ {
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
t.Raw.Type = typ
|
2020-04-03 03:01:14 +00:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
func OperationTokenType(operation *hclsyntax.Operation) hclsyntax.TokenType {
|
|
|
|
switch operation {
|
|
|
|
case hclsyntax.OpAdd:
|
|
|
|
return hclsyntax.TokenPlus
|
|
|
|
case hclsyntax.OpDivide:
|
|
|
|
return hclsyntax.TokenSlash
|
|
|
|
case hclsyntax.OpEqual:
|
|
|
|
return hclsyntax.TokenEqualOp
|
|
|
|
case hclsyntax.OpGreaterThan:
|
|
|
|
return hclsyntax.TokenGreaterThan
|
|
|
|
case hclsyntax.OpGreaterThanOrEqual:
|
|
|
|
return hclsyntax.TokenGreaterThanEq
|
|
|
|
case hclsyntax.OpLessThan:
|
|
|
|
return hclsyntax.TokenLessThan
|
|
|
|
case hclsyntax.OpLessThanOrEqual:
|
|
|
|
return hclsyntax.TokenLessThanEq
|
|
|
|
case hclsyntax.OpLogicalAnd:
|
|
|
|
return hclsyntax.TokenAnd
|
|
|
|
case hclsyntax.OpLogicalNot:
|
|
|
|
return hclsyntax.TokenBang
|
|
|
|
case hclsyntax.OpLogicalOr:
|
|
|
|
return hclsyntax.TokenOr
|
|
|
|
case hclsyntax.OpModulo:
|
|
|
|
return hclsyntax.TokenPercent
|
|
|
|
case hclsyntax.OpMultiply:
|
|
|
|
return hclsyntax.TokenStar
|
|
|
|
case hclsyntax.OpNegate:
|
|
|
|
return hclsyntax.TokenMinus
|
|
|
|
case hclsyntax.OpNotEqual:
|
|
|
|
return hclsyntax.TokenNotEqual
|
|
|
|
case hclsyntax.OpSubtract:
|
|
|
|
return hclsyntax.TokenMinus
|
|
|
|
}
|
|
|
|
return hclsyntax.TokenInvalid
|
|
|
|
}
|
|
|
|
|
|
|
|
func newRawToken(typ hclsyntax.TokenType, text ...string) hclsyntax.Token {
|
|
|
|
bytes := []byte(tokenStrings[typ])
|
|
|
|
if len(text) != 0 {
|
|
|
|
bytes = []byte(text[0])
|
|
|
|
}
|
|
|
|
return hclsyntax.Token{
|
|
|
|
Type: typ,
|
|
|
|
Bytes: bytes,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeTokens is a closed interface that is used to represent arbitrary *Tokens types in this package.
|
|
|
|
type NodeTokens interface {
|
|
|
|
isNodeTokens()
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
// Parentheses records enclosing parenthesis tokens for expressions.
|
|
|
|
type Parentheses struct {
|
|
|
|
Open []Token
|
|
|
|
Close []Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) Any() bool {
|
|
|
|
return len(parens.Open) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) GetLeadingTrivia() TriviaList {
|
|
|
|
if !parens.Any() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return parens.Open[0].LeadingTrivia
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) SetLeadingTrivia(trivia TriviaList) {
|
|
|
|
if parens.Any() {
|
|
|
|
parens.Open[0].LeadingTrivia = trivia
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) GetTrailingTrivia() TriviaList {
|
|
|
|
if !parens.Any() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return parens.Close[0].TrailingTrivia
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) SetTrailingTrivia(trivia TriviaList) {
|
|
|
|
if parens.Any() {
|
|
|
|
parens.Close[0].TrailingTrivia = trivia
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (parens Parentheses) Format(f fmt.State, c rune) {
|
|
|
|
switch c {
|
|
|
|
case '(':
|
|
|
|
for i := len(parens.Open) - 1; i >= 0; i-- {
|
|
|
|
if _, err := fmt.Fprintf(f, "%v", parens.Open[i]); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case ')':
|
|
|
|
for _, p := range parens.Close {
|
|
|
|
if _, err := fmt.Fprintf(f, "%v", p); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if _, err := fmt.Fprintf(f, "%v%v", parens.Open, parens.Close); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func exprRange(filename string, parens Parentheses, start, end hcl.Pos) hcl.Range {
|
|
|
|
if parens.Any() {
|
|
|
|
start = parens.Open[len(parens.Open)-1].Range().Start
|
|
|
|
end = parens.Close[len(parens.Close)-1].Range().End
|
|
|
|
}
|
|
|
|
return hcl.Range{
|
|
|
|
Filename: filename,
|
|
|
|
Start: start,
|
|
|
|
End: end,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
// AttributeTokens records the tokens associated with an *hclsyntax.Attribute.
|
|
|
|
type AttributeTokens struct {
|
|
|
|
Name Token
|
|
|
|
Equals Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAttributeTokens(name string) *AttributeTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *AttributeTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &AttributeTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Name: t.GetName(name),
|
|
|
|
Equals: t.GetEquals(),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *AttributeTokens) GetName(name string) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenIdent, name)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Name.withIdent(name)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *AttributeTokens) GetEquals() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenEqual),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Equals
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*AttributeTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// BinaryOpTokens records the tokens associated with an *hclsyntax.BinaryOpExpr.
|
|
|
|
type BinaryOpTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Operator Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBinaryOpTokens(operation *hclsyntax.Operation) *BinaryOpTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *BinaryOpTokens
|
|
|
|
return &BinaryOpTokens{Operator: t.GetOperator(operation)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *BinaryOpTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Parentheses
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *BinaryOpTokens) GetOperator(operation *hclsyntax.Operation) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{
|
|
|
|
Raw: newRawToken(OperationTokenType(operation)),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Operator.withOperation(operation)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (*BinaryOpTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// BlockTokens records the tokens associated with an *hclsyntax.Block.
|
|
|
|
type BlockTokens struct {
|
|
|
|
Type Token
|
|
|
|
Labels []Token
|
|
|
|
OpenBrace Token
|
|
|
|
CloseBrace Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBlockTokens(typ string, labels ...string) *BlockTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *BlockTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &BlockTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Type: t.GetType(typ),
|
|
|
|
Labels: t.GetLabels(labels),
|
|
|
|
OpenBrace: t.GetOpenBrace(),
|
|
|
|
CloseBrace: t.GetCloseBrace(),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *BlockTokens) GetType(typ string) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenIdent, typ)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Type.withIdent(typ)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *BlockTokens) GetLabels(labels []string) []Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
labelTokens := make([]Token, len(labels))
|
|
|
|
for i, l := range labels {
|
|
|
|
var raw hclsyntax.Token
|
|
|
|
if hclsyntax.ValidIdentifier(l) {
|
|
|
|
raw = newRawToken(hclsyntax.TokenIdent, l)
|
|
|
|
} else {
|
|
|
|
raw = newRawToken(hclsyntax.TokenQuotedLit, fmt.Sprintf("%q", l))
|
|
|
|
}
|
|
|
|
labelTokens[i] = Token{
|
|
|
|
Raw: raw,
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return labelTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Labels
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *BlockTokens) GetOpenBrace() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{
|
2020-04-16 23:44:34 +00:00
|
|
|
Raw: newRawToken(hclsyntax.TokenOBrace),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
TrailingTrivia: TriviaList{NewWhitespace('\n')},
|
2020-04-14 02:11:56 +00:00
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.OpenBrace
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *BlockTokens) GetCloseBrace() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{
|
2020-04-16 23:44:34 +00:00
|
|
|
Raw: newRawToken(hclsyntax.TokenCBrace),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace('\n')},
|
|
|
|
TrailingTrivia: TriviaList{NewWhitespace('\n')},
|
2020-04-14 02:11:56 +00:00
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.CloseBrace
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*BlockTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// BodyTokens records the tokens associated with an *hclsyntax.Body.
|
|
|
|
type BodyTokens struct {
|
|
|
|
EndOfFile *Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *BodyTokens) GetEndOfFile() *Token {
|
|
|
|
if t == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return t.EndOfFile
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*BodyTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// ConditionalTokens records the tokens associated with an *hclsyntax.ConditionalExpr of the form "a ? t : f".
|
|
|
|
type ConditionalTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
QuestionMark Token
|
|
|
|
Colon Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewConditionalTokens() *ConditionalTokens {
|
|
|
|
return &ConditionalTokens{
|
|
|
|
QuestionMark: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenQuestion),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
Colon: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenColon),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*ConditionalTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// TemplateConditionalTokens records the tokens associated with an *hclsyntax.ConditionalExpr inside a template
|
|
|
|
// expression.
|
|
|
|
type TemplateConditionalTokens struct {
|
|
|
|
OpenIf Token
|
|
|
|
If Token
|
|
|
|
CloseIf Token
|
|
|
|
OpenElse *Token
|
|
|
|
Else *Token
|
|
|
|
CloseElse *Token
|
|
|
|
OpenEndif Token
|
|
|
|
Endif Token
|
|
|
|
CloseEndif Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTemplateConditionalTokens(hasElse bool) *TemplateConditionalTokens {
|
|
|
|
var openElseT, elseT, closeElseT *Token
|
|
|
|
if hasElse {
|
|
|
|
openElseT = &Token{Raw: newRawToken(hclsyntax.TokenTemplateControl)}
|
|
|
|
elseT = &Token{Raw: newRawToken(hclsyntax.TokenIdent, "else")}
|
|
|
|
closeElseT = &Token{Raw: newRawToken(hclsyntax.TokenTemplateSeqEnd)}
|
|
|
|
}
|
|
|
|
return &TemplateConditionalTokens{
|
|
|
|
OpenIf: Token{Raw: newRawToken(hclsyntax.TokenTemplateControl)},
|
|
|
|
If: Token{Raw: newRawToken(hclsyntax.TokenIdent, "if")},
|
|
|
|
CloseIf: Token{Raw: newRawToken(hclsyntax.TokenTemplateSeqEnd)},
|
|
|
|
OpenElse: openElseT,
|
|
|
|
Else: elseT,
|
|
|
|
CloseElse: closeElseT,
|
|
|
|
OpenEndif: Token{Raw: newRawToken(hclsyntax.TokenTemplateControl)},
|
|
|
|
Endif: Token{Raw: newRawToken(hclsyntax.TokenIdent, "endif")},
|
|
|
|
CloseEndif: Token{Raw: newRawToken(hclsyntax.TokenTemplateSeqEnd)},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TemplateConditionalTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// ForTokens records the tokens associated with an *hclsyntax.ForExpr.
|
|
|
|
type ForTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Open Token
|
|
|
|
For Token
|
|
|
|
Key *Token
|
|
|
|
Comma *Token
|
|
|
|
Value Token
|
|
|
|
In Token
|
|
|
|
Colon Token
|
|
|
|
Arrow *Token
|
|
|
|
Group *Token
|
|
|
|
If *Token
|
|
|
|
Close Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewForTokens(keyVariable, valueVariable string, mapFor, group, conditional bool) *ForTokens {
|
|
|
|
var keyT, commaT, arrowT, groupT, ifT *Token
|
|
|
|
if keyVariable != "" {
|
|
|
|
keyT = &Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, keyVariable),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
|
|
|
commaT = &Token{Raw: newRawToken(hclsyntax.TokenComma)}
|
|
|
|
}
|
|
|
|
if mapFor {
|
|
|
|
arrowT = &Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenFatArrow),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if group {
|
|
|
|
groupT = &Token{Raw: newRawToken(hclsyntax.TokenEllipsis)}
|
|
|
|
}
|
|
|
|
if conditional {
|
|
|
|
ifT = &Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, "if"),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ForTokens{
|
|
|
|
Open: Token{Raw: newRawToken(hclsyntax.TokenOBrack)},
|
|
|
|
For: Token{Raw: newRawToken(hclsyntax.TokenIdent, "for")},
|
|
|
|
Key: keyT,
|
|
|
|
Comma: commaT,
|
|
|
|
Value: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, valueVariable),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
In: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, "in"),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
Colon: Token{Raw: newRawToken(hclsyntax.TokenColon)},
|
|
|
|
Arrow: arrowT,
|
|
|
|
Group: groupT,
|
|
|
|
If: ifT,
|
|
|
|
Close: Token{Raw: newRawToken(hclsyntax.TokenCBrack)},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*ForTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// TemplateForTokens records the tokens associated with an *hclsyntax.ForExpr inside a template.
|
|
|
|
type TemplateForTokens struct {
|
|
|
|
OpenFor Token
|
|
|
|
For Token
|
|
|
|
Key *Token
|
|
|
|
Comma *Token
|
|
|
|
Value Token
|
|
|
|
In Token
|
|
|
|
CloseFor Token
|
|
|
|
OpenEndfor Token
|
|
|
|
Endfor Token
|
|
|
|
CloseEndfor Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTemplateForTokens(keyVariable, valueVariable string) *TemplateForTokens {
|
|
|
|
var keyT, commaT *Token
|
|
|
|
if keyVariable != "" {
|
|
|
|
keyT = &Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, keyVariable),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
}
|
|
|
|
commaT = &Token{Raw: newRawToken(hclsyntax.TokenComma)}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &TemplateForTokens{
|
|
|
|
OpenFor: Token{Raw: newRawToken(hclsyntax.TokenTemplateControl)},
|
|
|
|
For: Token{Raw: newRawToken(hclsyntax.TokenIdent, "for")},
|
|
|
|
Key: keyT,
|
|
|
|
Comma: commaT,
|
|
|
|
Value: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, valueVariable),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
In: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenIdent, "in"),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
CloseFor: Token{Raw: newRawToken(hclsyntax.TokenTemplateSeqEnd)},
|
|
|
|
OpenEndfor: Token{Raw: newRawToken(hclsyntax.TokenTemplateControl)},
|
|
|
|
Endfor: Token{Raw: newRawToken(hclsyntax.TokenIdent, "endfor")},
|
|
|
|
CloseEndfor: Token{Raw: newRawToken(hclsyntax.TokenTemplateSeqEnd)},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TemplateForTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// FunctionCallTokens records the tokens associated with an *hclsyntax.FunctionCallExpr.
|
|
|
|
type FunctionCallTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Name Token
|
|
|
|
OpenParen Token
|
|
|
|
Commas []Token
|
|
|
|
CloseParen Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFunctionCallTokens(name string, argCount int) *FunctionCallTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *FunctionCallTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &FunctionCallTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Name: t.GetName(name),
|
|
|
|
OpenParen: t.GetOpenParen(),
|
|
|
|
Commas: t.GetCommas(argCount),
|
|
|
|
CloseParen: t.GetCloseParen(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *FunctionCallTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Parentheses
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *FunctionCallTokens) GetName(name string) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenIdent, name)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Name.withIdent(name)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *FunctionCallTokens) GetOpenParen() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenOParen)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.OpenParen
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *FunctionCallTokens) GetCommas(argCount int) []Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-30 20:44:32 +00:00
|
|
|
if argCount == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
commas := make([]Token, argCount-1)
|
|
|
|
for i := 0; i < len(commas); i++ {
|
|
|
|
commas[i] = Token{Raw: newRawToken(hclsyntax.TokenComma)}
|
|
|
|
}
|
|
|
|
return commas
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Commas
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *FunctionCallTokens) GetCloseParen() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenCParen)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.CloseParen
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*FunctionCallTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// IndexTokens records the tokens associated with an *hclsyntax.IndexExpr.
|
|
|
|
type IndexTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
OpenBracket Token
|
|
|
|
CloseBracket Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewIndexTokens() *IndexTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *IndexTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &IndexTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
OpenBracket: t.GetOpenBracket(),
|
|
|
|
CloseBracket: t.GetCloseBracket(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *IndexTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Parentheses
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *IndexTokens) GetOpenBracket() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenOBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.OpenBracket
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *IndexTokens) GetCloseBracket() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenCBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.CloseBracket
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*IndexTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// LiteralValueTokens records the tokens associated with an *hclsyntax.LiteralValueExpr.
|
|
|
|
type LiteralValueTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Value []Token
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func rawLiteralValueToken(value cty.Value) hclsyntax.Token {
|
|
|
|
rawType, rawText := hclsyntax.TokenIdent, ""
|
|
|
|
switch value.Type() {
|
|
|
|
case cty.Bool:
|
|
|
|
rawText = "false"
|
|
|
|
if value.True() {
|
|
|
|
rawText = "true"
|
|
|
|
}
|
|
|
|
case cty.Number:
|
|
|
|
rawType = hclsyntax.TokenNumberLit
|
|
|
|
|
|
|
|
bf := value.AsBigFloat()
|
|
|
|
i, acc := bf.Int64()
|
|
|
|
if acc == big.Exact {
|
2023-12-12 12:19:42 +00:00
|
|
|
rawText = strconv.FormatInt(i, 10)
|
2020-04-14 02:11:56 +00:00
|
|
|
} else {
|
|
|
|
d, _ := bf.Float64()
|
|
|
|
rawText = fmt.Sprintf("%g", d)
|
|
|
|
}
|
|
|
|
case cty.String:
|
|
|
|
rawText = value.AsString()
|
|
|
|
}
|
|
|
|
return newRawToken(rawType, rawText)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewLiteralValueTokens(value cty.Value) *LiteralValueTokens {
|
|
|
|
var t *LiteralValueTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &LiteralValueTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Value: t.GetValue(value),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *LiteralValueTokens) GetParentheses() Parentheses {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *LiteralValueTokens) GetValue(value cty.Value) []Token {
|
|
|
|
if t == nil {
|
|
|
|
return []Token{{Raw: rawLiteralValueToken(value)}}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*LiteralValueTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// ObjectConsItemTokens records the tokens associated with an hclsyntax.ObjectConsItem.
|
|
|
|
type ObjectConsItemTokens struct {
|
|
|
|
Equals Token
|
|
|
|
Comma *Token
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func NewObjectConsItemTokens(last bool) ObjectConsItemTokens {
|
|
|
|
var comma *Token
|
|
|
|
if !last {
|
|
|
|
comma = &Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenComma),
|
|
|
|
TrailingTrivia: TriviaList{NewWhitespace('\n')},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ObjectConsItemTokens{
|
|
|
|
Equals: Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenEqual),
|
|
|
|
LeadingTrivia: TriviaList{NewWhitespace(' ')},
|
|
|
|
},
|
|
|
|
Comma: comma,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
// ObjectConsTokens records the tokens associated with an *hclsyntax.ObjectConsExpr.
|
|
|
|
type ObjectConsTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
OpenBrace Token
|
|
|
|
Items []ObjectConsItemTokens
|
|
|
|
CloseBrace Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewObjectConsTokens(itemCount int) *ObjectConsTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *ObjectConsTokens
|
|
|
|
return &ObjectConsTokens{
|
|
|
|
OpenBrace: t.GetOpenBrace(itemCount),
|
|
|
|
Items: t.GetItems(itemCount),
|
|
|
|
CloseBrace: t.GetCloseBrace(),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
}
|
2020-04-09 23:37:52 +00:00
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *ObjectConsTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Parentheses
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *ObjectConsTokens) GetOpenBrace(itemCount int) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
var openBraceTrailingTrivia TriviaList
|
|
|
|
if itemCount > 0 {
|
|
|
|
openBraceTrailingTrivia = TriviaList{NewWhitespace('\n')}
|
|
|
|
}
|
|
|
|
return Token{
|
|
|
|
Raw: newRawToken(hclsyntax.TokenOBrace),
|
|
|
|
TrailingTrivia: openBraceTrailingTrivia,
|
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.OpenBrace
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *ObjectConsTokens) GetItems(itemCount int) []ObjectConsItemTokens {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
items := make([]ObjectConsItemTokens, itemCount)
|
|
|
|
for i := 0; i < len(items); i++ {
|
|
|
|
items[i] = NewObjectConsItemTokens(i == len(items)-1)
|
|
|
|
}
|
|
|
|
return items
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Items
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ObjectConsTokens) GetCloseBrace() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenCBrace)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.CloseBrace
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*ObjectConsTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// TraverserTokens is a closed interface implemented by DotTraverserTokens and BracketTraverserTokens
|
|
|
|
type TraverserTokens interface {
|
2020-04-14 02:11:56 +00:00
|
|
|
Range() hcl.Range
|
2020-04-03 03:01:14 +00:00
|
|
|
|
|
|
|
isTraverserTokens()
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func NewTraverserTokens(traverser hcl.Traverser) TraverserTokens {
|
|
|
|
switch traverser := traverser.(type) {
|
|
|
|
case hcl.TraverseAttr:
|
|
|
|
return NewDotTraverserTokens(traverser.Name)
|
|
|
|
case hcl.TraverseIndex:
|
|
|
|
return NewBracketTraverserTokens(string(rawLiteralValueToken(traverser.Key).Bytes))
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
// DotTraverserTokens records the tokens associated with dotted traverser (i.e. '.' <attr>).
|
|
|
|
type DotTraverserTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Dot Token
|
|
|
|
Index Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDotTraverserTokens(index string) *DotTraverserTokens {
|
|
|
|
indexType := hclsyntax.TokenIdent
|
|
|
|
_, err := cty.ParseNumberVal(index)
|
|
|
|
if err == nil {
|
|
|
|
indexType = hclsyntax.TokenNumberLit
|
|
|
|
}
|
|
|
|
return &DotTraverserTokens{
|
|
|
|
Dot: Token{Raw: newRawToken(hclsyntax.TokenDot)},
|
|
|
|
Index: Token{Raw: newRawToken(indexType, index)},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *DotTraverserTokens) Range() hcl.Range {
|
|
|
|
filename := t.Dot.Range().Filename
|
|
|
|
return exprRange(filename, t.Parentheses, t.Dot.Range().Start, t.Index.Range().End)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (*DotTraverserTokens) isTraverserTokens() {}
|
|
|
|
|
|
|
|
// BracketTraverserTokens records the tokens associated with a bracketed traverser (i.e. '[' <index> ']').
|
|
|
|
type BracketTraverserTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
OpenBracket Token
|
|
|
|
Index Token
|
|
|
|
CloseBracket Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBracketTraverserTokens(index string) *BracketTraverserTokens {
|
|
|
|
indexType := hclsyntax.TokenIdent
|
|
|
|
_, err := cty.ParseNumberVal(index)
|
|
|
|
if err == nil {
|
|
|
|
indexType = hclsyntax.TokenNumberLit
|
|
|
|
}
|
|
|
|
return &BracketTraverserTokens{
|
|
|
|
OpenBracket: Token{Raw: newRawToken(hclsyntax.TokenOBrack)},
|
|
|
|
Index: Token{Raw: newRawToken(indexType, index)},
|
|
|
|
CloseBracket: Token{Raw: newRawToken(hclsyntax.TokenCBrack)},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *BracketTraverserTokens) Range() hcl.Range {
|
|
|
|
filename := t.OpenBracket.Range().Filename
|
|
|
|
return exprRange(filename, t.Parentheses, t.OpenBracket.Range().Start, t.CloseBracket.Range().End)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (*BracketTraverserTokens) isTraverserTokens() {}
|
2020-04-03 03:01:14 +00:00
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func newRelativeTraversalTokens(traversal hcl.Traversal) []TraverserTokens {
|
|
|
|
result := make([]TraverserTokens, len(traversal))
|
|
|
|
for i, t := range traversal {
|
|
|
|
result[i] = NewTraverserTokens(t)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return result
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RelativeTraversalTokens records the tokens associated with an *hclsyntax.RelativeTraversalExpr.
|
|
|
|
type RelativeTraversalTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Traversal []TraverserTokens
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func NewRelativeTraversalTokens(traversal hcl.Traversal) *RelativeTraversalTokens {
|
|
|
|
return &RelativeTraversalTokens{
|
|
|
|
Traversal: newRelativeTraversalTokens(traversal),
|
|
|
|
}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *RelativeTraversalTokens) GetParentheses() Parentheses {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *RelativeTraversalTokens) GetTraversal(traversal hcl.Traversal) []TraverserTokens {
|
|
|
|
if t == nil {
|
|
|
|
return newRelativeTraversalTokens(traversal)
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Traversal
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*RelativeTraversalTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// ScopeTraversalTokens records the tokens associated with an *hclsyntax.ScopeTraversalExpr.
|
|
|
|
type ScopeTraversalTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Root Token
|
|
|
|
Traversal []TraverserTokens
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func NewScopeTraversalTokens(traversal hcl.Traversal) *ScopeTraversalTokens {
|
|
|
|
var t *ScopeTraversalTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &ScopeTraversalTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Root: t.GetRoot(traversal),
|
|
|
|
Traversal: t.GetTraversal(traversal),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *ScopeTraversalTokens) GetParentheses() Parentheses {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ScopeTraversalTokens) GetRoot(traversal hcl.Traversal) Token {
|
|
|
|
if t == nil {
|
|
|
|
rootName := traversal[0].(hcl.TraverseRoot).Name
|
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenIdent, rootName)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Root
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *ScopeTraversalTokens) GetTraversal(traversal hcl.Traversal) []TraverserTokens {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return newRelativeTraversalTokens(traversal[1:])
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Traversal
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*ScopeTraversalTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// SplatTokens records the tokens associated with an *hclsyntax.SplatExpr.
|
|
|
|
type SplatTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Open Token
|
|
|
|
Star Token
|
|
|
|
Close *Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSplatTokens(dotted bool) *SplatTokens {
|
|
|
|
openType := hclsyntax.TokenDot
|
|
|
|
var closeT *Token
|
|
|
|
if !dotted {
|
|
|
|
openType = hclsyntax.TokenOBrack
|
|
|
|
closeT = &Token{Raw: newRawToken(hclsyntax.TokenCBrack)}
|
|
|
|
}
|
|
|
|
return &SplatTokens{
|
|
|
|
Open: Token{Raw: newRawToken(openType)},
|
|
|
|
Star: Token{Raw: newRawToken(hclsyntax.TokenStar)},
|
|
|
|
Close: closeT,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *SplatTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
func (t *SplatTokens) GetOpen() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenOBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Open
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *SplatTokens) GetStar() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenStar)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Star
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *SplatTokens) GetClose() *Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return &Token{Raw: newRawToken(hclsyntax.TokenCBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Close
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*SplatTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// TemplateTokens records the tokens associated with an *hclsyntax.TemplateExpr.
|
|
|
|
type TemplateTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Open Token
|
|
|
|
Close Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTemplateTokens() *TemplateTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *TemplateTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &TemplateTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Open: t.GetOpen(),
|
|
|
|
Close: t.GetClose(),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *TemplateTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
func (t *TemplateTokens) GetOpen() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenOQuote)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Open
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TemplateTokens) GetClose() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenCQuote)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Close
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TemplateTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// TupleConsTokens records the tokens associated with an *hclsyntax.TupleConsExpr.
|
|
|
|
type TupleConsTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
OpenBracket Token
|
|
|
|
Commas []Token
|
|
|
|
CloseBracket Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTupleConsTokens(elementCount int) *TupleConsTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *TupleConsTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &TupleConsTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
OpenBracket: t.GetOpenBracket(),
|
|
|
|
Commas: t.GetCommas(elementCount),
|
|
|
|
CloseBracket: t.GetCloseBracket(),
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *TupleConsTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
|
|
|
}
|
|
|
|
return t.Parentheses
|
|
|
|
}
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
func (t *TupleConsTokens) GetOpenBracket() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenOBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.OpenBracket
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *TupleConsTokens) GetCommas(elementCount int) []Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-30 20:44:32 +00:00
|
|
|
if elementCount == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
commas := make([]Token, elementCount-1)
|
|
|
|
for i := 0; i < len(commas); i++ {
|
|
|
|
commas[i] = Token{Raw: newRawToken(hclsyntax.TokenComma)}
|
|
|
|
}
|
|
|
|
return commas
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Commas
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TupleConsTokens) GetCloseBracket() Token {
|
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(hclsyntax.TokenCBrack)}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.CloseBracket
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*TupleConsTokens) isNodeTokens() {}
|
|
|
|
|
|
|
|
// UnaryOpTokens records the tokens associated with an *hclsyntax.UnaryOpExpr.
|
|
|
|
type UnaryOpTokens struct {
|
2020-04-14 02:11:56 +00:00
|
|
|
Parentheses Parentheses
|
|
|
|
|
2020-04-03 03:01:14 +00:00
|
|
|
Operator Token
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUnaryOpTokens(operation *hclsyntax.Operation) *UnaryOpTokens {
|
2020-04-14 02:11:56 +00:00
|
|
|
var t *UnaryOpTokens
|
2020-04-03 03:01:14 +00:00
|
|
|
return &UnaryOpTokens{
|
2020-04-14 02:11:56 +00:00
|
|
|
Operator: t.GetOperator(operation),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *UnaryOpTokens) GetParentheses() Parentheses {
|
|
|
|
if t == nil {
|
|
|
|
return Parentheses{}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
2020-04-14 02:11:56 +00:00
|
|
|
return t.Parentheses
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 02:11:56 +00:00
|
|
|
func (t *UnaryOpTokens) GetOperator(operation *hclsyntax.Operation) Token {
|
2020-04-03 03:01:14 +00:00
|
|
|
if t == nil {
|
2020-04-14 02:11:56 +00:00
|
|
|
return Token{Raw: newRawToken(OperationTokenType(operation))}
|
2020-04-03 03:01:14 +00:00
|
|
|
}
|
|
|
|
return t.Operator
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*UnaryOpTokens) isNodeTokens() {}
|