Move the zcl package and its two parsing subpackages to "hcl" names

This is a super-invasive update since the "zcl" package in particular
is referenced all over.

There are probably still a few zcl references hanging around in comments,
etc but this takes care of most of it.
This commit is contained in:
Martin Atkins 2017-09-11 16:40:37 -07:00
parent 0dc3a6015c
commit 708abb8c97
115 changed files with 5394 additions and 5392 deletions

View File

@ -9,9 +9,9 @@ import (
"os" "os"
"strings" "strings"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hclparse" "github.com/hashicorp/hcl2/hclparse"
"github.com/hashicorp/hcl2/hclwrite" "github.com/hashicorp/hcl2/hclwrite"
"github.com/hashicorp/hcl2/zcl"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
@ -25,7 +25,7 @@ var (
) )
var parser = hclparse.NewParser() var parser = hclparse.NewParser()
var diagWr zcl.DiagnosticWriter // initialized in init var diagWr hcl.DiagnosticWriter // initialized in init
var checkErrs = false var checkErrs = false
var changed []string var changed []string
@ -35,7 +35,7 @@ func init() {
if err != nil { if err != nil {
w = 80 w = 80
} }
diagWr = zcl.NewDiagnosticTextWriter(os.Stderr, parser.Files(), uint(w), color) diagWr = hcl.NewDiagnosticTextWriter(os.Stderr, parser.Files(), uint(w), color)
} }
func main() { func main() {

View File

@ -5,7 +5,7 @@ import (
"strings" "strings"
"github.com/hashicorp/hcl2/hclparse" "github.com/hashicorp/hcl2/hclparse"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// FileResolver creates and returns a Resolver that interprets include paths // FileResolver creates and returns a Resolver that interprets include paths
@ -35,13 +35,13 @@ type fileResolver struct {
Parser *hclparse.Parser Parser *hclparse.Parser
} }
func (r fileResolver) ResolveBodyPath(path string, refRange zcl.Range) (zcl.Body, zcl.Diagnostics) { func (r fileResolver) ResolveBodyPath(path string, refRange hcl.Range) (hcl.Body, hcl.Diagnostics) {
callerFile := filepath.Join(r.BaseDir, refRange.Filename) callerFile := filepath.Join(r.BaseDir, refRange.Filename)
callerDir := filepath.Dir(callerFile) callerDir := filepath.Dir(callerFile)
targetFile := filepath.Join(callerDir, path) targetFile := filepath.Join(callerDir, path)
var f *zcl.File var f *hcl.File
var diags zcl.Diagnostics var diags hcl.Diagnostics
if strings.HasSuffix(targetFile, ".json") { if strings.HasSuffix(targetFile, ".json") {
f, diags = r.Parser.ParseJSONFile(targetFile) f, diags = r.Parser.ParseJSONFile(targetFile)
} else { } else {

View File

@ -3,7 +3,7 @@ package include
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// MapResolver returns a Resolver that consults the given map for preloaded // MapResolver returns a Resolver that consults the given map for preloaded
@ -11,15 +11,15 @@ import (
// //
// An error diagnostic is returned if a path is requested that does not appear // An error diagnostic is returned if a path is requested that does not appear
// as a key in the given map. // as a key in the given map.
func MapResolver(m map[string]zcl.Body) Resolver { func MapResolver(m map[string]hcl.Body) Resolver {
return ResolverFunc(func(path string, refRange zcl.Range) (zcl.Body, zcl.Diagnostics) { return ResolverFunc(func(path string, refRange hcl.Range) (hcl.Body, hcl.Diagnostics) {
if body, ok := m[path]; ok { if body, ok := m[path]; ok {
return body, nil return body, nil
} }
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid include path", Summary: "Invalid include path",
Detail: fmt.Sprintf("The include path %q is not recognized.", path), Detail: fmt.Sprintf("The include path %q is not recognized.", path),
Subject: &refRange, Subject: &refRange,

View File

@ -1,11 +1,11 @@
package include package include
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// A Resolver maps an include path (an arbitrary string, but usually something // A Resolver maps an include path (an arbitrary string, but usually something
// filepath-like) to a zcl.Body. // filepath-like) to a hcl.Body.
// //
// The parameter "refRange" is the source range of the expression in the calling // The parameter "refRange" is the source range of the expression in the calling
// body that provided the given path, for use in generating "invalid path"-type // body that provided the given path, for use in generating "invalid path"-type
@ -16,13 +16,13 @@ import (
// Any returned diagnostics will be emitted when content is requested from the // Any returned diagnostics will be emitted when content is requested from the
// final composed body (after all includes have been dealt with). // final composed body (after all includes have been dealt with).
type Resolver interface { type Resolver interface {
ResolveBodyPath(path string, refRange zcl.Range) (zcl.Body, zcl.Diagnostics) ResolveBodyPath(path string, refRange hcl.Range) (hcl.Body, hcl.Diagnostics)
} }
// ResolverFunc is a function type that implements Resolver. // ResolverFunc is a function type that implements Resolver.
type ResolverFunc func(path string, refRange zcl.Range) (zcl.Body, zcl.Diagnostics) type ResolverFunc func(path string, refRange hcl.Range) (hcl.Body, hcl.Diagnostics)
// ResolveBodyPath is an implementation of Resolver.ResolveBodyPath. // ResolveBodyPath is an implementation of Resolver.ResolveBodyPath.
func (f ResolverFunc) ResolveBodyPath(path string, refRange zcl.Range) (zcl.Body, zcl.Diagnostics) { func (f ResolverFunc) ResolveBodyPath(path string, refRange hcl.Range) (hcl.Body, hcl.Diagnostics) {
return f(path, refRange) return f(path, refRange)
} }

View File

@ -3,7 +3,7 @@ package include
import ( import (
"github.com/hashicorp/hcl2/ext/transform" "github.com/hashicorp/hcl2/ext/transform"
"github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Transformer builds a transformer that finds any "include" blocks in a body // Transformer builds a transformer that finds any "include" blocks in a body
@ -30,10 +30,10 @@ import (
// // "body" will now have includes resolved in its own content and that // // "body" will now have includes resolved in its own content and that
// // of any descendent blocks. // // of any descendent blocks.
// //
func Transformer(blockType string, ctx *zcl.EvalContext, resolver Resolver) transform.Transformer { func Transformer(blockType string, ctx *hcl.EvalContext, resolver Resolver) transform.Transformer {
return &transformer{ return &transformer{
Schema: &zcl.BodySchema{ Schema: &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: blockType, Type: blockType,
}, },
@ -45,12 +45,12 @@ func Transformer(blockType string, ctx *zcl.EvalContext, resolver Resolver) tran
} }
type transformer struct { type transformer struct {
Schema *zcl.BodySchema Schema *hcl.BodySchema
Ctx *zcl.EvalContext Ctx *hcl.EvalContext
Resolver Resolver Resolver Resolver
} }
func (t *transformer) TransformBody(in zcl.Body) zcl.Body { func (t *transformer) TransformBody(in hcl.Body) hcl.Body {
content, remain, diags := in.PartialContent(t.Schema) content, remain, diags := in.PartialContent(t.Schema)
if content == nil || len(content.Blocks) == 0 { if content == nil || len(content.Blocks) == 0 {
@ -58,7 +58,7 @@ func (t *transformer) TransformBody(in zcl.Body) zcl.Body {
return transform.BodyWithDiagnostics(remain, diags) return transform.BodyWithDiagnostics(remain, diags)
} }
bodies := make([]zcl.Body, 1, len(content.Blocks)+1) bodies := make([]hcl.Body, 1, len(content.Blocks)+1)
bodies[0] = remain // content in "remain" takes priority over includes bodies[0] = remain // content in "remain" takes priority over includes
for _, block := range content.Blocks { for _, block := range content.Blocks {
incContent, incDiags := block.Body.Content(includeBlockSchema) incContent, incDiags := block.Body.Content(includeBlockSchema)
@ -79,11 +79,11 @@ func (t *transformer) TransformBody(in zcl.Body) zcl.Body {
bodies = append(bodies, transform.BodyWithDiagnostics(incBody, incDiags)) bodies = append(bodies, transform.BodyWithDiagnostics(incBody, incDiags))
} }
return zcl.MergeBodies(bodies) return hcl.MergeBodies(bodies)
} }
var includeBlockSchema = &zcl.BodySchema{ var includeBlockSchema = &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "path", Name: "path",
Required: true, Required: true,

View File

@ -7,33 +7,33 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/hcltest" "github.com/hashicorp/hcl2/hcltest"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
func TestTransformer(t *testing.T) { func TestTransformer(t *testing.T) {
caller := hcltest.MockBody(&zcl.BodyContent{ caller := hcltest.MockBody(&hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "include", Type: "include",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"path": hcltest.MockExprVariable("var_path"), "path": hcltest.MockExprVariable("var_path"),
}), }),
}), }),
}, },
{ {
Type: "include", Type: "include",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"path": hcltest.MockExprLiteral(cty.StringVal("include2")), "path": hcltest.MockExprLiteral(cty.StringVal("include2")),
}), }),
}), }),
}, },
{ {
Type: "foo", Type: "foo",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"from": hcltest.MockExprLiteral(cty.StringVal("caller")), "from": hcltest.MockExprLiteral(cty.StringVal("caller")),
}), }),
}), }),
@ -41,25 +41,25 @@ func TestTransformer(t *testing.T) {
}, },
}) })
resolver := MapResolver(map[string]zcl.Body{ resolver := MapResolver(map[string]hcl.Body{
"include1": hcltest.MockBody(&zcl.BodyContent{ "include1": hcltest.MockBody(&hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"from": hcltest.MockExprLiteral(cty.StringVal("include1")), "from": hcltest.MockExprLiteral(cty.StringVal("include1")),
}), }),
}), }),
}, },
}, },
}), }),
"include2": hcltest.MockBody(&zcl.BodyContent{ "include2": hcltest.MockBody(&hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"from": hcltest.MockExprLiteral(cty.StringVal("include2")), "from": hcltest.MockExprLiteral(cty.StringVal("include2")),
}), }),
}), }),
@ -68,7 +68,7 @@ func TestTransformer(t *testing.T) {
}), }),
}) })
ctx := &zcl.EvalContext{ ctx := &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"var_path": cty.StringVal("include1"), "var_path": cty.StringVal("include1"),
}, },

View File

@ -1,20 +1,20 @@
package transform package transform
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// NewErrorBody returns a zcl.Body that returns the given diagnostics whenever // NewErrorBody returns a hcl.Body that returns the given diagnostics whenever
// any of its content-access methods are called. // any of its content-access methods are called.
// //
// The given diagnostics must have at least one diagnostic of severity // The given diagnostics must have at least one diagnostic of severity
// zcl.DiagError, or this function will panic. // hcl.DiagError, or this function will panic.
// //
// This can be used to prepare a return value for a Transformer that // This can be used to prepare a return value for a Transformer that
// can't complete due to an error. While the transform itself will succeed, // can't complete due to an error. While the transform itself will succeed,
// the error will be returned as soon as a caller attempts to extract content // the error will be returned as soon as a caller attempts to extract content
// from the resulting body. // from the resulting body.
func NewErrorBody(diags zcl.Diagnostics) zcl.Body { func NewErrorBody(diags hcl.Diagnostics) hcl.Body {
if !diags.HasErrors() { if !diags.HasErrors() {
panic("NewErrorBody called without any error diagnostics") panic("NewErrorBody called without any error diagnostics")
} }
@ -23,7 +23,7 @@ func NewErrorBody(diags zcl.Diagnostics) zcl.Body {
} }
} }
// BodyWithDiagnostics returns a zcl.Body that wraps another zcl.Body // BodyWithDiagnostics returns a hcl.Body that wraps another hcl.Body
// and emits the given diagnostics for any content-extraction method. // and emits the given diagnostics for any content-extraction method.
// //
// Unlike the result of NewErrorBody, a body with diagnostics still runs // Unlike the result of NewErrorBody, a body with diagnostics still runs
@ -36,7 +36,7 @@ func NewErrorBody(diags zcl.Diagnostics) zcl.Body {
// This function is intended for conveniently reporting errors and/or warnings // This function is intended for conveniently reporting errors and/or warnings
// produced during a transform, ensuring that they will be seen when the // produced during a transform, ensuring that they will be seen when the
// caller eventually extracts content from the returned body. // caller eventually extracts content from the returned body.
func BodyWithDiagnostics(body zcl.Body, diags zcl.Diagnostics) zcl.Body { func BodyWithDiagnostics(body hcl.Body, diags hcl.Diagnostics) hcl.Body {
if len(diags) == 0 { if len(diags) == 0 {
// nothing to do! // nothing to do!
return body return body
@ -49,60 +49,60 @@ func BodyWithDiagnostics(body zcl.Body, diags zcl.Diagnostics) zcl.Body {
} }
type diagBody struct { type diagBody struct {
Diags zcl.Diagnostics Diags hcl.Diagnostics
Wrapped zcl.Body Wrapped hcl.Body
} }
func (b diagBody) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostics) { func (b diagBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
if b.Diags.HasErrors() { if b.Diags.HasErrors() {
return b.emptyContent(), b.Diags return b.emptyContent(), b.Diags
} }
content, wrappedDiags := b.Wrapped.Content(schema) content, wrappedDiags := b.Wrapped.Content(schema)
diags := make(zcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags)) diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))
diags = append(diags, b.Diags...) diags = append(diags, b.Diags...)
diags = append(diags, wrappedDiags...) diags = append(diags, wrappedDiags...)
return content, diags return content, diags
} }
func (b diagBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Body, zcl.Diagnostics) { func (b diagBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
if b.Diags.HasErrors() { if b.Diags.HasErrors() {
return b.emptyContent(), b.Wrapped, b.Diags return b.emptyContent(), b.Wrapped, b.Diags
} }
content, remain, wrappedDiags := b.Wrapped.PartialContent(schema) content, remain, wrappedDiags := b.Wrapped.PartialContent(schema)
diags := make(zcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags)) diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))
diags = append(diags, b.Diags...) diags = append(diags, b.Diags...)
diags = append(diags, wrappedDiags...) diags = append(diags, wrappedDiags...)
return content, remain, diags return content, remain, diags
} }
func (b diagBody) JustAttributes() (zcl.Attributes, zcl.Diagnostics) { func (b diagBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
if b.Diags.HasErrors() { if b.Diags.HasErrors() {
return nil, b.Diags return nil, b.Diags
} }
attributes, wrappedDiags := b.Wrapped.JustAttributes() attributes, wrappedDiags := b.Wrapped.JustAttributes()
diags := make(zcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags)) diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))
diags = append(diags, b.Diags...) diags = append(diags, b.Diags...)
diags = append(diags, wrappedDiags...) diags = append(diags, wrappedDiags...)
return attributes, diags return attributes, diags
} }
func (b diagBody) MissingItemRange() zcl.Range { func (b diagBody) MissingItemRange() hcl.Range {
if b.Wrapped != nil { if b.Wrapped != nil {
return b.Wrapped.MissingItemRange() return b.Wrapped.MissingItemRange()
} }
// Placeholder. This should never be seen in practice because decoding // Placeholder. This should never be seen in practice because decoding
// a diagBody without a wrapped body should always produce an error. // a diagBody without a wrapped body should always produce an error.
return zcl.Range{ return hcl.Range{
Filename: "<empty>", Filename: "<empty>",
} }
} }
func (b diagBody) emptyContent() *zcl.BodyContent { func (b diagBody) emptyContent() *hcl.BodyContent {
return &zcl.BodyContent{ return &hcl.BodyContent{
MissingItemRange: b.MissingItemRange(), MissingItemRange: b.MissingItemRange(),
} }
} }

View File

@ -1,12 +1,12 @@
package transform package transform
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Shallow is equivalent to calling transformer.TransformBody(body), and // Shallow is equivalent to calling transformer.TransformBody(body), and
// is provided only for completeness of the top-level API. // is provided only for completeness of the top-level API.
func Shallow(body zcl.Body, transformer Transformer) zcl.Body { func Shallow(body hcl.Body, transformer Transformer) hcl.Body {
return transformer.TransformBody(body) return transformer.TransformBody(body)
} }
@ -19,36 +19,36 @@ func Shallow(body zcl.Body, transformer Transformer) zcl.Body {
// //
// Due to the wrapping behavior, the body resulting from this function // Due to the wrapping behavior, the body resulting from this function
// will not be of the type returned by the transformer. Callers may call // will not be of the type returned by the transformer. Callers may call
// only the methods defined for interface zcl.Body, and may not type-assert // only the methods defined for interface hcl.Body, and may not type-assert
// to access other methods. // to access other methods.
func Deep(body zcl.Body, transformer Transformer) zcl.Body { func Deep(body hcl.Body, transformer Transformer) hcl.Body {
return deepWrapper{ return deepWrapper{
Transformed: transformer.TransformBody(body), Transformed: transformer.TransformBody(body),
Transformer: transformer, Transformer: transformer,
} }
} }
// deepWrapper is a zcl.Body implementation that ensures that a given // deepWrapper is a hcl.Body implementation that ensures that a given
// transformer is applied to another given body when content is extracted, // transformer is applied to another given body when content is extracted,
// and that it recursively applies to any child blocks that are extracted. // and that it recursively applies to any child blocks that are extracted.
type deepWrapper struct { type deepWrapper struct {
Transformed zcl.Body Transformed hcl.Body
Transformer Transformer Transformer Transformer
} }
func (w deepWrapper) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostics) { func (w deepWrapper) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
content, diags := w.Transformed.Content(schema) content, diags := w.Transformed.Content(schema)
content = w.transformContent(content) content = w.transformContent(content)
return content, diags return content, diags
} }
func (w deepWrapper) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Body, zcl.Diagnostics) { func (w deepWrapper) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
content, remain, diags := w.Transformed.PartialContent(schema) content, remain, diags := w.Transformed.PartialContent(schema)
content = w.transformContent(content) content = w.transformContent(content)
return content, remain, diags return content, remain, diags
} }
func (w deepWrapper) transformContent(content *zcl.BodyContent) *zcl.BodyContent { func (w deepWrapper) transformContent(content *hcl.BodyContent) *hcl.BodyContent {
if len(content.Blocks) == 0 { if len(content.Blocks) == 0 {
// Easy path: if there are no blocks then there are no child bodies to wrap // Easy path: if there are no blocks then there are no child bodies to wrap
return content return content
@ -57,10 +57,10 @@ func (w deepWrapper) transformContent(content *zcl.BodyContent) *zcl.BodyContent
// Since we're going to change things here, we'll be polite and clone the // Since we're going to change things here, we'll be polite and clone the
// structure so that we don't risk impacting any internal state of the // structure so that we don't risk impacting any internal state of the
// original body. // original body.
ret := &zcl.BodyContent{ ret := &hcl.BodyContent{
Attributes: content.Attributes, Attributes: content.Attributes,
MissingItemRange: content.MissingItemRange, MissingItemRange: content.MissingItemRange,
Blocks: make(zcl.Blocks, len(content.Blocks)), Blocks: make(hcl.Blocks, len(content.Blocks)),
} }
for i, givenBlock := range content.Blocks { for i, givenBlock := range content.Blocks {
@ -73,11 +73,11 @@ func (w deepWrapper) transformContent(content *zcl.BodyContent) *zcl.BodyContent
return ret return ret
} }
func (w deepWrapper) JustAttributes() (zcl.Attributes, zcl.Diagnostics) { func (w deepWrapper) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
// Attributes can't have bodies or nested blocks, so this is just a thin wrapper. // Attributes can't have bodies or nested blocks, so this is just a thin wrapper.
return w.Transformed.JustAttributes() return w.Transformed.JustAttributes()
} }
func (w deepWrapper) MissingItemRange() zcl.Range { func (w deepWrapper) MissingItemRange() hcl.Range {
return w.Transformed.MissingItemRange() return w.Transformed.MissingItemRange()
} }

View File

@ -6,18 +6,18 @@ import (
"reflect" "reflect"
"github.com/hashicorp/hcl2/hcltest" "github.com/hashicorp/hcl2/hcltest"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
// Assert that deepWrapper implements Body // Assert that deepWrapper implements Body
var deepWrapperIsBody zcl.Body = deepWrapper{} var deepWrapperIsBody hcl.Body = deepWrapper{}
func TestDeep(t *testing.T) { func TestDeep(t *testing.T) {
testTransform := TransformerFunc(func(body zcl.Body) zcl.Body { testTransform := TransformerFunc(func(body hcl.Body) hcl.Body {
_, remain, diags := body.PartialContent(&zcl.BodySchema{ _, remain, diags := body.PartialContent(&hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "remove", Type: "remove",
}, },
@ -27,19 +27,19 @@ func TestDeep(t *testing.T) {
return BodyWithDiagnostics(remain, diags) return BodyWithDiagnostics(remain, diags)
}) })
src := hcltest.MockBody(&zcl.BodyContent{ src := hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]zcl.Expression{ Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"true": hcltest.MockExprLiteral(cty.True), "true": hcltest.MockExprLiteral(cty.True),
}), }),
Blocks: []*zcl.Block{ Blocks: []*hcl.Block{
{ {
Type: "remove", Type: "remove",
Body: zcl.EmptyBody(), Body: hcl.EmptyBody(),
}, },
{ {
Type: "child", Type: "child",
Body: hcltest.MockBody(&zcl.BodyContent{ Body: hcltest.MockBody(&hcl.BodyContent{
Blocks: []*zcl.Block{ Blocks: []*hcl.Block{
{ {
Type: "remove", Type: "remove",
}, },
@ -51,13 +51,13 @@ func TestDeep(t *testing.T) {
wrapped := Deep(src, testTransform) wrapped := Deep(src, testTransform)
rootContent, diags := wrapped.Content(&zcl.BodySchema{ rootContent, diags := wrapped.Content(&hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "true", Name: "true",
}, },
}, },
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "child", Type: "child",
}, },
@ -70,7 +70,7 @@ func TestDeep(t *testing.T) {
} }
} }
wantAttrs := hcltest.MockAttrs(map[string]zcl.Expression{ wantAttrs := hcltest.MockAttrs(map[string]hcl.Expression{
"true": hcltest.MockExprLiteral(cty.True), "true": hcltest.MockExprLiteral(cty.True),
}) })
if !reflect.DeepEqual(rootContent.Attributes, wantAttrs) { if !reflect.DeepEqual(rootContent.Attributes, wantAttrs) {
@ -85,7 +85,7 @@ func TestDeep(t *testing.T) {
} }
childBlock := rootContent.Blocks[0] childBlock := rootContent.Blocks[0]
childContent, diags := childBlock.Body.Content(&zcl.BodySchema{}) childContent, diags := childBlock.Body.Content(&hcl.BodySchema{})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("unexpected diagnostics for child content") t.Errorf("unexpected diagnostics for child content")
for _, diag := range diags { for _, diag := range diags {

View File

@ -1,7 +1,7 @@
package transform package transform
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// A Transformer takes a given body, applies some (possibly no-op) // A Transformer takes a given body, applies some (possibly no-op)
@ -13,14 +13,14 @@ import (
// returns diagnostics when its methods are called. NewErrorBody is a utility // returns diagnostics when its methods are called. NewErrorBody is a utility
// to help with this. // to help with this.
type Transformer interface { type Transformer interface {
TransformBody(zcl.Body) zcl.Body TransformBody(hcl.Body) hcl.Body
} }
// TransformerFunc is a function type that implements Transformer. // TransformerFunc is a function type that implements Transformer.
type TransformerFunc func(zcl.Body) zcl.Body type TransformerFunc func(hcl.Body) hcl.Body
// TransformBody is an implementation of Transformer.TransformBody. // TransformBody is an implementation of Transformer.TransformBody.
func (f TransformerFunc) TransformBody(in zcl.Body) zcl.Body { func (f TransformerFunc) TransformBody(in hcl.Body) hcl.Body {
return f(in) return f(in)
} }
@ -32,7 +32,7 @@ func Chain(c []Transformer) Transformer {
return chain(c) return chain(c)
} }
func (c chain) TransformBody(body zcl.Body) zcl.Body { func (c chain) TransformBody(body hcl.Body) hcl.Body {
for _, t := range c { for _, t := range c {
body = t.TransformBody(body) body = t.TransformBody(body)
} }

View File

@ -15,7 +15,7 @@ function "add" {
The extension is implemented as a pre-processor for `cty.Body` objects. Given The extension is implemented as a pre-processor for `cty.Body` objects. Given
a body that may contain functions, the `DecodeUserFunctions` function searches a body that may contain functions, the `DecodeUserFunctions` function searches
for blocks that define functions and returns a functions map suitable for for blocks that define functions and returns a functions map suitable for
inclusion in a `zcl.EvalContext`. It also returns a new `cty.Body` that inclusion in a `hcl.EvalContext`. It also returns a new `cty.Body` that
contains the remainder of the content from the given body, allowing for contains the remainder of the content from the given body, allowing for
further processing of remaining content. further processing of remaining content.

View File

@ -2,13 +2,13 @@ package userfunc
import ( import (
"github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
) )
var funcBodySchema = &zcl.BodySchema{ var funcBodySchema = &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "params", Name: "params",
Required: true, Required: true,
@ -24,9 +24,9 @@ var funcBodySchema = &zcl.BodySchema{
}, },
} }
func decodeUserFunctions(body zcl.Body, blockType string, contextFunc ContextFunc) (funcs map[string]function.Function, remain zcl.Body, diags zcl.Diagnostics) { func decodeUserFunctions(body hcl.Body, blockType string, contextFunc ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {
schema := &zcl.BodySchema{ schema := &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: blockType, Type: blockType,
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -42,8 +42,8 @@ func decodeUserFunctions(body zcl.Body, blockType string, contextFunc ContextFun
// first call to getBaseCtx will populate context, and then the same // first call to getBaseCtx will populate context, and then the same
// context will be used for all subsequent calls. It's assumed that // context will be used for all subsequent calls. It's assumed that
// all functions in a given body should see an identical context. // all functions in a given body should see an identical context.
var baseCtx *zcl.EvalContext var baseCtx *hcl.EvalContext
getBaseCtx := func() *zcl.EvalContext { getBaseCtx := func() *hcl.EvalContext {
if baseCtx == nil { if baseCtx == nil {
if contextFunc != nil { if contextFunc != nil {
baseCtx = contextFunc() baseCtx = contextFunc()
@ -64,7 +64,7 @@ func decodeUserFunctions(body zcl.Body, blockType string, contextFunc ContextFun
paramsExpr := funcContent.Attributes["params"].Expr paramsExpr := funcContent.Attributes["params"].Expr
resultExpr := funcContent.Attributes["result"].Expr resultExpr := funcContent.Attributes["result"].Expr
var varParamExpr zcl.Expression var varParamExpr hcl.Expression
if funcContent.Attributes["variadic_param"] != nil { if funcContent.Attributes["variadic_param"] != nil {
varParamExpr = funcContent.Attributes["variadic_param"].Expr varParamExpr = funcContent.Attributes["variadic_param"].Expr
} }

View File

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -13,7 +13,7 @@ func TestDecodeUserFunctions(t *testing.T) {
tests := []struct { tests := []struct {
src string src string
testExpr string testExpr string
baseCtx *zcl.EvalContext baseCtx *hcl.EvalContext
want cty.Value want cty.Value
diagCount int diagCount int
}{ }{
@ -98,7 +98,7 @@ function "closure" {
} }
`, `,
`closure()`, `closure()`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"upvalue": cty.True, "upvalue": cty.True,
}, },
@ -138,23 +138,23 @@ function "neg" {
for i, test := range tests { for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
f, diags := zclsyntax.ParseConfig([]byte(test.src), "config", zcl.Pos{Line: 1, Column: 1}) f, diags := hclsyntax.ParseConfig([]byte(test.src), "config", hcl.Pos{Line: 1, Column: 1})
if f == nil || f.Body == nil { if f == nil || f.Body == nil {
t.Fatalf("got nil file or body") t.Fatalf("got nil file or body")
} }
funcs, _, funcsDiags := decodeUserFunctions(f.Body, "function", func() *zcl.EvalContext { funcs, _, funcsDiags := decodeUserFunctions(f.Body, "function", func() *hcl.EvalContext {
return test.baseCtx return test.baseCtx
}) })
diags = append(diags, funcsDiags...) diags = append(diags, funcsDiags...)
expr, exprParseDiags := zclsyntax.ParseExpression([]byte(test.testExpr), "testexpr", zcl.Pos{Line: 1, Column: 1}) expr, exprParseDiags := hclsyntax.ParseExpression([]byte(test.testExpr), "testexpr", hcl.Pos{Line: 1, Column: 1})
diags = append(diags, exprParseDiags...) diags = append(diags, exprParseDiags...)
if expr == nil { if expr == nil {
t.Fatalf("parsing test expr returned nil") t.Fatalf("parsing test expr returned nil")
} }
got, exprDiags := expr.Value(&zcl.EvalContext{ got, exprDiags := expr.Value(&hcl.EvalContext{
Functions: funcs, Functions: funcs,
}) })
diags = append(diags, exprDiags...) diags = append(diags, exprDiags...)

View File

@ -1,7 +1,7 @@
package userfunc package userfunc
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
) )
@ -17,7 +17,7 @@ import (
// configuration language, but more complex applications may use different // configuration language, but more complex applications may use different
// contexts to support lexical scoping depending on where in a configuration // contexts to support lexical scoping depending on where in a configuration
// structure a function declaration is found, etc. // structure a function declaration is found, etc.
type ContextFunc func() *zcl.EvalContext type ContextFunc func() *hcl.EvalContext
// DecodeUserFunctions looks for blocks of the given type in the given body // DecodeUserFunctions looks for blocks of the given type in the given body
// and, for each one found, interprets it as a custom function definition. // and, for each one found, interprets it as a custom function definition.
@ -37,6 +37,6 @@ type ContextFunc func() *zcl.EvalContext
// //
// If the returned diagnostics set has errors then the function map and // If the returned diagnostics set has errors then the function map and
// remain body may be nil or incomplete. // remain body may be nil or incomplete.
func DecodeUserFunctions(body zcl.Body, blockType string, context ContextFunc) (funcs map[string]function.Function, remain zcl.Body, diags zcl.Diagnostics) { func DecodeUserFunctions(body hcl.Body, blockType string, context ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {
return decodeUserFunctions(body, blockType, context) return decodeUserFunctions(body, blockType, context)
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/gocty" "github.com/zclconf/go-cty/cty/gocty"
) )
@ -25,7 +25,7 @@ import (
// are returned then the given value may have been partially-populated but // are returned then the given value may have been partially-populated but
// may still be accessed by a careful caller for static analysis and editor // may still be accessed by a careful caller for static analysis and editor
// integration use-cases. // integration use-cases.
func DecodeBody(body zcl.Body, ctx *zcl.EvalContext, val interface{}) zcl.Diagnostics { func DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
rv := reflect.ValueOf(val) rv := reflect.ValueOf(val)
if rv.Kind() != reflect.Ptr { if rv.Kind() != reflect.Ptr {
panic(fmt.Sprintf("target value must be a pointer, not %s", rv.Type().String())) panic(fmt.Sprintf("target value must be a pointer, not %s", rv.Type().String()))
@ -34,7 +34,7 @@ func DecodeBody(body zcl.Body, ctx *zcl.EvalContext, val interface{}) zcl.Diagno
return decodeBodyToValue(body, ctx, rv.Elem()) return decodeBodyToValue(body, ctx, rv.Elem())
} }
func decodeBodyToValue(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value) zcl.Diagnostics { func decodeBodyToValue(body hcl.Body, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics {
et := val.Type() et := val.Type()
switch et.Kind() { switch et.Kind() {
case reflect.Struct: case reflect.Struct:
@ -46,12 +46,12 @@ func decodeBodyToValue(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value) z
} }
} }
func decodeBodyToStruct(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value) zcl.Diagnostics { func decodeBodyToStruct(body hcl.Body, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics {
schema, partial := ImpliedBodySchema(val.Interface()) schema, partial := ImpliedBodySchema(val.Interface())
var content *zcl.BodyContent var content *hcl.BodyContent
var leftovers zcl.Body var leftovers hcl.Body
var diags zcl.Diagnostics var diags hcl.Diagnostics
if partial { if partial {
content, leftovers, diags = body.PartialContent(schema) content, leftovers, diags = body.PartialContent(schema)
} else { } else {
@ -117,8 +117,8 @@ func decodeBodyToStruct(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value)
} }
if len(blocks) > 1 && !isSlice { if len(blocks) > 1 && !isSlice {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Duplicate %s block", typeName), Summary: fmt.Sprintf("Duplicate %s block", typeName),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Only one %s block is allowed. Another was defined at %s.", "Only one %s block is allowed. Another was defined at %s.",
@ -133,8 +133,8 @@ func decodeBodyToStruct(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value)
if isSlice || isPtr { if isSlice || isPtr {
val.Field(fieldIdx).Set(reflect.Zero(field.Type)) val.Field(fieldIdx).Set(reflect.Zero(field.Type))
} else { } else {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Missing %s block", typeName), Summary: fmt.Sprintf("Missing %s block", typeName),
Detail: fmt.Sprintf("A %s block is required.", typeName), Detail: fmt.Sprintf("A %s block is required.", typeName),
Subject: body.MissingItemRange().Ptr(), Subject: body.MissingItemRange().Ptr(),
@ -181,7 +181,7 @@ func decodeBodyToStruct(body zcl.Body, ctx *zcl.EvalContext, val reflect.Value)
return diags return diags
} }
func decodeBodyToMap(body zcl.Body, ctx *zcl.EvalContext, v reflect.Value) zcl.Diagnostics { func decodeBodyToMap(body hcl.Body, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics {
attrs, diags := body.JustAttributes() attrs, diags := body.JustAttributes()
if attrs == nil { if attrs == nil {
return diags return diags
@ -207,8 +207,8 @@ func decodeBodyToMap(body zcl.Body, ctx *zcl.EvalContext, v reflect.Value) zcl.D
return diags return diags
} }
func decodeBlockToValue(block *zcl.Block, ctx *zcl.EvalContext, v reflect.Value) zcl.Diagnostics { func decodeBlockToValue(block *hcl.Block, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics {
var diags zcl.Diagnostics var diags hcl.Diagnostics
ty := v.Type() ty := v.Type()
@ -253,7 +253,7 @@ func decodeBlockToValue(block *zcl.Block, ctx *zcl.EvalContext, v reflect.Value)
// are returned then the given value may have been partially-populated but // are returned then the given value may have been partially-populated but
// may still be accessed by a careful caller for static analysis and editor // may still be accessed by a careful caller for static analysis and editor
// integration use-cases. // integration use-cases.
func DecodeExpression(expr zcl.Expression, ctx *zcl.EvalContext, val interface{}) zcl.Diagnostics { func DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {
srcVal, diags := expr.Value(ctx) srcVal, diags := expr.Value(ctx)
convTy, err := gocty.ImpliedType(val) convTy, err := gocty.ImpliedType(val)
@ -263,8 +263,8 @@ func DecodeExpression(expr zcl.Expression, ctx *zcl.EvalContext, val interface{}
srcVal, err = convert.Convert(srcVal, convTy) srcVal, err = convert.Convert(srcVal, convTy)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsuitable value type", Summary: "Unsuitable value type",
Detail: fmt.Sprintf("Unsuitable value: %s", err.Error()), Detail: fmt.Sprintf("Unsuitable value: %s", err.Error()),
Subject: expr.StartRange().Ptr(), Subject: expr.StartRange().Ptr(),
@ -275,8 +275,8 @@ func DecodeExpression(expr zcl.Expression, ctx *zcl.EvalContext, val interface{}
err = gocty.FromCtyValue(srcVal, val) err = gocty.FromCtyValue(srcVal, val)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsuitable value type", Summary: "Unsuitable value type",
Detail: fmt.Sprintf("Unsuitable value: %s", err.Error()), Detail: fmt.Sprintf("Unsuitable value: %s", err.Error()),
Subject: expr.StartRange().Ptr(), Subject: expr.StartRange().Ptr(),

View File

@ -7,8 +7,8 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/zcl" zclJSON "github.com/hashicorp/hcl2/hcl/json"
zclJSON "github.com/hashicorp/hcl2/zcl/json" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -83,12 +83,12 @@ func TestDecodeBody(t *testing.T) {
}, },
struct { struct {
Name string `zcl:"name"` Name string `zcl:"name"`
Attrs zcl.Attributes `zcl:",remain"` Attrs hcl.Attributes `zcl:",remain"`
}{}, }{},
func(gotI interface{}) bool { func(gotI interface{}) bool {
got := gotI.(struct { got := gotI.(struct {
Name string `zcl:"name"` Name string `zcl:"name"`
Attrs zcl.Attributes `zcl:",remain"` Attrs hcl.Attributes `zcl:",remain"`
}) })
return got.Name == "Ermintrude" && len(got.Attrs) == 1 && got.Attrs["age"] != nil return got.Name == "Ermintrude" && len(got.Attrs) == 1 && got.Attrs["age"] != nil
}, },
@ -101,12 +101,12 @@ func TestDecodeBody(t *testing.T) {
}, },
struct { struct {
Name string `zcl:"name"` Name string `zcl:"name"`
Remain zcl.Body `zcl:",remain"` Remain hcl.Body `zcl:",remain"`
}{}, }{},
func(gotI interface{}) bool { func(gotI interface{}) bool {
got := gotI.(struct { got := gotI.(struct {
Name string `zcl:"name"` Name string `zcl:"name"`
Remain zcl.Body `zcl:",remain"` Remain hcl.Body `zcl:",remain"`
}) })
attrs, _ := got.Remain.JustAttributes() attrs, _ := got.Remain.JustAttributes()
@ -420,9 +420,9 @@ func TestDecodeBody(t *testing.T) {
"name": "Ermintrude", "name": "Ermintrude",
"age": 89, "age": 89,
}, },
map[string]*zcl.Attribute(nil), map[string]*hcl.Attribute(nil),
func(gotI interface{}) bool { func(gotI interface{}) bool {
got := gotI.(map[string]*zcl.Attribute) got := gotI.(map[string]*hcl.Attribute)
return len(got) == 2 && got["name"] != nil && got["age"] != nil return len(got) == 2 && got["name"] != nil && got["age"] != nil
}, },
0, 0,
@ -432,9 +432,9 @@ func TestDecodeBody(t *testing.T) {
"name": "Ermintrude", "name": "Ermintrude",
"age": 13, "age": 13,
}, },
map[string]zcl.Expression(nil), map[string]hcl.Expression(nil),
func(gotI interface{}) bool { func(gotI interface{}) bool {
got := gotI.(map[string]zcl.Expression) got := gotI.(map[string]hcl.Expression)
return len(got) == 2 && got["name"] != nil && got["age"] != nil return len(got) == 2 && got["name"] != nil && got["age"] != nil
}, },
0, 0,
@ -561,17 +561,17 @@ type fixedExpression struct {
val cty.Value val cty.Value
} }
func (e *fixedExpression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *fixedExpression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return e.val, nil return e.val, nil
} }
func (e *fixedExpression) Range() (r zcl.Range) { func (e *fixedExpression) Range() (r hcl.Range) {
return return
} }
func (e *fixedExpression) StartRange() (r zcl.Range) { func (e *fixedExpression) StartRange() (r hcl.Range) {
return return
} }
func (e *fixedExpression) Variables() []zcl.Traversal { func (e *fixedExpression) Variables() []hcl.Traversal {
return nil return nil
} }

View File

@ -19,11 +19,11 @@
// label indicates that the value is to populated from a block label // label indicates that the value is to populated from a block label
// remain indicates that the value is to be populated from the remaining body after populating other fields // remain indicates that the value is to be populated from the remaining body after populating other fields
// //
// "attr" fields may either be of type *zcl.Expression, in which case the raw // "attr" fields may either be of type *hcl.Expression, in which case the raw
// expression is assigned, or of any type accepted by gocty, in which case // expression is assigned, or of any type accepted by gocty, in which case
// gocty will be used to assign the value to a native Go type. // gocty will be used to assign the value to a native Go type.
// //
// "block" fields may be of type *zcl.Block or zcl.Body, in which case the // "block" fields may be of type *hcl.Block or hcl.Body, in which case the
// corresponding raw value is assigned, or may be a struct that recursively // corresponding raw value is assigned, or may be a struct that recursively
// uses the same tags. Block fields may also be slices of any of these types, // uses the same tags. Block fields may also be slices of any of these types,
// in which case multiple blocks of the corresponding type are decoded into // in which case multiple blocks of the corresponding type are decoded into
@ -35,7 +35,7 @@
// an identifier for the label in diagnostic messages. // an identifier for the label in diagnostic messages.
// //
// "remain" can be placed on a single field that may be either of type // "remain" can be placed on a single field that may be either of type
// zcl.Body or zcl.Attributes, in which case any remaining body content is // hcl.Body or hcl.Attributes, in which case any remaining body content is
// placed into this field for delayed processing. If no "remain" field is // placed into this field for delayed processing. If no "remain" field is
// present then any attributes or blocks not matched by another valid tag // present then any attributes or blocks not matched by another valid tag
// will cause an error diagnostic. // will cause an error diagnostic.

View File

@ -6,10 +6,10 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// ImpliedBodySchema produces a zcl.BodySchema derived from the type of the // ImpliedBodySchema produces a hcl.BodySchema derived from the type of the
// given value, which must be a struct value or a pointer to one. If an // given value, which must be a struct value or a pointer to one. If an
// inappropriate value is passed, this function will panic. // inappropriate value is passed, this function will panic.
// //
@ -19,7 +19,7 @@ import (
// This uses the tags on the fields of the struct to discover how each // This uses the tags on the fields of the struct to discover how each
// field's value should be expressed within configuration. If an invalid // field's value should be expressed within configuration. If an invalid
// mapping is attempted, this function will panic. // mapping is attempted, this function will panic.
func ImpliedBodySchema(val interface{}) (schema *zcl.BodySchema, partial bool) { func ImpliedBodySchema(val interface{}) (schema *hcl.BodySchema, partial bool) {
ty := reflect.TypeOf(val) ty := reflect.TypeOf(val)
if ty.Kind() == reflect.Ptr { if ty.Kind() == reflect.Ptr {
@ -30,8 +30,8 @@ func ImpliedBodySchema(val interface{}) (schema *zcl.BodySchema, partial bool) {
panic(fmt.Sprintf("given value must be struct, not %T", val)) panic(fmt.Sprintf("given value must be struct, not %T", val))
} }
var attrSchemas []zcl.AttributeSchema var attrSchemas []hcl.AttributeSchema
var blockSchemas []zcl.BlockHeaderSchema var blockSchemas []hcl.BlockHeaderSchema
tags := getFieldTags(ty) tags := getFieldTags(ty)
@ -43,7 +43,7 @@ func ImpliedBodySchema(val interface{}) (schema *zcl.BodySchema, partial bool) {
for _, n := range attrNames { for _, n := range attrNames {
idx := tags.Attributes[n] idx := tags.Attributes[n]
field := ty.Field(idx) field := ty.Field(idx)
attrSchemas = append(attrSchemas, zcl.AttributeSchema{ attrSchemas = append(attrSchemas, hcl.AttributeSchema{
Name: n, Name: n,
Required: field.Type.Kind() != reflect.Ptr, Required: field.Type.Kind() != reflect.Ptr,
}) })
@ -78,14 +78,14 @@ func ImpliedBodySchema(val interface{}) (schema *zcl.BodySchema, partial bool) {
} }
} }
blockSchemas = append(blockSchemas, zcl.BlockHeaderSchema{ blockSchemas = append(blockSchemas, hcl.BlockHeaderSchema{
Type: n, Type: n,
LabelNames: labelNames, LabelNames: labelNames,
}) })
} }
partial = tags.Remain != nil partial = tags.Remain != nil
schema = &zcl.BodySchema{ schema = &hcl.BodySchema{
Attributes: attrSchemas, Attributes: attrSchemas,
Blocks: blockSchemas, Blocks: blockSchemas,
} }

View File

@ -6,25 +6,25 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
func TestImpliedBodySchema(t *testing.T) { func TestImpliedBodySchema(t *testing.T) {
tests := []struct { tests := []struct {
val interface{} val interface{}
wantSchema *zcl.BodySchema wantSchema *hcl.BodySchema
wantPartial bool wantPartial bool
}{ }{
{ {
struct{}{}, struct{}{},
&zcl.BodySchema{}, &hcl.BodySchema{},
false, false,
}, },
{ {
struct { struct {
Ignored bool Ignored bool
}{}, }{},
&zcl.BodySchema{}, &hcl.BodySchema{},
false, false,
}, },
{ {
@ -32,8 +32,8 @@ func TestImpliedBodySchema(t *testing.T) {
Attr1 bool `zcl:"attr1"` Attr1 bool `zcl:"attr1"`
Attr2 bool `zcl:"attr2"` Attr2 bool `zcl:"attr2"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "attr1", Name: "attr1",
Required: true, Required: true,
@ -50,8 +50,8 @@ func TestImpliedBodySchema(t *testing.T) {
struct { struct {
Attr *bool `zcl:"attr,attr"` Attr *bool `zcl:"attr,attr"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "attr", Name: "attr",
Required: false, Required: false,
@ -64,8 +64,8 @@ func TestImpliedBodySchema(t *testing.T) {
struct { struct {
Thing struct{} `zcl:"thing,block"` Thing struct{} `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
}, },
@ -80,8 +80,8 @@ func TestImpliedBodySchema(t *testing.T) {
Name string `zcl:"name,label"` Name string `zcl:"name,label"`
} `zcl:"thing,block"` } `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
LabelNames: []string{"type", "name"}, LabelNames: []string{"type", "name"},
@ -97,8 +97,8 @@ func TestImpliedBodySchema(t *testing.T) {
Name string `zcl:"name,label"` Name string `zcl:"name,label"`
} `zcl:"thing,block"` } `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
LabelNames: []string{"type", "name"}, LabelNames: []string{"type", "name"},
@ -114,8 +114,8 @@ func TestImpliedBodySchema(t *testing.T) {
Name string `zcl:"name,label"` Name string `zcl:"name,label"`
} `zcl:"thing,block"` } `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
LabelNames: []string{"type", "name"}, LabelNames: []string{"type", "name"},
@ -131,8 +131,8 @@ func TestImpliedBodySchema(t *testing.T) {
Something string `zcl:"something"` Something string `zcl:"something"`
} `zcl:"thing,block"` } `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -148,14 +148,14 @@ func TestImpliedBodySchema(t *testing.T) {
Name string `zcl:"name,label"` Name string `zcl:"name,label"`
} `zcl:"thing,block"` } `zcl:"thing,block"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "doodad", Name: "doodad",
Required: true, Required: true,
}, },
}, },
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "thing", Type: "thing",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -169,8 +169,8 @@ func TestImpliedBodySchema(t *testing.T) {
Doodad string `zcl:"doodad"` Doodad string `zcl:"doodad"`
Config string `zcl:",remain"` Config string `zcl:",remain"`
}{}, }{},
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "doodad", Name: "doodad",
Required: true, Required: true,

View File

@ -3,14 +3,14 @@ package gohcl
import ( import (
"reflect" "reflect"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
var victimExpr zcl.Expression var victimExpr hcl.Expression
var victimBody zcl.Body var victimBody hcl.Body
var exprType = reflect.TypeOf(&victimExpr).Elem() var exprType = reflect.TypeOf(&victimExpr).Elem()
var bodyType = reflect.TypeOf(&victimBody).Elem() var bodyType = reflect.TypeOf(&victimBody).Elem()
var blockType = reflect.TypeOf((*zcl.Block)(nil)) var blockType = reflect.TypeOf((*hcl.Block)(nil))
var attrType = reflect.TypeOf((*zcl.Attribute)(nil)) var attrType = reflect.TypeOf((*hcl.Attribute)(nil))
var attrsType = reflect.TypeOf(zcl.Attributes(nil)) var attrsType = reflect.TypeOf(hcl.Attributes(nil))

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"fmt" "fmt"
@ -67,7 +67,7 @@ func (d Diagnostics) Error() string {
// This is provided as a convenience for returning from a function that // This is provided as a convenience for returning from a function that
// collects and then returns a set of diagnostics: // collects and then returns a set of diagnostics:
// //
// return nil, diags.Append(&zcl.Diagnostic{ ... }) // return nil, diags.Append(&hcl.Diagnostic{ ... })
// //
// Note that this modifies the array underlying the diagnostics slice, so // Note that this modifies the array underlying the diagnostics slice, so
// must be used carefully within a single codepath. It is incorrect (and rude) // must be used carefully within a single codepath. It is incorrect (and rude)

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"bufio" "bufio"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"bytes" "bytes"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"github.com/agext/levenshtein" "github.com/agext/levenshtein"

1
hcl/doc.go Normal file
View File

@ -0,0 +1 @@
package hcl

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/agext/levenshtein" "github.com/agext/levenshtein"

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import "testing" import "testing"

View File

@ -4,4 +4,4 @@
// In normal use applications should rarely depend on this package directly, // In normal use applications should rarely depend on this package directly,
// instead preferring the higher-level interface of the main zcl page and // instead preferring the higher-level interface of the main zcl page and
// its companion zclparse. // its companion zclparse.
package zclsyntax package hclsyntax

View File

@ -1,9 +1,9 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
@ -13,60 +13,60 @@ import (
type Expression interface { type Expression interface {
Node Node
// The zcl.Expression methods are duplicated here, rather than simply // The hcl.Expression methods are duplicated here, rather than simply
// embedded, because both Node and zcl.Expression have a Range method // embedded, because both Node and hcl.Expression have a Range method
// and so they conflict. // and so they conflict.
Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
Variables() []zcl.Traversal Variables() []hcl.Traversal
StartRange() zcl.Range StartRange() hcl.Range
} }
// Assert that Expression implements zcl.Expression // Assert that Expression implements hcl.Expression
var assertExprImplExpr zcl.Expression = Expression(nil) var assertExprImplExpr hcl.Expression = Expression(nil)
// LiteralValueExpr is an expression that just always returns a given value. // LiteralValueExpr is an expression that just always returns a given value.
type LiteralValueExpr struct { type LiteralValueExpr struct {
Val cty.Value Val cty.Value
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) { func (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) {
// Literal values have no child nodes // Literal values have no child nodes
} }
func (e *LiteralValueExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *LiteralValueExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return e.Val, nil return e.Val, nil
} }
func (e *LiteralValueExpr) Range() zcl.Range { func (e *LiteralValueExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *LiteralValueExpr) StartRange() zcl.Range { func (e *LiteralValueExpr) StartRange() hcl.Range {
return e.SrcRange return e.SrcRange
} }
// ScopeTraversalExpr is an Expression that retrieves a value from the scope // ScopeTraversalExpr is an Expression that retrieves a value from the scope
// using a traversal. // using a traversal.
type ScopeTraversalExpr struct { type ScopeTraversalExpr struct {
Traversal zcl.Traversal Traversal hcl.Traversal
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) { func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {
// Scope traversals have no child nodes // Scope traversals have no child nodes
} }
func (e *ScopeTraversalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return e.Traversal.TraverseAbs(ctx) return e.Traversal.TraverseAbs(ctx)
} }
func (e *ScopeTraversalExpr) Range() zcl.Range { func (e *ScopeTraversalExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *ScopeTraversalExpr) StartRange() zcl.Range { func (e *ScopeTraversalExpr) StartRange() hcl.Range {
return e.SrcRange return e.SrcRange
} }
@ -74,26 +74,26 @@ func (e *ScopeTraversalExpr) StartRange() zcl.Range {
// value using a _relative_ traversal. // value using a _relative_ traversal.
type RelativeTraversalExpr struct { type RelativeTraversalExpr struct {
Source Expression Source Expression
Traversal zcl.Traversal Traversal hcl.Traversal
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) { func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) {
// Scope traversals have no child nodes // Scope traversals have no child nodes
} }
func (e *RelativeTraversalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
src, diags := e.Source.Value(ctx) src, diags := e.Source.Value(ctx)
ret, travDiags := e.Traversal.TraverseRel(src) ret, travDiags := e.Traversal.TraverseRel(src)
diags = append(diags, travDiags...) diags = append(diags, travDiags...)
return ret, diags return ret, diags
} }
func (e *RelativeTraversalExpr) Range() zcl.Range { func (e *RelativeTraversalExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *RelativeTraversalExpr) StartRange() zcl.Range { func (e *RelativeTraversalExpr) StartRange() hcl.Range {
return e.SrcRange return e.SrcRange
} }
@ -107,9 +107,9 @@ type FunctionCallExpr struct {
// expand to be one argument per element. // expand to be one argument per element.
ExpandFinal bool ExpandFinal bool
NameRange zcl.Range NameRange hcl.Range
OpenParenRange zcl.Range OpenParenRange hcl.Range
CloseParenRange zcl.Range CloseParenRange hcl.Range
} }
func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) { func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {
@ -118,8 +118,8 @@ func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {
} }
} }
func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
var f function.Function var f function.Function
exists := false exists := false
@ -140,9 +140,9 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
if !exists { if !exists {
if !hasNonNilMap { if !hasNonNilMap {
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Function calls not allowed", Summary: "Function calls not allowed",
Detail: "Functions may not be called here.", Detail: "Functions may not be called here.",
Subject: e.Range().Ptr(), Subject: e.Range().Ptr(),
@ -159,9 +159,9 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
suggestion = fmt.Sprintf(" Did you mean %q?", suggestion) suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
} }
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Call to unknown function", Summary: "Call to unknown function",
Detail: fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion), Detail: fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion),
Subject: &e.NameRange, Subject: &e.NameRange,
@ -189,8 +189,8 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
switch { switch {
case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType(): case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():
if expandVal.IsNull() { if expandVal.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid expanding argument value", Summary: "Invalid expanding argument value",
Detail: "The expanding argument (indicated by ...) must not be null.", Detail: "The expanding argument (indicated by ...) must not be null.",
Context: expandExpr.Range().Ptr(), Context: expandExpr.Range().Ptr(),
@ -214,8 +214,8 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
} }
args = newArgs args = newArgs
default: default:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid expanding argument value", Summary: "Invalid expanding argument value",
Detail: "The expanding argument (indicated by ...) must be of a tuple, list, or set type.", Detail: "The expanding argument (indicated by ...) must be of a tuple, list, or set type.",
Context: expandExpr.Range().Ptr(), Context: expandExpr.Range().Ptr(),
@ -231,9 +231,9 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
if varParam != nil { if varParam != nil {
qual = " at least" qual = " at least"
} }
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Not enough function arguments", Summary: "Not enough function arguments",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Function %q expects%s %d argument(s). Missing value for %q.", "Function %q expects%s %d argument(s). Missing value for %q.",
@ -246,9 +246,9 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
} }
if varParam == nil && len(args) > len(params) { if varParam == nil && len(args) > len(params) {
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Too many function arguments", Summary: "Too many function arguments",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Function %q expects only %d argument(s).", "Function %q expects only %d argument(s).",
@ -278,8 +278,8 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
// Try to convert our value to the parameter type // Try to convert our value to the parameter type
val, err := convert.Convert(val, param.Type) val, err := convert.Convert(val, param.Type)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid function argument", Summary: "Invalid function argument",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Invalid value for %q parameter: %s.", "Invalid value for %q parameter: %s.",
@ -315,8 +315,8 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
// TODO: we should also unpick a PathError here and show the // TODO: we should also unpick a PathError here and show the
// path to the deep value where the error was detected. // path to the deep value where the error was detected.
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid function argument", Summary: "Invalid function argument",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Invalid value for %q parameter: %s.", "Invalid value for %q parameter: %s.",
@ -327,8 +327,8 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
}) })
default: default:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Error in function call", Summary: "Error in function call",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Call to function %q failed: %s.", "Call to function %q failed: %s.",
@ -345,12 +345,12 @@ func (e *FunctionCallExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
return resultVal, diags return resultVal, diags
} }
func (e *FunctionCallExpr) Range() zcl.Range { func (e *FunctionCallExpr) Range() hcl.Range {
return zcl.RangeBetween(e.NameRange, e.CloseParenRange) return hcl.RangeBetween(e.NameRange, e.CloseParenRange)
} }
func (e *FunctionCallExpr) StartRange() zcl.Range { func (e *FunctionCallExpr) StartRange() hcl.Range {
return zcl.RangeBetween(e.NameRange, e.OpenParenRange) return hcl.RangeBetween(e.NameRange, e.OpenParenRange)
} }
type ConditionalExpr struct { type ConditionalExpr struct {
@ -358,7 +358,7 @@ type ConditionalExpr struct {
TrueResult Expression TrueResult Expression
FalseResult Expression FalseResult Expression
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) { func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {
@ -367,17 +367,17 @@ func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {
e.FalseResult = w(e.FalseResult).(Expression) e.FalseResult = w(e.FalseResult).(Expression)
} }
func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
trueResult, trueDiags := e.TrueResult.Value(ctx) trueResult, trueDiags := e.TrueResult.Value(ctx)
falseResult, falseDiags := e.FalseResult.Value(ctx) falseResult, falseDiags := e.FalseResult.Value(ctx)
var diags zcl.Diagnostics var diags hcl.Diagnostics
// Try to find a type that both results can be converted to. // Try to find a type that both results can be converted to.
resultType, convs := convert.UnifyUnsafe([]cty.Type{trueResult.Type(), falseResult.Type()}) resultType, convs := convert.UnifyUnsafe([]cty.Type{trueResult.Type(), falseResult.Type()})
if resultType == cty.NilType { if resultType == cty.NilType {
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Inconsistent conditional result types", Summary: "Inconsistent conditional result types",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
// FIXME: Need a helper function for showing natural-language type diffs, // FIXME: Need a helper function for showing natural-language type diffs,
@ -387,7 +387,7 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
"The true and false result expressions must have consistent types. The given expressions are %s and %s, respectively.", "The true and false result expressions must have consistent types. The given expressions are %s and %s, respectively.",
trueResult.Type(), falseResult.Type(), trueResult.Type(), falseResult.Type(),
), ),
Subject: zcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(), Subject: hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(),
Context: &e.SrcRange, Context: &e.SrcRange,
}, },
} }
@ -396,8 +396,8 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
condResult, condDiags := e.Condition.Value(ctx) condResult, condDiags := e.Condition.Value(ctx)
diags = append(diags, condDiags...) diags = append(diags, condDiags...)
if condResult.IsNull() { if condResult.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Null condition", Summary: "Null condition",
Detail: "The condition value is null. Conditions must either be true or false.", Detail: "The condition value is null. Conditions must either be true or false.",
Subject: e.Condition.Range().Ptr(), Subject: e.Condition.Range().Ptr(),
@ -410,8 +410,8 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
} }
condResult, err := convert.Convert(condResult, cty.Bool) condResult, err := convert.Convert(condResult, cty.Bool)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect condition type", Summary: "Incorrect condition type",
Detail: fmt.Sprintf("The condition expression must be of type bool."), Detail: fmt.Sprintf("The condition expression must be of type bool."),
Subject: e.Condition.Range().Ptr(), Subject: e.Condition.Range().Ptr(),
@ -427,8 +427,8 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
trueResult, err = convs[0](trueResult) trueResult, err = convs[0](trueResult)
if err != nil { if err != nil {
// Unsafe conversion failed with the concrete result value // Unsafe conversion failed with the concrete result value
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Inconsistent conditional result types", Summary: "Inconsistent conditional result types",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"The true result value has the wrong type: %s.", "The true result value has the wrong type: %s.",
@ -448,8 +448,8 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
falseResult, err = convs[1](falseResult) falseResult, err = convs[1](falseResult)
if err != nil { if err != nil {
// Unsafe conversion failed with the concrete result value // Unsafe conversion failed with the concrete result value
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Inconsistent conditional result types", Summary: "Inconsistent conditional result types",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"The false result value has the wrong type: %s.", "The false result value has the wrong type: %s.",
@ -465,11 +465,11 @@ func (e *ConditionalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
} }
} }
func (e *ConditionalExpr) Range() zcl.Range { func (e *ConditionalExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *ConditionalExpr) StartRange() zcl.Range { func (e *ConditionalExpr) StartRange() hcl.Range {
return e.Condition.StartRange() return e.Condition.StartRange()
} }
@ -477,8 +477,8 @@ type IndexExpr struct {
Collection Expression Collection Expression
Key Expression Key Expression
SrcRange zcl.Range SrcRange hcl.Range
OpenRange zcl.Range OpenRange hcl.Range
} }
func (e *IndexExpr) walkChildNodes(w internalWalkFunc) { func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
@ -486,29 +486,29 @@ func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
e.Key = w(e.Key).(Expression) e.Key = w(e.Key).(Expression)
} }
func (e *IndexExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
coll, collDiags := e.Collection.Value(ctx) coll, collDiags := e.Collection.Value(ctx)
key, keyDiags := e.Key.Value(ctx) key, keyDiags := e.Key.Value(ctx)
diags = append(diags, collDiags...) diags = append(diags, collDiags...)
diags = append(diags, keyDiags...) diags = append(diags, keyDiags...)
return zcl.Index(coll, key, &e.SrcRange) return hcl.Index(coll, key, &e.SrcRange)
} }
func (e *IndexExpr) Range() zcl.Range { func (e *IndexExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *IndexExpr) StartRange() zcl.Range { func (e *IndexExpr) StartRange() hcl.Range {
return e.OpenRange return e.OpenRange
} }
type TupleConsExpr struct { type TupleConsExpr struct {
Exprs []Expression Exprs []Expression
SrcRange zcl.Range SrcRange hcl.Range
OpenRange zcl.Range OpenRange hcl.Range
} }
func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) { func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {
@ -517,9 +517,9 @@ func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {
} }
} }
func (e *TupleConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *TupleConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var vals []cty.Value var vals []cty.Value
var diags zcl.Diagnostics var diags hcl.Diagnostics
vals = make([]cty.Value, len(e.Exprs)) vals = make([]cty.Value, len(e.Exprs))
for i, expr := range e.Exprs { for i, expr := range e.Exprs {
@ -531,19 +531,19 @@ func (e *TupleConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
return cty.TupleVal(vals), diags return cty.TupleVal(vals), diags
} }
func (e *TupleConsExpr) Range() zcl.Range { func (e *TupleConsExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *TupleConsExpr) StartRange() zcl.Range { func (e *TupleConsExpr) StartRange() hcl.Range {
return e.OpenRange return e.OpenRange
} }
type ObjectConsExpr struct { type ObjectConsExpr struct {
Items []ObjectConsItem Items []ObjectConsItem
SrcRange zcl.Range SrcRange hcl.Range
OpenRange zcl.Range OpenRange hcl.Range
} }
type ObjectConsItem struct { type ObjectConsItem struct {
@ -558,9 +558,9 @@ func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) {
} }
} }
func (e *ObjectConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var vals map[string]cty.Value var vals map[string]cty.Value
var diags zcl.Diagnostics var diags hcl.Diagnostics
// This will get set to true if we fail to produce any of our keys, // This will get set to true if we fail to produce any of our keys,
// either because they are actually unknown or if the evaluation produces // either because they are actually unknown or if the evaluation produces
@ -586,8 +586,8 @@ func (e *ObjectConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics
} }
if key.IsNull() { if key.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Null value as key", Summary: "Null value as key",
Detail: "Can't use a null value as a key.", Detail: "Can't use a null value as a key.",
Subject: item.ValueExpr.Range().Ptr(), Subject: item.ValueExpr.Range().Ptr(),
@ -599,8 +599,8 @@ func (e *ObjectConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics
var err error var err error
key, err = convert.Convert(key, cty.String) key, err = convert.Convert(key, cty.String)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect key type", Summary: "Incorrect key type",
Detail: fmt.Sprintf("Can't use this value as a key: %s.", err.Error()), Detail: fmt.Sprintf("Can't use this value as a key: %s.", err.Error()),
Subject: item.ValueExpr.Range().Ptr(), Subject: item.ValueExpr.Range().Ptr(),
@ -626,11 +626,11 @@ func (e *ObjectConsExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics
return cty.ObjectVal(vals), diags return cty.ObjectVal(vals), diags
} }
func (e *ObjectConsExpr) Range() zcl.Range { func (e *ObjectConsExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *ObjectConsExpr) StartRange() zcl.Range { func (e *ObjectConsExpr) StartRange() hcl.Range {
return e.OpenRange return e.OpenRange
} }
@ -651,20 +651,20 @@ type ForExpr struct {
Group bool // set if the ellipsis is used on the value in an object for Group bool // set if the ellipsis is used on the value in an object for
SrcRange zcl.Range SrcRange hcl.Range
OpenRange zcl.Range OpenRange hcl.Range
CloseRange zcl.Range CloseRange hcl.Range
} }
func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
collVal, collDiags := e.CollExpr.Value(ctx) collVal, collDiags := e.CollExpr.Value(ctx)
diags = append(diags, collDiags...) diags = append(diags, collDiags...)
if collVal.IsNull() { if collVal.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Iteration over null value", Summary: "Iteration over null value",
Detail: "A null value cannot be used as the collection in a 'for' expression.", Detail: "A null value cannot be used as the collection in a 'for' expression.",
Subject: e.CollExpr.Range().Ptr(), Subject: e.CollExpr.Range().Ptr(),
@ -676,8 +676,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
return cty.DynamicVal, diags return cty.DynamicVal, diags
} }
if !collVal.CanIterateElements() { if !collVal.CanIterateElements() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Iteration over non-iterable value", Summary: "Iteration over non-iterable value",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"A value of type %s cannot be used as the collection in a 'for' expression.", "A value of type %s cannot be used as the collection in a 'for' expression.",
@ -708,8 +708,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
result, condDiags := e.CondExpr.Value(childCtx) result, condDiags := e.CondExpr.Value(childCtx)
diags = append(diags, condDiags...) diags = append(diags, condDiags...)
if result.IsNull() { if result.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Condition is null", Summary: "Condition is null",
Detail: "The value of the 'if' clause must not be null.", Detail: "The value of the 'if' clause must not be null.",
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -719,8 +719,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
} }
_, err := convert.Convert(result, cty.Bool) _, err := convert.Convert(result, cty.Bool)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' condition", Summary: "Invalid 'for' condition",
Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -758,8 +758,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
diags = append(diags, condDiags...) diags = append(diags, condDiags...)
if includeRaw.IsNull() { if includeRaw.IsNull() {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Condition is null", Summary: "Condition is null",
Detail: "The value of the 'if' clause must not be null.", Detail: "The value of the 'if' clause must not be null.",
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -772,8 +772,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
include, err := convert.Convert(includeRaw, cty.Bool) include, err := convert.Convert(includeRaw, cty.Bool)
if err != nil { if err != nil {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' condition", Summary: "Invalid 'for' condition",
Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -798,8 +798,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
diags = append(diags, keyDiags...) diags = append(diags, keyDiags...)
if keyRaw.IsNull() { if keyRaw.IsNull() {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid object key", Summary: "Invalid object key",
Detail: "Key expression in 'for' expression must not produce a null value.", Detail: "Key expression in 'for' expression must not produce a null value.",
Subject: e.KeyExpr.Range().Ptr(), Subject: e.KeyExpr.Range().Ptr(),
@ -817,8 +817,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
key, err := convert.Convert(keyRaw, cty.String) key, err := convert.Convert(keyRaw, cty.String)
if err != nil { if err != nil {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid object key", Summary: "Invalid object key",
Detail: fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()), Detail: fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()),
Subject: e.KeyExpr.Range().Ptr(), Subject: e.KeyExpr.Range().Ptr(),
@ -838,8 +838,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
} else { } else {
k := key.AsString() k := key.AsString()
if _, exists := vals[k]; exists { if _, exists := vals[k]; exists {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Duplicate object key", Summary: "Duplicate object key",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Two different items produced the key %q in this for expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.", "Two different items produced the key %q in this for expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.",
@ -886,8 +886,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
diags = append(diags, condDiags...) diags = append(diags, condDiags...)
if includeRaw.IsNull() { if includeRaw.IsNull() {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Condition is null", Summary: "Condition is null",
Detail: "The value of the 'if' clause must not be null.", Detail: "The value of the 'if' clause must not be null.",
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -908,8 +908,8 @@ func (e *ForExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
include, err := convert.Convert(includeRaw, cty.Bool) include, err := convert.Convert(includeRaw, cty.Bool)
if err != nil { if err != nil {
if known { if known {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' condition", Summary: "Invalid 'for' condition",
Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
Subject: e.CondExpr.Range().Ptr(), Subject: e.CondExpr.Range().Ptr(),
@ -968,11 +968,11 @@ func (e *ForExpr) walkChildNodes(w internalWalkFunc) {
} }
} }
func (e *ForExpr) Range() zcl.Range { func (e *ForExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *ForExpr) StartRange() zcl.Range { func (e *ForExpr) StartRange() hcl.Range {
return e.OpenRange return e.OpenRange
} }
@ -981,11 +981,11 @@ type SplatExpr struct {
Each Expression Each Expression
Item *AnonSymbolExpr Item *AnonSymbolExpr
SrcRange zcl.Range SrcRange hcl.Range
MarkerRange zcl.Range MarkerRange hcl.Range
} }
func (e *SplatExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
sourceVal, diags := e.Source.Value(ctx) sourceVal, diags := e.Source.Value(ctx)
if diags.HasErrors() { if diags.HasErrors() {
// We'll evaluate our "Each" expression here just to see if it // We'll evaluate our "Each" expression here just to see if it
@ -998,12 +998,12 @@ func (e *SplatExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
} }
if sourceVal.IsNull() { if sourceVal.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Splat of null value", Summary: "Splat of null value",
Detail: "Splat expressions (with the * symbol) cannot be applied to null values.", Detail: "Splat expressions (with the * symbol) cannot be applied to null values.",
Subject: e.Source.Range().Ptr(), Subject: e.Source.Range().Ptr(),
Context: zcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(), Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
}) })
return cty.DynamicVal, diags return cty.DynamicVal, diags
} }
@ -1051,11 +1051,11 @@ func (e *SplatExpr) walkChildNodes(w internalWalkFunc) {
e.Each = w(e.Each).(Expression) e.Each = w(e.Each).(Expression)
} }
func (e *SplatExpr) Range() zcl.Range { func (e *SplatExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *SplatExpr) StartRange() zcl.Range { func (e *SplatExpr) StartRange() hcl.Range {
return e.MarkerRange return e.MarkerRange
} }
@ -1071,11 +1071,11 @@ func (e *SplatExpr) StartRange() zcl.Range {
// in terms of another node (i.e. a splat expression) which temporarily // in terms of another node (i.e. a splat expression) which temporarily
// assigns it a value. // assigns it a value.
type AnonSymbolExpr struct { type AnonSymbolExpr struct {
SrcRange zcl.Range SrcRange hcl.Range
values map[*zcl.EvalContext]cty.Value values map[*hcl.EvalContext]cty.Value
} }
func (e *AnonSymbolExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
if ctx == nil { if ctx == nil {
return cty.DynamicVal, nil return cty.DynamicVal, nil
} }
@ -1088,9 +1088,9 @@ func (e *AnonSymbolExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics
// setValue sets a temporary local value for the expression when evaluated // setValue sets a temporary local value for the expression when evaluated
// in the given context, which must be non-nil. // in the given context, which must be non-nil.
func (e *AnonSymbolExpr) setValue(ctx *zcl.EvalContext, val cty.Value) { func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
if e.values == nil { if e.values == nil {
e.values = make(map[*zcl.EvalContext]cty.Value) e.values = make(map[*hcl.EvalContext]cty.Value)
} }
if ctx == nil { if ctx == nil {
panic("can't setValue for a nil EvalContext") panic("can't setValue for a nil EvalContext")
@ -1098,7 +1098,7 @@ func (e *AnonSymbolExpr) setValue(ctx *zcl.EvalContext, val cty.Value) {
e.values[ctx] = val e.values[ctx] = val
} }
func (e *AnonSymbolExpr) clearValue(ctx *zcl.EvalContext) { func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {
if e.values == nil { if e.values == nil {
return return
} }
@ -1112,10 +1112,10 @@ func (e *AnonSymbolExpr) walkChildNodes(w internalWalkFunc) {
// AnonSymbolExpr is a leaf node in the tree // AnonSymbolExpr is a leaf node in the tree
} }
func (e *AnonSymbolExpr) Range() zcl.Range { func (e *AnonSymbolExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *AnonSymbolExpr) StartRange() zcl.Range { func (e *AnonSymbolExpr) StartRange() hcl.Range {
return e.SrcRange return e.SrcRange
} }

View File

@ -1,9 +1,9 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
@ -125,7 +125,7 @@ type BinaryOpExpr struct {
Op *Operation Op *Operation
RHS Expression RHS Expression
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) { func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {
@ -133,13 +133,13 @@ func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {
e.RHS = w(e.RHS).(Expression) e.RHS = w(e.RHS).(Expression)
} }
func (e *BinaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
impl := e.Op.Impl // assumed to be a function taking exactly two arguments impl := e.Op.Impl // assumed to be a function taking exactly two arguments
params := impl.Params() params := impl.Params()
lhsParam := params[0] lhsParam := params[0]
rhsParam := params[1] rhsParam := params[1]
var diags zcl.Diagnostics var diags hcl.Diagnostics
givenLHSVal, lhsDiags := e.LHS.Value(ctx) givenLHSVal, lhsDiags := e.LHS.Value(ctx)
givenRHSVal, rhsDiags := e.RHS.Value(ctx) givenRHSVal, rhsDiags := e.RHS.Value(ctx)
@ -148,8 +148,8 @@ func (e *BinaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type) lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid operand", Summary: "Invalid operand",
Detail: fmt.Sprintf("Unsuitable value for left operand: %s.", err), Detail: fmt.Sprintf("Unsuitable value for left operand: %s.", err),
Subject: e.LHS.Range().Ptr(), Subject: e.LHS.Range().Ptr(),
@ -158,8 +158,8 @@ func (e *BinaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
} }
rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type) rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid operand", Summary: "Invalid operand",
Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err), Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err),
Subject: e.RHS.Range().Ptr(), Subject: e.RHS.Range().Ptr(),
@ -176,9 +176,9 @@ func (e *BinaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
args := []cty.Value{lhsVal, rhsVal} args := []cty.Value{lhsVal, rhsVal}
result, err := impl.Call(args) result, err := impl.Call(args)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
// FIXME: This diagnostic is useless. // FIXME: This diagnostic is useless.
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Operation failed", Summary: "Operation failed",
Detail: fmt.Sprintf("Error during operation: %s.", err), Detail: fmt.Sprintf("Error during operation: %s.", err),
Subject: &e.SrcRange, Subject: &e.SrcRange,
@ -189,11 +189,11 @@ func (e *BinaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
return result, diags return result, diags
} }
func (e *BinaryOpExpr) Range() zcl.Range { func (e *BinaryOpExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *BinaryOpExpr) StartRange() zcl.Range { func (e *BinaryOpExpr) StartRange() hcl.Range {
return e.LHS.StartRange() return e.LHS.StartRange()
} }
@ -201,15 +201,15 @@ type UnaryOpExpr struct {
Op *Operation Op *Operation
Val Expression Val Expression
SrcRange zcl.Range SrcRange hcl.Range
SymbolRange zcl.Range SymbolRange hcl.Range
} }
func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) { func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {
e.Val = w(e.Val).(Expression) e.Val = w(e.Val).(Expression)
} }
func (e *UnaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
impl := e.Op.Impl // assumed to be a function taking exactly one argument impl := e.Op.Impl // assumed to be a function taking exactly one argument
params := impl.Params() params := impl.Params()
param := params[0] param := params[0]
@ -218,8 +218,8 @@ func (e *UnaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
val, err := convert.Convert(givenVal, param.Type) val, err := convert.Convert(givenVal, param.Type)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid operand", Summary: "Invalid operand",
Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err), Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err),
Subject: e.Val.Range().Ptr(), Subject: e.Val.Range().Ptr(),
@ -236,9 +236,9 @@ func (e *UnaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
args := []cty.Value{val} args := []cty.Value{val}
result, err := impl.Call(args) result, err := impl.Call(args)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
// FIXME: This diagnostic is useless. // FIXME: This diagnostic is useless.
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Operation failed", Summary: "Operation failed",
Detail: fmt.Sprintf("Error during operation: %s.", err), Detail: fmt.Sprintf("Error during operation: %s.", err),
Subject: &e.SrcRange, Subject: &e.SrcRange,
@ -249,10 +249,10 @@ func (e *UnaryOpExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
return result, diags return result, diags
} }
func (e *UnaryOpExpr) Range() zcl.Range { func (e *UnaryOpExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *UnaryOpExpr) StartRange() zcl.Range { func (e *UnaryOpExpr) StartRange() hcl.Range {
return e.SymbolRange return e.SymbolRange
} }

View File

@ -1,10 +1,10 @@
package zclsyntax package hclsyntax
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
) )
@ -12,7 +12,7 @@ import (
type TemplateExpr struct { type TemplateExpr struct {
Parts []Expression Parts []Expression
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) { func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {
@ -21,9 +21,9 @@ func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {
} }
} }
func (e *TemplateExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
var diags zcl.Diagnostics var diags hcl.Diagnostics
isKnown := true isKnown := true
for _, part := range e.Parts { for _, part := range e.Parts {
@ -31,8 +31,8 @@ func (e *TemplateExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
diags = append(diags, partDiags...) diags = append(diags, partDiags...)
if partVal.IsNull() { if partVal.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template interpolation value", Summary: "Invalid template interpolation value",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"The expression result is null. Cannot include a null value in a string template.", "The expression result is null. Cannot include a null value in a string template.",
@ -54,8 +54,8 @@ func (e *TemplateExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
strVal, err := convert.Convert(partVal, cty.String) strVal, err := convert.Convert(partVal, cty.String)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template interpolation value", Summary: "Invalid template interpolation value",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Cannot include the given value in a string template: %s.", "Cannot include the given value in a string template: %s.",
@ -77,11 +77,11 @@ func (e *TemplateExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics)
return cty.StringVal(buf.String()), diags return cty.StringVal(buf.String()), diags
} }
func (e *TemplateExpr) Range() zcl.Range { func (e *TemplateExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *TemplateExpr) StartRange() zcl.Range { func (e *TemplateExpr) StartRange() hcl.Range {
return e.Parts[0].StartRange() return e.Parts[0].StartRange()
} }
@ -97,7 +97,7 @@ func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {
e.Tuple = w(e.Tuple).(Expression) e.Tuple = w(e.Tuple).(Expression)
} }
func (e *TemplateJoinExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
tuple, diags := e.Tuple.Value(ctx) tuple, diags := e.Tuple.Value(ctx)
if tuple.IsNull() { if tuple.IsNull() {
@ -121,8 +121,8 @@ func (e *TemplateJoinExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
_, val := it.Element() _, val := it.Element()
if val.IsNull() { if val.IsNull() {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template interpolation value", Summary: "Invalid template interpolation value",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"An iteration result is null. Cannot include a null value in a string template.", "An iteration result is null. Cannot include a null value in a string template.",
@ -136,8 +136,8 @@ func (e *TemplateJoinExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
} }
strVal, err := convert.Convert(val, cty.String) strVal, err := convert.Convert(val, cty.String)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template interpolation value", Summary: "Invalid template interpolation value",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Cannot include one of the interpolation results into the string template: %s.", "Cannot include one of the interpolation results into the string template: %s.",
@ -157,11 +157,11 @@ func (e *TemplateJoinExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnosti
return cty.StringVal(buf.String()), diags return cty.StringVal(buf.String()), diags
} }
func (e *TemplateJoinExpr) Range() zcl.Range { func (e *TemplateJoinExpr) Range() hcl.Range {
return e.Tuple.Range() return e.Tuple.Range()
} }
func (e *TemplateJoinExpr) StartRange() zcl.Range { func (e *TemplateJoinExpr) StartRange() hcl.Range {
return e.Tuple.StartRange() return e.Tuple.StartRange()
} }
@ -172,21 +172,21 @@ func (e *TemplateJoinExpr) StartRange() zcl.Range {
type TemplateWrapExpr struct { type TemplateWrapExpr struct {
Wrapped Expression Wrapped Expression
SrcRange zcl.Range SrcRange hcl.Range
} }
func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) { func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {
e.Wrapped = w(e.Wrapped).(Expression) e.Wrapped = w(e.Wrapped).(Expression)
} }
func (e *TemplateWrapExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return e.Wrapped.Value(ctx) return e.Wrapped.Value(ctx)
} }
func (e *TemplateWrapExpr) Range() zcl.Range { func (e *TemplateWrapExpr) Range() hcl.Range {
return e.SrcRange return e.SrcRange
} }
func (e *TemplateWrapExpr) StartRange() zcl.Range { func (e *TemplateWrapExpr) StartRange() hcl.Range {
return e.SrcRange return e.SrcRange
} }

View File

@ -1,9 +1,9 @@
package zclsyntax package hclsyntax
import ( import (
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -12,7 +12,7 @@ func TestTemplateExprParseAndValue(t *testing.T) {
// method, with the focus on the latter but indirectly testing the former. // method, with the focus on the latter but indirectly testing the former.
tests := []struct { tests := []struct {
input string input string
ctx *zcl.EvalContext ctx *hcl.EvalContext
want cty.Value want cty.Value
diagCount int diagCount int
}{ }{
@ -209,7 +209,7 @@ trim`,
}, },
{ {
`%{ for v in ["a", "b", "c"] }${v}${nl}%{ endfor }`, `%{ for v in ["a", "b", "c"] }${v}${nl}%{ endfor }`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"nl": cty.StringVal("\n"), "nl": cty.StringVal("\n"),
}, },
@ -221,7 +221,7 @@ trim`,
for _, test := range tests { for _, test := range tests {
t.Run(test.input, func(t *testing.T) { t.Run(test.input, func(t *testing.T) {
expr, parseDiags := ParseTemplate([]byte(test.input), "", zcl.Pos{Line: 1, Column: 1, Byte: 0}) expr, parseDiags := ParseTemplate([]byte(test.input), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
got, valDiags := expr.Value(test.ctx) got, valDiags := expr.Value(test.ctx)

View File

@ -1,9 +1,9 @@
package zclsyntax package hclsyntax
import ( import (
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
"github.com/zclconf/go-cty/cty/function/stdlib" "github.com/zclconf/go-cty/cty/function/stdlib"
@ -14,7 +14,7 @@ func TestExpressionParseAndValue(t *testing.T) {
// method, with the focus on the latter but indirectly testing the former. // method, with the focus on the latter but indirectly testing the former.
tests := []struct { tests := []struct {
input string input string
ctx *zcl.EvalContext ctx *hcl.EvalContext
want cty.Value want cty.Value
diagCount int diagCount int
}{ }{
@ -38,7 +38,7 @@ func TestExpressionParseAndValue(t *testing.T) {
}, },
{ {
`(2+unk)`, `(2+unk)`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.UnknownVal(cty.Number), "unk": cty.UnknownVal(cty.Number),
}, },
@ -48,7 +48,7 @@ func TestExpressionParseAndValue(t *testing.T) {
}, },
{ {
`(2+unk)`, `(2+unk)`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.DynamicVal, "unk": cty.DynamicVal,
}, },
@ -58,7 +58,7 @@ func TestExpressionParseAndValue(t *testing.T) {
}, },
{ {
`(unk+unk)`, `(unk+unk)`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.DynamicVal, "unk": cty.DynamicVal,
}, },
@ -220,7 +220,7 @@ func TestExpressionParseAndValue(t *testing.T) {
}, },
{ {
`upper("foo")`, `upper("foo")`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -234,7 +234,7 @@ upper(
"foo" "foo"
) )
`, `,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -244,7 +244,7 @@ upper(
}, },
{ {
`upper(["foo"]...)`, `upper(["foo"]...)`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -254,7 +254,7 @@ upper(
}, },
{ {
`upper("foo", []...)`, `upper("foo", []...)`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -264,7 +264,7 @@ upper(
}, },
{ {
`upper("foo", "bar")`, `upper("foo", "bar")`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -274,7 +274,7 @@ upper(
}, },
{ {
`upper(["foo", "bar"]...)`, `upper(["foo", "bar"]...)`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -419,7 +419,7 @@ upper(
}, },
{ {
`{for k, v in {hello: "world"}: upper(k) => upper(v) if k == "hello"}`, `{for k, v in {hello: "world"}: upper(k) => upper(v) if k == "hello"}`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"upper": stdlib.UpperFunc, "upper": stdlib.UpperFunc,
}, },
@ -475,7 +475,7 @@ upper(
}, },
{ {
`{for k, v in {hello: "world"}: k => foo}`, `{for k, v in {hello: "world"}: k => foo}`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.StringVal("foo"), "foo": cty.StringVal("foo"),
}, },
@ -578,7 +578,7 @@ upper(
}, },
{ {
`[for v in unk: v]`, `[for v in unk: v]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.UnknownVal(cty.List(cty.String)), "unk": cty.UnknownVal(cty.List(cty.String)),
}, },
@ -588,7 +588,7 @@ upper(
}, },
{ {
`[for v in unk: v]`, `[for v in unk: v]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.DynamicVal, "unk": cty.DynamicVal,
}, },
@ -598,7 +598,7 @@ upper(
}, },
{ {
`[for v in unk: v]`, `[for v in unk: v]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.UnknownVal(cty.String), "unk": cty.UnknownVal(cty.String),
}, },
@ -608,7 +608,7 @@ upper(
}, },
{ {
`[for v in ["a", "b"]: v if unkbool]`, `[for v in ["a", "b"]: v if unkbool]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unkbool": cty.UnknownVal(cty.Bool), "unkbool": cty.UnknownVal(cty.Bool),
}, },
@ -618,7 +618,7 @@ upper(
}, },
{ {
`[for v in ["a", "b"]: v if nullbool]`, `[for v in ["a", "b"]: v if nullbool]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"nullbool": cty.NullVal(cty.Bool), "nullbool": cty.NullVal(cty.Bool),
}, },
@ -628,7 +628,7 @@ upper(
}, },
{ {
`[for v in ["a", "b"]: v if dyn]`, `[for v in ["a", "b"]: v if dyn]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"dyn": cty.DynamicVal, "dyn": cty.DynamicVal,
}, },
@ -638,7 +638,7 @@ upper(
}, },
{ {
`[for v in ["a", "b"]: v if unknum]`, `[for v in ["a", "b"]: v if unknum]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unknum": cty.UnknownVal(cty.List(cty.Number)), "unknum": cty.UnknownVal(cty.List(cty.Number)),
}, },
@ -654,7 +654,7 @@ upper(
}, },
{ {
`[for v in ["a", "b"]: unkstr]`, `[for v in ["a", "b"]: unkstr]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unkstr": cty.UnknownVal(cty.String), "unkstr": cty.UnknownVal(cty.String),
}, },
@ -751,7 +751,7 @@ upper(
}, },
{ {
`["hello"][negate(0)]`, `["hello"][negate(0)]`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"negate": stdlib.NegateFunc, "negate": stdlib.NegateFunc,
}, },
@ -761,7 +761,7 @@ upper(
}, },
{ {
`[][negate(0)]`, `[][negate(0)]`,
&zcl.EvalContext{ &hcl.EvalContext{
Functions: map[string]function.Function{ Functions: map[string]function.Function{
"negate": stdlib.NegateFunc, "negate": stdlib.NegateFunc,
}, },
@ -778,7 +778,7 @@ upper(
{ {
`foo`, `foo`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.StringVal("hello"), "foo": cty.StringVal("hello"),
}, },
@ -788,13 +788,13 @@ upper(
}, },
{ {
`bar`, `bar`,
&zcl.EvalContext{}, &hcl.EvalContext{},
cty.DynamicVal, cty.DynamicVal,
1, // variables not allowed here 1, // variables not allowed here
}, },
{ {
`foo.bar`, `foo.bar`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.StringVal("hello"), "foo": cty.StringVal("hello"),
}, },
@ -804,7 +804,7 @@ upper(
}, },
{ {
`foo.baz`, `foo.baz`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.ObjectVal(map[string]cty.Value{ "foo": cty.ObjectVal(map[string]cty.Value{
"baz": cty.StringVal("hello"), "baz": cty.StringVal("hello"),
@ -816,7 +816,7 @@ upper(
}, },
{ {
`foo["baz"]`, `foo["baz"]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.ObjectVal(map[string]cty.Value{ "foo": cty.ObjectVal(map[string]cty.Value{
"baz": cty.StringVal("hello"), "baz": cty.StringVal("hello"),
@ -828,7 +828,7 @@ upper(
}, },
{ {
`foo[true]`, // key is converted to string `foo[true]`, // key is converted to string
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.ObjectVal(map[string]cty.Value{ "foo": cty.ObjectVal(map[string]cty.Value{
"true": cty.StringVal("hello"), "true": cty.StringVal("hello"),
@ -840,7 +840,7 @@ upper(
}, },
{ {
`foo[0].baz`, `foo[0].baz`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"foo": cty.ListVal([]cty.Value{ "foo": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{ cty.ObjectVal(map[string]cty.Value{
@ -854,7 +854,7 @@ upper(
}, },
{ {
`unk["baz"]`, `unk["baz"]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.UnknownVal(cty.String), "unk": cty.UnknownVal(cty.String),
}, },
@ -864,7 +864,7 @@ upper(
}, },
{ {
`unk["boop"]`, `unk["boop"]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"unk": cty.UnknownVal(cty.Map(cty.String)), "unk": cty.UnknownVal(cty.Map(cty.String)),
}, },
@ -874,7 +874,7 @@ upper(
}, },
{ {
`dyn["boop"]`, `dyn["boop"]`,
&zcl.EvalContext{ &hcl.EvalContext{
Variables: map[string]cty.Value{ Variables: map[string]cty.Value{
"dyn": cty.DynamicVal, "dyn": cty.DynamicVal,
}, },
@ -886,7 +886,7 @@ upper(
for _, test := range tests { for _, test := range tests {
t.Run(test.input, func(t *testing.T) { t.Run(test.input, func(t *testing.T) {
expr, parseDiags := ParseExpression([]byte(test.input), "", zcl.Pos{Line: 1, Column: 1, Byte: 0}) expr, parseDiags := ParseExpression([]byte(test.input), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
got, valDiags := expr.Value(test.ctx) got, valDiags := expr.Value(test.ctx)
@ -918,7 +918,7 @@ func TestFunctionCallExprValue(t *testing.T) {
tests := map[string]struct { tests := map[string]struct {
expr *FunctionCallExpr expr *FunctionCallExpr
ctx *zcl.EvalContext ctx *hcl.EvalContext
want cty.Value want cty.Value
diagCount int diagCount int
}{ }{
@ -931,7 +931,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.NumberIntVal(5), cty.NumberIntVal(5),
@ -946,7 +946,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.NumberIntVal(4), // length of string "true" cty.NumberIntVal(4), // length of string "true"
@ -961,7 +961,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.UnknownVal(cty.Number), cty.UnknownVal(cty.Number),
@ -976,7 +976,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.UnknownVal(cty.Number), cty.UnknownVal(cty.Number),
@ -991,7 +991,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.UnknownVal(cty.Number), cty.UnknownVal(cty.Number),
@ -1006,7 +1006,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.DynamicVal, cty.DynamicVal,
@ -1021,7 +1021,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.StringVal("hello"), cty.StringVal("hello"),
@ -1036,7 +1036,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.DynamicVal, // type depends on arg value cty.DynamicVal, // type depends on arg value
@ -1051,7 +1051,7 @@ func TestFunctionCallExprValue(t *testing.T) {
}, },
}, },
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.DynamicVal, cty.DynamicVal,
@ -1062,7 +1062,7 @@ func TestFunctionCallExprValue(t *testing.T) {
Name: "lenth", Name: "lenth",
Args: []Expression{}, Args: []Expression{},
}, },
&zcl.EvalContext{ &hcl.EvalContext{
Functions: funcs, Functions: funcs,
}, },
cty.DynamicVal, cty.DynamicVal,

View File

@ -0,0 +1,72 @@
package hclsyntax
// Generated by expression_vars_get.go. DO NOT EDIT.
// Run 'go generate' on this package to update the set of functions here.
import (
"github.com/hashicorp/hcl2/hcl"
)
func (e *AnonSymbolExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *BinaryOpExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *ConditionalExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *ForExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *FunctionCallExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *IndexExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *LiteralValueExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *ObjectConsExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *RelativeTraversalExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *ScopeTraversalExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *SplatExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *TemplateExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *TemplateJoinExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *TemplateWrapExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *TupleConsExpr) Variables() []hcl.Traversal {
return Variables(e)
}
func (e *UnaryOpExpr) Variables() []hcl.Traversal {
return Variables(e)
}

View File

@ -94,6 +94,6 @@ import (
const outputMethodFmt = ` const outputMethodFmt = `
func (e %s) Variables() []zcl.Traversal { func (e %s) Variables() []hcl.Traversal {
return Variables(e) return Variables(e)
}` }`

View File

@ -1,6 +1,8 @@
package zclsyntax package hclsyntax
import "github.com/hashicorp/hcl2/zcl" import (
"github.com/hashicorp/hcl2/hcl"
)
// File is the top-level object resulting from parsing a configuration file. // File is the top-level object resulting from parsing a configuration file.
type File struct { type File struct {
@ -8,8 +10,8 @@ type File struct {
Bytes []byte Bytes []byte
} }
func (f *File) AsZCLFile() *zcl.File { func (f *File) AsZCLFile() *hcl.File {
return &zcl.File{ return &hcl.File{
Body: f.Body, Body: f.Body,
Bytes: f.Bytes, Bytes: f.Bytes,

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
//go:generate go run expression_vars_gen.go //go:generate go run expression_vars_gen.go
//go:generate ruby unicode2ragel.rb --url=http://www.unicode.org/Public/9.0.0/ucd/DerivedCoreProperties.txt -m UnicodeDerived -p ID_Start,ID_Continue -o unicode_derived.rl //go:generate ruby unicode2ragel.rb --url=http://www.unicode.org/Public/9.0.0/ucd/DerivedCoreProperties.txt -m UnicodeDerived -p ID_Start,ID_Continue -o unicode_derived.rl

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import ( import (
"bytes" "bytes"

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import ( import (
"bytes" "bytes"

View File

@ -1,7 +1,7 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Node is the abstract type that every AST node implements. // Node is the abstract type that every AST node implements.
@ -16,7 +16,7 @@ type Node interface {
// walks. // walks.
walkChildNodes(w internalWalkFunc) walkChildNodes(w internalWalkFunc)
Range() zcl.Range Range() hcl.Range
} }
type internalWalkFunc func(Node) Node type internalWalkFunc func(Node) Node

View File

@ -0,0 +1,227 @@
package hclsyntax
import (
"testing"
"reflect"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
func TestParseTraversalAbs(t *testing.T) {
tests := []struct {
src string
want hcl.Traversal
diagCount int
}{
{
"",
nil,
1, // variable name required
},
{
"foo",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
0,
},
{
"foo.bar.baz",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
hcl.TraverseAttr{
Name: "bar",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
},
hcl.TraverseAttr{
Name: "baz",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
},
0,
},
{
"foo[1]",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
hcl.TraverseIndex{
Key: cty.NumberIntVal(1),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
},
},
0,
},
{
"foo[1][2]",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
hcl.TraverseIndex{
Key: cty.NumberIntVal(1),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
},
hcl.TraverseIndex{
Key: cty.NumberIntVal(2),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 10, Byte: 9},
},
},
},
0,
},
{
"foo[1].bar",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
hcl.TraverseIndex{
Key: cty.NumberIntVal(1),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
},
hcl.TraverseAttr{
Name: "bar",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 11, Byte: 10},
},
},
},
0,
},
{
"foo.",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
1, // attribute name required
},
{
"foo[",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
1, // index required
},
{
"foo[index]",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
1, // index must be literal
},
{
"foo[0",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
hcl.TraverseIndex{
Key: cty.NumberIntVal(0),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
},
1, // missing close bracket
},
{
"foo 0",
hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
1, // extra junk after traversal
},
}
for _, test := range tests {
t.Run(test.src, func(t *testing.T) {
got, diags := ParseTraversalAbs([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
if len(diags) != test.diagCount {
for _, diag := range diags {
t.Logf(" - %s", diag.Error())
}
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.diagCount)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("wrong result\nsrc: %s\ngot: %s\nwant: %s", test.src, spew.Sdump(got), spew.Sdump(test.want))
}
})
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"strings" "strings"
"unicode" "unicode"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
func (p *parser) ParseTemplate() (Expression, zcl.Diagnostics) { func (p *parser) ParseTemplate() (Expression, hcl.Diagnostics) {
return p.parseTemplate(TokenEOF) return p.parseTemplate(TokenEOF)
} }
func (p *parser) parseTemplate(end TokenType) (Expression, zcl.Diagnostics) { func (p *parser) parseTemplate(end TokenType) (Expression, hcl.Diagnostics) {
exprs, passthru, rng, diags := p.parseTemplateInner(end) exprs, passthru, rng, diags := p.parseTemplateInner(end)
if passthru { if passthru {
@ -32,7 +32,7 @@ func (p *parser) parseTemplate(end TokenType) (Expression, zcl.Diagnostics) {
}, diags }, diags
} }
func (p *parser) parseTemplateInner(end TokenType) ([]Expression, bool, zcl.Range, zcl.Diagnostics) { func (p *parser) parseTemplateInner(end TokenType) ([]Expression, bool, hcl.Range, hcl.Diagnostics) {
parts, diags := p.parseTemplateParts(end) parts, diags := p.parseTemplateParts(end)
tp := templateParser{ tp := templateParser{
Tokens: parts.Tokens, Tokens: parts.Tokens,
@ -53,14 +53,14 @@ func (p *parser) parseTemplateInner(end TokenType) ([]Expression, bool, zcl.Rang
type templateParser struct { type templateParser struct {
Tokens []templateToken Tokens []templateToken
SrcRange zcl.Range SrcRange hcl.Range
pos int pos int
} }
func (p *templateParser) parseRoot() ([]Expression, zcl.Diagnostics) { func (p *templateParser) parseRoot() ([]Expression, hcl.Diagnostics) {
var exprs []Expression var exprs []Expression
var diags zcl.Diagnostics var diags hcl.Diagnostics
for { for {
next := p.Peek() next := p.Peek()
@ -76,7 +76,7 @@ func (p *templateParser) parseRoot() ([]Expression, zcl.Diagnostics) {
return exprs, diags return exprs, diags
} }
func (p *templateParser) parseExpr() (Expression, zcl.Diagnostics) { func (p *templateParser) parseExpr() (Expression, hcl.Diagnostics) {
next := p.Peek() next := p.Peek()
switch tok := next.(type) { switch tok := next.(type) {
@ -99,12 +99,12 @@ func (p *templateParser) parseExpr() (Expression, zcl.Diagnostics) {
case *templateEndToken: case *templateEndToken:
p.Read() // eat erroneous token p.Read() // eat erroneous token
return errPlaceholderExpr(tok.SrcRange), zcl.Diagnostics{ return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{
{ {
// This is a particularly unhelpful diagnostic, so callers // This is a particularly unhelpful diagnostic, so callers
// should attempt to pre-empt it and produce a more helpful // should attempt to pre-empt it and produce a more helpful
// diagnostic that is context-aware. // diagnostic that is context-aware.
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unexpected end of template", Summary: "Unexpected end of template",
Detail: "The control directives within this template are unbalanced.", Detail: "The control directives within this template are unbalanced.",
Subject: &tok.SrcRange, Subject: &tok.SrcRange,
@ -113,9 +113,9 @@ func (p *templateParser) parseExpr() (Expression, zcl.Diagnostics) {
case *templateEndCtrlToken: case *templateEndCtrlToken:
p.Read() // eat erroneous token p.Read() // eat erroneous token
return errPlaceholderExpr(tok.SrcRange), zcl.Diagnostics{ return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unexpected %s directive", tok.Name()), Summary: fmt.Sprintf("Unexpected %s directive", tok.Name()),
Detail: "The control directives within this template are unbalanced.", Detail: "The control directives within this template are unbalanced.",
Subject: &tok.SrcRange, Subject: &tok.SrcRange,
@ -128,7 +128,7 @@ func (p *templateParser) parseExpr() (Expression, zcl.Diagnostics) {
} }
} }
func (p *templateParser) parseIf() (Expression, zcl.Diagnostics) { func (p *templateParser) parseIf() (Expression, hcl.Diagnostics) {
open := p.Read() open := p.Read()
openIf, isIf := open.(*templateIfToken) openIf, isIf := open.(*templateIfToken)
if !isIf { if !isIf {
@ -137,16 +137,16 @@ func (p *templateParser) parseIf() (Expression, zcl.Diagnostics) {
} }
var ifExprs, elseExprs []Expression var ifExprs, elseExprs []Expression
var diags zcl.Diagnostics var diags hcl.Diagnostics
var endifRange zcl.Range var endifRange hcl.Range
currentExprs := &ifExprs currentExprs := &ifExprs
Token: Token:
for { for {
next := p.Peek() next := p.Peek()
if end, isEnd := next.(*templateEndToken); isEnd { if end, isEnd := next.(*templateEndToken); isEnd {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unexpected end of template", Summary: "Unexpected end of template",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"The if directive at %s is missing its corresponding endif directive.", "The if directive at %s is missing its corresponding endif directive.",
@ -167,8 +167,8 @@ Token:
continue Token continue Token
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unexpected else directive", Summary: "Unexpected else directive",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Already in the else clause for the if started at %s.", "Already in the else clause for the if started at %s.",
@ -182,8 +182,8 @@ Token:
break Token break Token
default: default:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unexpected %s directive", end.Name()), Summary: fmt.Sprintf("Unexpected %s directive", end.Name()),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Expecting an endif directive for the if started at %s.", "Expecting an endif directive for the if started at %s.",
@ -204,7 +204,7 @@ Token:
if len(ifExprs) == 0 { if len(ifExprs) == 0 {
ifExprs = append(ifExprs, &LiteralValueExpr{ ifExprs = append(ifExprs, &LiteralValueExpr{
Val: cty.StringVal(""), Val: cty.StringVal(""),
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: openIf.SrcRange.Filename, Filename: openIf.SrcRange.Filename,
Start: openIf.SrcRange.End, Start: openIf.SrcRange.End,
End: openIf.SrcRange.End, End: openIf.SrcRange.End,
@ -214,7 +214,7 @@ Token:
if len(elseExprs) == 0 { if len(elseExprs) == 0 {
elseExprs = append(elseExprs, &LiteralValueExpr{ elseExprs = append(elseExprs, &LiteralValueExpr{
Val: cty.StringVal(""), Val: cty.StringVal(""),
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: endifRange.Filename, Filename: endifRange.Filename,
Start: endifRange.Start, Start: endifRange.Start,
End: endifRange.Start, End: endifRange.Start,
@ -224,11 +224,11 @@ Token:
trueExpr := &TemplateExpr{ trueExpr := &TemplateExpr{
Parts: ifExprs, Parts: ifExprs,
SrcRange: zcl.RangeBetween(ifExprs[0].Range(), ifExprs[len(ifExprs)-1].Range()), SrcRange: hcl.RangeBetween(ifExprs[0].Range(), ifExprs[len(ifExprs)-1].Range()),
} }
falseExpr := &TemplateExpr{ falseExpr := &TemplateExpr{
Parts: elseExprs, Parts: elseExprs,
SrcRange: zcl.RangeBetween(elseExprs[0].Range(), elseExprs[len(elseExprs)-1].Range()), SrcRange: hcl.RangeBetween(elseExprs[0].Range(), elseExprs[len(elseExprs)-1].Range()),
} }
return &ConditionalExpr{ return &ConditionalExpr{
@ -236,11 +236,11 @@ Token:
TrueResult: trueExpr, TrueResult: trueExpr,
FalseResult: falseExpr, FalseResult: falseExpr,
SrcRange: zcl.RangeBetween(openIf.SrcRange, endifRange), SrcRange: hcl.RangeBetween(openIf.SrcRange, endifRange),
}, diags }, diags
} }
func (p *templateParser) parseFor() (Expression, zcl.Diagnostics) { func (p *templateParser) parseFor() (Expression, hcl.Diagnostics) {
open := p.Read() open := p.Read()
openFor, isFor := open.(*templateForToken) openFor, isFor := open.(*templateForToken)
if !isFor { if !isFor {
@ -249,15 +249,15 @@ func (p *templateParser) parseFor() (Expression, zcl.Diagnostics) {
} }
var contentExprs []Expression var contentExprs []Expression
var diags zcl.Diagnostics var diags hcl.Diagnostics
var endforRange zcl.Range var endforRange hcl.Range
Token: Token:
for { for {
next := p.Peek() next := p.Peek()
if end, isEnd := next.(*templateEndToken); isEnd { if end, isEnd := next.(*templateEndToken); isEnd {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unexpected end of template", Summary: "Unexpected end of template",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"The for directive at %s is missing its corresponding endfor directive.", "The for directive at %s is missing its corresponding endfor directive.",
@ -273,8 +273,8 @@ Token:
switch end.Type { switch end.Type {
case templateElse: case templateElse:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unexpected else directive", Summary: "Unexpected else directive",
Detail: "An else clause is not expected for a for directive.", Detail: "An else clause is not expected for a for directive.",
Subject: &end.SrcRange, Subject: &end.SrcRange,
@ -285,8 +285,8 @@ Token:
break Token break Token
default: default:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unexpected %s directive", end.Name()), Summary: fmt.Sprintf("Unexpected %s directive", end.Name()),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Expecting an endfor directive corresponding to the for directive at %s.", "Expecting an endfor directive corresponding to the for directive at %s.",
@ -307,7 +307,7 @@ Token:
if len(contentExprs) == 0 { if len(contentExprs) == 0 {
contentExprs = append(contentExprs, &LiteralValueExpr{ contentExprs = append(contentExprs, &LiteralValueExpr{
Val: cty.StringVal(""), Val: cty.StringVal(""),
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: openFor.SrcRange.Filename, Filename: openFor.SrcRange.Filename,
Start: openFor.SrcRange.End, Start: openFor.SrcRange.End,
End: openFor.SrcRange.End, End: openFor.SrcRange.End,
@ -317,7 +317,7 @@ Token:
contentExpr := &TemplateExpr{ contentExpr := &TemplateExpr{
Parts: contentExprs, Parts: contentExprs,
SrcRange: zcl.RangeBetween(contentExprs[0].Range(), contentExprs[len(contentExprs)-1].Range()), SrcRange: hcl.RangeBetween(contentExprs[0].Range(), contentExprs[len(contentExprs)-1].Range()),
} }
forExpr := &ForExpr{ forExpr := &ForExpr{
@ -327,7 +327,7 @@ Token:
CollExpr: openFor.CollExpr, CollExpr: openFor.CollExpr,
ValExpr: contentExpr, ValExpr: contentExpr,
SrcRange: zcl.RangeBetween(openFor.SrcRange, endforRange), SrcRange: hcl.RangeBetween(openFor.SrcRange, endforRange),
OpenRange: openFor.SrcRange, OpenRange: openFor.SrcRange,
CloseRange: endforRange, CloseRange: endforRange,
} }
@ -354,14 +354,14 @@ func (p *templateParser) Read() templateToken {
// sequences, or control flow markers. // sequences, or control flow markers.
// //
// A further pass is required on the result to turn it into an AST. // A further pass is required on the result to turn it into an AST.
func (p *parser) parseTemplateParts(end TokenType) (*templateParts, zcl.Diagnostics) { func (p *parser) parseTemplateParts(end TokenType) (*templateParts, hcl.Diagnostics) {
var parts []templateToken var parts []templateToken
var diags zcl.Diagnostics var diags hcl.Diagnostics
startRange := p.NextRange() startRange := p.NextRange()
ltrimNext := false ltrimNext := false
nextCanTrimPrev := false nextCanTrimPrev := false
var endRange zcl.Range var endRange hcl.Range
Token: Token:
for { for {
@ -409,12 +409,12 @@ Token:
close := p.Peek() close := p.Peek()
if close.Type != TokenTemplateSeqEnd { if close.Type != TokenTemplateSeqEnd {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extra characters after interpolation expression", Summary: "Extra characters after interpolation expression",
Detail: "Expected a closing brace to end the interpolation expression, but found extra characters.", Detail: "Expected a closing brace to end the interpolation expression, but found extra characters.",
Subject: &close.Range, Subject: &close.Range,
Context: zcl.RangeBetween(startRange, close.Range).Ptr(), Context: hcl.RangeBetween(startRange, close.Range).Ptr(),
}) })
} }
p.recover(TokenTemplateSeqEnd) p.recover(TokenTemplateSeqEnd)
@ -431,7 +431,7 @@ Token:
p.PopIncludeNewlines() p.PopIncludeNewlines()
parts = append(parts, &templateInterpToken{ parts = append(parts, &templateInterpToken{
Expr: expr, Expr: expr,
SrcRange: zcl.RangeBetween(next.Range, close.Range), SrcRange: hcl.RangeBetween(next.Range, close.Range),
}) })
case TokenTemplateControl: case TokenTemplateControl:
@ -449,12 +449,12 @@ Token:
kw := p.Peek() kw := p.Peek()
if kw.Type != TokenIdent { if kw.Type != TokenIdent {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template directive", Summary: "Invalid template directive",
Detail: "A template directive keyword (\"if\", \"for\", etc) is expected at the beginning of a !{ sequence.", Detail: "A template directive keyword (\"if\", \"for\", etc) is expected at the beginning of a !{ sequence.",
Subject: &kw.Range, Subject: &kw.Range,
Context: zcl.RangeBetween(next.Range, kw.Range).Ptr(), Context: hcl.RangeBetween(next.Range, kw.Range).Ptr(),
}) })
} }
p.recover(TokenTemplateSeqEnd) p.recover(TokenTemplateSeqEnd)
@ -470,27 +470,27 @@ Token:
diags = append(diags, exprDiags...) diags = append(diags, exprDiags...)
parts = append(parts, &templateIfToken{ parts = append(parts, &templateIfToken{
CondExpr: condExpr, CondExpr: condExpr,
SrcRange: zcl.RangeBetween(next.Range, p.NextRange()), SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
}) })
case elseKeyword.TokenMatches(kw): case elseKeyword.TokenMatches(kw):
parts = append(parts, &templateEndCtrlToken{ parts = append(parts, &templateEndCtrlToken{
Type: templateElse, Type: templateElse,
SrcRange: zcl.RangeBetween(next.Range, p.NextRange()), SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
}) })
case endifKeyword.TokenMatches(kw): case endifKeyword.TokenMatches(kw):
parts = append(parts, &templateEndCtrlToken{ parts = append(parts, &templateEndCtrlToken{
Type: templateEndIf, Type: templateEndIf,
SrcRange: zcl.RangeBetween(next.Range, p.NextRange()), SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
}) })
case forKeyword.TokenMatches(kw): case forKeyword.TokenMatches(kw):
var keyName, valName string var keyName, valName string
if p.Peek().Type != TokenIdent { if p.Peek().Type != TokenIdent {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' directive", Summary: "Invalid 'for' directive",
Detail: "For directive requires variable name after 'for'.", Detail: "For directive requires variable name after 'for'.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -510,8 +510,8 @@ Token:
if p.Peek().Type != TokenIdent { if p.Peek().Type != TokenIdent {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' directive", Summary: "Invalid 'for' directive",
Detail: "For directive requires value variable name after comma.", Detail: "For directive requires value variable name after comma.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -527,8 +527,8 @@ Token:
if !inKeyword.TokenMatches(p.Peek()) { if !inKeyword.TokenMatches(p.Peek()) {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid 'for' directive", Summary: "Invalid 'for' directive",
Detail: "For directive requires 'in' keyword after names.", Detail: "For directive requires 'in' keyword after names.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -547,13 +547,13 @@ Token:
ValVar: valName, ValVar: valName,
CollExpr: collExpr, CollExpr: collExpr,
SrcRange: zcl.RangeBetween(next.Range, p.NextRange()), SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
}) })
case endforKeyword.TokenMatches(kw): case endforKeyword.TokenMatches(kw):
parts = append(parts, &templateEndCtrlToken{ parts = append(parts, &templateEndCtrlToken{
Type: templateEndFor, Type: templateEndFor,
SrcRange: zcl.RangeBetween(next.Range, p.NextRange()), SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),
}) })
default: default:
@ -565,12 +565,12 @@ Token:
suggestion = fmt.Sprintf(" Did you mean %q?", suggestion) suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid template control keyword", Summary: "Invalid template control keyword",
Detail: fmt.Sprintf("%q is not a valid template control keyword.%s", given, suggestion), Detail: fmt.Sprintf("%q is not a valid template control keyword.%s", given, suggestion),
Subject: &kw.Range, Subject: &kw.Range,
Context: zcl.RangeBetween(next.Range, kw.Range).Ptr(), Context: hcl.RangeBetween(next.Range, kw.Range).Ptr(),
}) })
} }
p.recover(TokenTemplateSeqEnd) p.recover(TokenTemplateSeqEnd)
@ -582,12 +582,12 @@ Token:
close := p.Peek() close := p.Peek()
if close.Type != TokenTemplateSeqEnd { if close.Type != TokenTemplateSeqEnd {
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Extra characters in %s marker", kw.Bytes), Summary: fmt.Sprintf("Extra characters in %s marker", kw.Bytes),
Detail: "Expected a closing brace to end the sequence, but found extra characters.", Detail: "Expected a closing brace to end the sequence, but found extra characters.",
Subject: &close.Range, Subject: &close.Range,
Context: zcl.RangeBetween(startRange, close.Range).Ptr(), Context: hcl.RangeBetween(startRange, close.Range).Ptr(),
}) })
} }
p.recover(TokenTemplateSeqEnd) p.recover(TokenTemplateSeqEnd)
@ -605,12 +605,12 @@ Token:
default: default:
if !p.recovery { if !p.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unterminated template string", Summary: "Unterminated template string",
Detail: "No closing marker was found for the string.", Detail: "No closing marker was found for the string.",
Subject: &next.Range, Subject: &next.Range,
Context: zcl.RangeBetween(startRange, next.Range).Ptr(), Context: hcl.RangeBetween(startRange, next.Range).Ptr(),
}) })
} }
final := p.recover(end) final := p.recover(end)
@ -625,7 +625,7 @@ Token:
// if they write "" in configuration. // if they write "" in configuration.
parts = append(parts, &templateLiteralToken{ parts = append(parts, &templateLiteralToken{
Val: "", Val: "",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
// Range is the zero-character span immediately after the // Range is the zero-character span immediately after the
// opening quote. // opening quote.
Filename: startRange.Filename, Filename: startRange.Filename,
@ -643,7 +643,7 @@ Token:
ret := &templateParts{ ret := &templateParts{
Tokens: parts, Tokens: parts,
SrcRange: zcl.RangeBetween(startRange, endRange), SrcRange: hcl.RangeBetween(startRange, endRange),
} }
return ret, diags return ret, diags
@ -651,7 +651,7 @@ Token:
type templateParts struct { type templateParts struct {
Tokens []templateToken Tokens []templateToken
SrcRange zcl.Range SrcRange hcl.Range
} }
// templateToken is a higher-level token that represents a single atom within // templateToken is a higher-level token that represents a single atom within
@ -664,19 +664,19 @@ type templateToken interface {
type templateLiteralToken struct { type templateLiteralToken struct {
Val string Val string
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }
type templateInterpToken struct { type templateInterpToken struct {
Expr Expression Expr Expression
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }
type templateIfToken struct { type templateIfToken struct {
CondExpr Expression CondExpr Expression
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }
@ -684,7 +684,7 @@ type templateForToken struct {
KeyVar string // empty if ignoring key KeyVar string // empty if ignoring key
ValVar string ValVar string
CollExpr Expression CollExpr Expression
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }
@ -698,7 +698,7 @@ const (
type templateEndCtrlToken struct { type templateEndCtrlToken struct {
Type templateEndCtrlType Type templateEndCtrlType
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }
@ -717,7 +717,7 @@ func (t *templateEndCtrlToken) Name() string {
} }
type templateEndToken struct { type templateEndToken struct {
SrcRange zcl.Range SrcRange hcl.Range
isTemplateToken isTemplateToken
} }

View File

@ -0,0 +1,823 @@
package hclsyntax
import (
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/hcl"
"github.com/kylelemons/godebug/pretty"
"github.com/zclconf/go-cty/cty"
)
func TestParseConfig(t *testing.T) {
tests := []struct {
input string
diagCount int
want *Body
}{
{
``,
0,
&Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 1, Byte: 0},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 1, Byte: 0},
},
},
},
{
"block {}\n",
0,
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: nil,
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 9, Byte: 8},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: nil,
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 9},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 9},
End: hcl.Pos{Line: 2, Column: 1, Byte: 9},
},
},
},
{
"block {}block {}\n",
1, // missing newline after block definition
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: nil,
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 9, Byte: 8},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: nil,
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 17},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 17},
End: hcl.Pos{Line: 2, Column: 1, Byte: 17},
},
},
},
{
"block \"foo\" {}\n",
0,
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: []string{"foo"},
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 13, Byte: 12},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 13, Byte: 12},
End: hcl.Pos{Line: 1, Column: 14, Byte: 13},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 14, Byte: 13},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 15},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
},
},
{
`
block "invalid" 1.2 {}
block "valid" {}
`,
1,
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: []string{"invalid"},
Body: nil,
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 1},
End: hcl.Pos{Line: 2, Column: 6, Byte: 6},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 2, Column: 7, Byte: 7},
End: hcl.Pos{Line: 2, Column: 16, Byte: 16},
},
},
// Since we failed parsing before we got to the
// braces, the type range is used as a placeholder
// for these.
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 1},
End: hcl.Pos{Line: 2, Column: 6, Byte: 6},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 1},
End: hcl.Pos{Line: 2, Column: 6, Byte: 6},
},
},
// Recovery behavior should allow us to still see this
// second block, even though the first was invalid.
&Block{
Type: "block",
Labels: []string{"valid"},
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 3, Column: 15, Byte: 38},
End: hcl.Pos{Line: 3, Column: 17, Byte: 40},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 3, Column: 17, Byte: 40},
End: hcl.Pos{Line: 3, Column: 17, Byte: 40},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 3, Column: 1, Byte: 24},
End: hcl.Pos{Line: 3, Column: 6, Byte: 29},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 3, Column: 7, Byte: 30},
End: hcl.Pos{Line: 3, Column: 14, Byte: 37},
},
},
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 3, Column: 15, Byte: 38},
End: hcl.Pos{Line: 3, Column: 16, Byte: 39},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 3, Column: 16, Byte: 39},
End: hcl.Pos{Line: 3, Column: 17, Byte: 40},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 4, Column: 1, Byte: 41},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 4, Column: 1, Byte: 41},
End: hcl.Pos{Line: 4, Column: 1, Byte: 41},
},
},
},
{
`block "f\o" {}
`,
1, // "\o" is not a valid escape sequence
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: []string{"fo"},
Body: nil,
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 15},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
},
},
{
`block "f\n" {}
`,
0,
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: []string{"f\n"},
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 13, Byte: 12},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 13, Byte: 12},
End: hcl.Pos{Line: 1, Column: 14, Byte: 13},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 14, Byte: 13},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 15},
End: hcl.Pos{Line: 2, Column: 1, Byte: 15},
},
},
},
{
"a = 1\n",
0,
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &LiteralValueExpr{
Val: cty.NumberIntVal(1),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 6},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 6},
End: hcl.Pos{Line: 2, Column: 1, Byte: 6},
},
},
},
{
"a = \"hello ${true}\"\n",
0,
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &TemplateExpr{
Parts: []Expression{
&LiteralValueExpr{
Val: cty.StringVal("hello "),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 6, Byte: 5},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
&LiteralValueExpr{
Val: cty.True,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 14, Byte: 13},
End: hcl.Pos{Line: 1, Column: 18, Byte: 17},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 20, Byte: 19},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 20, Byte: 19},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 20},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 20},
End: hcl.Pos{Line: 2, Column: 1, Byte: 20},
},
},
},
{
"a = foo.bar\n",
0,
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
},
hcl.TraverseAttr{
Name: "bar",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 12},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 12},
End: hcl.Pos{Line: 2, Column: 1, Byte: 12},
},
},
},
{
"a = 1 # line comment\n",
0,
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &LiteralValueExpr{
Val: cty.NumberIntVal(1),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 21},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 21},
End: hcl.Pos{Line: 2, Column: 1, Byte: 21},
},
},
},
{
"a = [for k, v in foo: v if true]\n",
0,
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &ForExpr{
KeyVar: "k",
ValVar: "v",
CollExpr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 18, Byte: 17},
End: hcl.Pos{Line: 1, Column: 21, Byte: 20},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 18, Byte: 17},
End: hcl.Pos{Line: 1, Column: 21, Byte: 20},
},
},
ValExpr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "v",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 23, Byte: 22},
End: hcl.Pos{Line: 1, Column: 24, Byte: 23},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 23, Byte: 22},
End: hcl.Pos{Line: 1, Column: 24, Byte: 23},
},
},
CondExpr: &LiteralValueExpr{
Val: cty.True,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 28, Byte: 27},
End: hcl.Pos{Line: 1, Column: 32, Byte: 31},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 33, Byte: 32},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 32, Byte: 31},
End: hcl.Pos{Line: 1, Column: 33, Byte: 32},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 33, Byte: 32},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 33},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 33},
End: hcl.Pos{Line: 2, Column: 1, Byte: 33},
},
},
},
{
"a = [for k, v in foo: k => v... if true]\n",
2, // can't use => or ... in a tuple for
&Body{
Attributes: Attributes{
"a": {
Name: "a",
Expr: &ForExpr{
KeyVar: "k",
ValVar: "v",
CollExpr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "foo",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 18, Byte: 17},
End: hcl.Pos{Line: 1, Column: 21, Byte: 20},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 18, Byte: 17},
End: hcl.Pos{Line: 1, Column: 21, Byte: 20},
},
},
KeyExpr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "k",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 23, Byte: 22},
End: hcl.Pos{Line: 1, Column: 24, Byte: 23},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 23, Byte: 22},
End: hcl.Pos{Line: 1, Column: 24, Byte: 23},
},
},
ValExpr: &ScopeTraversalExpr{
Traversal: hcl.Traversal{
hcl.TraverseRoot{
Name: "v",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 28, Byte: 27},
End: hcl.Pos{Line: 1, Column: 29, Byte: 28},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 28, Byte: 27},
End: hcl.Pos{Line: 1, Column: 29, Byte: 28},
},
},
CondExpr: &LiteralValueExpr{
Val: cty.True,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 36, Byte: 35},
End: hcl.Pos{Line: 1, Column: 40, Byte: 39},
},
},
Group: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 41, Byte: 40},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 40, Byte: 39},
End: hcl.Pos{Line: 1, Column: 41, Byte: 40},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 41, Byte: 40},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EqualsRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 3, Byte: 2},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 41},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 41},
End: hcl.Pos{Line: 2, Column: 1, Byte: 41},
},
},
},
{
` `,
2, // tabs not allowed, and body item is required here
&Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
},
{
`\x81`,
2, // invalid UTF-8, and body item is required here
&Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
},
}
prettyConfig := &pretty.Config{
Diffable: true,
IncludeUnexported: true,
PrintStringers: true,
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
file, diags := ParseConfig([]byte(test.input), "", hcl.Pos{Byte: 0, Line: 1, Column: 1})
if len(diags) != test.diagCount {
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.diagCount)
for _, diag := range diags {
t.Logf(" - %s", diag.Error())
}
}
got := file.Body
if !reflect.DeepEqual(got, test.want) {
diff := prettyConfig.Compare(test.want, got)
if diff != "" {
t.Errorf("wrong result\ninput: %s\ndiff: %s", test.input, diff)
} else {
t.Errorf("wrong result\ninput: %s\ngot: %s\nwant: %s", test.input, spew.Sdump(got), spew.Sdump(test.want))
}
}
})
}
}

View File

@ -1,7 +1,7 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -9,15 +9,15 @@ import (
// all of the remaining tokens in the peeker. The usual parser recovery // all of the remaining tokens in the peeker. The usual parser recovery
// behavior is not supported here because traversals are not expected to // behavior is not supported here because traversals are not expected to
// be parsed as part of a larger program. // be parsed as part of a larger program.
func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) { func (p *parser) ParseTraversalAbs() (hcl.Traversal, hcl.Diagnostics) {
var ret zcl.Traversal var ret hcl.Traversal
var diags zcl.Diagnostics var diags hcl.Diagnostics
// Absolute traversal must always begin with a variable name // Absolute traversal must always begin with a variable name
varTok := p.Read() varTok := p.Read()
if varTok.Type != TokenIdent { if varTok.Type != TokenIdent {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Variable name required", Summary: "Variable name required",
Detail: "Must begin with a variable name.", Detail: "Must begin with a variable name.",
Subject: &varTok.Range, Subject: &varTok.Range,
@ -26,7 +26,7 @@ func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) {
} }
varName := string(varTok.Bytes) varName := string(varTok.Bytes)
ret = append(ret, zcl.TraverseRoot{ ret = append(ret, hcl.TraverseRoot{
Name: varName, Name: varName,
SrcRange: varTok.Range, SrcRange: varTok.Range,
}) })
@ -45,29 +45,29 @@ func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) {
nameTok := p.Read() nameTok := p.Read()
if nameTok.Type != TokenIdent { if nameTok.Type != TokenIdent {
if nameTok.Type == TokenStar { if nameTok.Type == TokenStar {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Attribute name required", Summary: "Attribute name required",
Detail: "Splat expressions (.*) may not be used here.", Detail: "Splat expressions (.*) may not be used here.",
Subject: &nameTok.Range, Subject: &nameTok.Range,
Context: zcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(), Context: hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),
}) })
} else { } else {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Attribute name required", Summary: "Attribute name required",
Detail: "Dot must be followed by attribute name.", Detail: "Dot must be followed by attribute name.",
Subject: &nameTok.Range, Subject: &nameTok.Range,
Context: zcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(), Context: hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),
}) })
} }
return ret, diags return ret, diags
} }
attrName := string(nameTok.Bytes) attrName := string(nameTok.Bytes)
ret = append(ret, zcl.TraverseAttr{ ret = append(ret, hcl.TraverseAttr{
Name: attrName, Name: attrName,
SrcRange: zcl.RangeBetween(dot.Range, nameTok.Range), SrcRange: hcl.RangeBetween(dot.Range, nameTok.Range),
}) })
case TokenOBrack: case TokenOBrack:
// Index // Index
@ -82,18 +82,18 @@ func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) {
close := p.Read() close := p.Read()
if close.Type != TokenCBrack { if close.Type != TokenCBrack {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unclosed index brackets", Summary: "Unclosed index brackets",
Detail: "Index key must be followed by a closing bracket.", Detail: "Index key must be followed by a closing bracket.",
Subject: &close.Range, Subject: &close.Range,
Context: zcl.RangeBetween(open.Range, close.Range).Ptr(), Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
}) })
} }
ret = append(ret, zcl.TraverseIndex{ ret = append(ret, hcl.TraverseIndex{
Key: numVal, Key: numVal,
SrcRange: zcl.RangeBetween(open.Range, close.Range), SrcRange: hcl.RangeBetween(open.Range, close.Range),
}) })
if diags.HasErrors() { if diags.HasErrors() {
@ -106,18 +106,18 @@ func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) {
close := p.Read() close := p.Read()
if close.Type != TokenCBrack { if close.Type != TokenCBrack {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unclosed index brackets", Summary: "Unclosed index brackets",
Detail: "Index key must be followed by a closing bracket.", Detail: "Index key must be followed by a closing bracket.",
Subject: &close.Range, Subject: &close.Range,
Context: zcl.RangeBetween(open.Range, close.Range).Ptr(), Context: hcl.RangeBetween(open.Range, close.Range).Ptr(),
}) })
} }
ret = append(ret, zcl.TraverseIndex{ ret = append(ret, hcl.TraverseIndex{
Key: cty.StringVal(str), Key: cty.StringVal(str),
SrcRange: zcl.RangeBetween(open.Range, close.Range), SrcRange: hcl.RangeBetween(open.Range, close.Range),
}) })
if diags.HasErrors() { if diags.HasErrors() {
@ -126,32 +126,32 @@ func (p *parser) ParseTraversalAbs() (zcl.Traversal, zcl.Diagnostics) {
default: default:
if next.Type == TokenStar { if next.Type == TokenStar {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Attribute name required", Summary: "Attribute name required",
Detail: "Splat expressions ([*]) may not be used here.", Detail: "Splat expressions ([*]) may not be used here.",
Subject: &next.Range, Subject: &next.Range,
Context: zcl.RangeBetween(varTok.Range, next.Range).Ptr(), Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
}) })
} else { } else {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Index value required", Summary: "Index value required",
Detail: "Index brackets must contain either a literal number or a literal string.", Detail: "Index brackets must contain either a literal number or a literal string.",
Subject: &next.Range, Subject: &next.Range,
Context: zcl.RangeBetween(varTok.Range, next.Range).Ptr(), Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
}) })
} }
return ret, diags return ret, diags
} }
default: default:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character", Summary: "Invalid character",
Detail: "Expected an attribute access or an index operator.", Detail: "Expected an attribute access or an index operator.",
Subject: &next.Range, Subject: &next.Range,
Context: zcl.RangeBetween(varTok.Range, next.Range).Ptr(), Context: hcl.RangeBetween(varTok.Range, next.Range).Ptr(),
}) })
return ret, diags return ret, diags
} }

View File

@ -1,7 +1,7 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
type peeker struct { type peeker struct {
@ -32,11 +32,11 @@ func (p *peeker) Read() Token {
return ret return ret
} }
func (p *peeker) NextRange() zcl.Range { func (p *peeker) NextRange() hcl.Range {
return p.Peek().Range return p.Peek().Range
} }
func (p *peeker) PrevRange() zcl.Range { func (p *peeker) PrevRange() hcl.Range {
if p.NextIndex == 0 { if p.NextIndex == 0 {
return p.NextRange() return p.NextRange()
} }

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import ( import (
"reflect" "reflect"

View File

@ -1,26 +1,26 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// ParseConfig parses the given buffer as a whole zcl config file, returning // ParseConfig parses the given buffer as a whole zcl config file, returning
// a *zcl.File representing its contents. If HasErrors called on the returned // a *hcl.File representing its contents. If HasErrors called on the returned
// diagnostics returns true, the returned body is likely to be incomplete // diagnostics returns true, the returned body is likely to be incomplete
// and should therefore be used with care. // and should therefore be used with care.
// //
// The body in the returned file has dynamic type *zclsyntax.Body, so callers // The body in the returned file has dynamic type *zclsyntax.Body, so callers
// may freely type-assert this to get access to the full zclsyntax API in // may freely type-assert this to get access to the full zclsyntax API in
// situations where detailed access is required. However, most common use-cases // situations where detailed access is required. However, most common use-cases
// should be served using the zcl.Body interface to ensure compatibility with // should be served using the hcl.Body interface to ensure compatibility with
// other configurationg syntaxes, such as JSON. // other configurationg syntaxes, such as JSON.
func ParseConfig(src []byte, filename string, start zcl.Pos) (*zcl.File, zcl.Diagnostics) { func ParseConfig(src []byte, filename string, start hcl.Pos) (*hcl.File, hcl.Diagnostics) {
tokens, diags := LexConfig(src, filename, start) tokens, diags := LexConfig(src, filename, start)
peeker := newPeeker(tokens, false) peeker := newPeeker(tokens, false)
parser := &parser{peeker: peeker} parser := &parser{peeker: peeker}
body, parseDiags := parser.ParseBody(TokenEOF) body, parseDiags := parser.ParseBody(TokenEOF)
diags = append(diags, parseDiags...) diags = append(diags, parseDiags...)
return &zcl.File{ return &hcl.File{
Body: body, Body: body,
Bytes: src, Bytes: src,
@ -32,7 +32,7 @@ func ParseConfig(src []byte, filename string, start zcl.Pos) (*zcl.File, zcl.Dia
// ParseExpression parses the given buffer as a standalone zcl expression, // ParseExpression parses the given buffer as a standalone zcl expression,
// returning it as an instance of Expression. // returning it as an instance of Expression.
func ParseExpression(src []byte, filename string, start zcl.Pos) (Expression, zcl.Diagnostics) { func ParseExpression(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {
tokens, diags := LexExpression(src, filename, start) tokens, diags := LexExpression(src, filename, start)
peeker := newPeeker(tokens, false) peeker := newPeeker(tokens, false)
parser := &parser{peeker: peeker} parser := &parser{peeker: peeker}
@ -46,8 +46,8 @@ func ParseExpression(src []byte, filename string, start zcl.Pos) (Expression, zc
next := parser.Peek() next := parser.Peek()
if next.Type != TokenEOF && !parser.recovery { if next.Type != TokenEOF && !parser.recovery {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extra characters after expression", Summary: "Extra characters after expression",
Detail: "An expression was successfully parsed, but extra characters were found after it.", Detail: "An expression was successfully parsed, but extra characters were found after it.",
Subject: &next.Range, Subject: &next.Range,
@ -59,7 +59,7 @@ func ParseExpression(src []byte, filename string, start zcl.Pos) (Expression, zc
// ParseTemplate parses the given buffer as a standalone zcl template, // ParseTemplate parses the given buffer as a standalone zcl template,
// returning it as an instance of Expression. // returning it as an instance of Expression.
func ParseTemplate(src []byte, filename string, start zcl.Pos) (Expression, zcl.Diagnostics) { func ParseTemplate(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {
tokens, diags := LexTemplate(src, filename, start) tokens, diags := LexTemplate(src, filename, start)
peeker := newPeeker(tokens, false) peeker := newPeeker(tokens, false)
parser := &parser{peeker: peeker} parser := &parser{peeker: peeker}
@ -74,7 +74,7 @@ func ParseTemplate(src []byte, filename string, start zcl.Pos) (Expression, zcl.
// it allows only attribute and indexing operations on variables. Traverals // it allows only attribute and indexing operations on variables. Traverals
// are useful as a syntax for referring to objects without necessarily // are useful as a syntax for referring to objects without necessarily
// evaluating them. // evaluating them.
func ParseTraversalAbs(src []byte, filename string, start zcl.Pos) (zcl.Traversal, zcl.Diagnostics) { func ParseTraversalAbs(src []byte, filename string, start hcl.Pos) (hcl.Traversal, hcl.Diagnostics) {
tokens, diags := LexExpression(src, filename, start) tokens, diags := LexExpression(src, filename, start)
peeker := newPeeker(tokens, false) peeker := newPeeker(tokens, false)
parser := &parser{peeker: peeker} parser := &parser{peeker: peeker}
@ -95,7 +95,7 @@ func ParseTraversalAbs(src []byte, filename string, start zcl.Pos) (zcl.Traversa
// diagnostics may include errors about lexical issues such as bad character // diagnostics may include errors about lexical issues such as bad character
// encodings or unrecognized characters, but full parsing is required to // encodings or unrecognized characters, but full parsing is required to
// detect _all_ syntax errors. // detect _all_ syntax errors.
func LexConfig(src []byte, filename string, start zcl.Pos) (Tokens, zcl.Diagnostics) { func LexConfig(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
tokens := scanTokens(src, filename, start, scanNormal) tokens := scanTokens(src, filename, start, scanNormal)
diags := checkInvalidTokens(tokens) diags := checkInvalidTokens(tokens)
return tokens, diags return tokens, diags
@ -108,7 +108,7 @@ func LexConfig(src []byte, filename string, start zcl.Pos) (Tokens, zcl.Diagnost
// diagnostics may include errors about lexical issues such as bad character // diagnostics may include errors about lexical issues such as bad character
// encodings or unrecognized characters, but full parsing is required to // encodings or unrecognized characters, but full parsing is required to
// detect _all_ syntax errors. // detect _all_ syntax errors.
func LexExpression(src []byte, filename string, start zcl.Pos) (Tokens, zcl.Diagnostics) { func LexExpression(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
// This is actually just the same thing as LexConfig, since configs // This is actually just the same thing as LexConfig, since configs
// and expressions lex in the same way. // and expressions lex in the same way.
tokens := scanTokens(src, filename, start, scanNormal) tokens := scanTokens(src, filename, start, scanNormal)
@ -123,7 +123,7 @@ func LexExpression(src []byte, filename string, start zcl.Pos) (Tokens, zcl.Diag
// diagnostics may include errors about lexical issues such as bad character // diagnostics may include errors about lexical issues such as bad character
// encodings or unrecognized characters, but full parsing is required to // encodings or unrecognized characters, but full parsing is required to
// detect _all_ syntax errors. // detect _all_ syntax errors.
func LexTemplate(src []byte, filename string, start zcl.Pos) (Tokens, zcl.Diagnostics) { func LexTemplate(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {
tokens := scanTokens(src, filename, start, scanTemplate) tokens := scanTokens(src, filename, start, scanTemplate)
diags := checkInvalidTokens(tokens) diags := checkInvalidTokens(tokens)
return tokens, diags return tokens, diags

View File

@ -1,10 +1,10 @@
// line 1 "scan_tokens.rl" // line 1 "scan_tokens.rl"
package zclsyntax package hclsyntax
import ( import (
"bytes" "bytes"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// This file is generated from scan_tokens.rl. DO NOT EDIT. // This file is generated from scan_tokens.rl. DO NOT EDIT.
@ -2750,7 +2750,7 @@ const zcltok_en_main int = 949
// line 15 "scan_tokens.rl" // line 15 "scan_tokens.rl"
func scanTokens(data []byte, filename string, start zcl.Pos, mode scanMode) []Token { func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {
f := &tokenAccum{ f := &tokenAccum{
Filename: filename, Filename: filename,
Bytes: data, Bytes: data,

View File

@ -14,7 +14,7 @@ import (
write data; write data;
}%% }%%
func scanTokens(data []byte, filename string, start zcl.Pos, mode scanMode) []Token { func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {
f := &tokenAccum{ f := &tokenAccum{
Filename: filename, Filename: filename,
Bytes: data, Bytes: data,

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# zcl Native Syntax Specification # zcl Native Syntax Specification
This is the specification of the syntax and semantics of the native syntax This is the specification of the syntax and semantics of the native syntax
for zcl. zcl is a system for defining configuration languages for applications. for hcl. zcl is a system for defining configuration languages for applications.
The zcl information model is designed to support multiple concrete syntaxes The zcl information model is designed to support multiple concrete syntaxes
for configuration, but this native syntax is considered the primary format for configuration, but this native syntax is considered the primary format
and is optimized for human authoring and maintenence, as opposed to machine and is optimized for human authoring and maintenence, as opposed to machine

View File

@ -1,31 +1,31 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"strings" "strings"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// AsZCLBlock returns the block data expressed as a *zcl.Block. // AsZCLBlock returns the block data expressed as a *hcl.Block.
func (b *Block) AsZCLBlock() *zcl.Block { func (b *Block) AsZCLBlock() *hcl.Block {
lastHeaderRange := b.TypeRange lastHeaderRange := b.TypeRange
if len(b.LabelRanges) > 0 { if len(b.LabelRanges) > 0 {
lastHeaderRange = b.LabelRanges[len(b.LabelRanges)-1] lastHeaderRange = b.LabelRanges[len(b.LabelRanges)-1]
} }
return &zcl.Block{ return &hcl.Block{
Type: b.Type, Type: b.Type,
Labels: b.Labels, Labels: b.Labels,
Body: b.Body, Body: b.Body,
DefRange: zcl.RangeBetween(b.TypeRange, lastHeaderRange), DefRange: hcl.RangeBetween(b.TypeRange, lastHeaderRange),
TypeRange: b.TypeRange, TypeRange: b.TypeRange,
LabelRanges: b.LabelRanges, LabelRanges: b.LabelRanges,
} }
} }
// Body is the implementation of zcl.Body for the zcl native syntax. // Body is the implementation of hcl.Body for the zcl native syntax.
type Body struct { type Body struct {
Attributes Attributes Attributes Attributes
Blocks Blocks Blocks Blocks
@ -35,23 +35,23 @@ type Body struct {
hiddenAttrs map[string]struct{} hiddenAttrs map[string]struct{}
hiddenBlocks map[string]struct{} hiddenBlocks map[string]struct{}
SrcRange zcl.Range SrcRange hcl.Range
EndRange zcl.Range // Final token of the body, for reporting missing items EndRange hcl.Range // Final token of the body, for reporting missing items
} }
// Assert that *Body implements zcl.Body // Assert that *Body implements hcl.Body
var assertBodyImplBody zcl.Body = &Body{} var assertBodyImplBody hcl.Body = &Body{}
func (b *Body) walkChildNodes(w internalWalkFunc) { func (b *Body) walkChildNodes(w internalWalkFunc) {
b.Attributes = w(b.Attributes).(Attributes) b.Attributes = w(b.Attributes).(Attributes)
b.Blocks = w(b.Blocks).(Blocks) b.Blocks = w(b.Blocks).(Blocks)
} }
func (b *Body) Range() zcl.Range { func (b *Body) Range() hcl.Range {
return b.SrcRange return b.SrcRange
} }
func (b *Body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostics) { func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
content, remainZCL, diags := b.PartialContent(schema) content, remainZCL, diags := b.PartialContent(schema)
// No we'll see if anything actually remains, to produce errors about // No we'll see if anything actually remains, to produce errors about
@ -80,8 +80,8 @@ func (b *Body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostic
} }
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsupported attribute", Summary: "Unsupported attribute",
Detail: fmt.Sprintf("An attribute named %q is not expected here.%s", name, suggestion), Detail: fmt.Sprintf("An attribute named %q is not expected here.%s", name, suggestion),
Subject: &attr.NameRange, Subject: &attr.NameRange,
@ -109,8 +109,8 @@ func (b *Body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostic
} }
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsupported block type", Summary: "Unsupported block type",
Detail: fmt.Sprintf("Blocks of type %q are not expected here.%s", blockTy, suggestion), Detail: fmt.Sprintf("Blocks of type %q are not expected here.%s", blockTy, suggestion),
Subject: &block.TypeRange, Subject: &block.TypeRange,
@ -121,10 +121,10 @@ func (b *Body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostic
return content, diags return content, diags
} }
func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Body, zcl.Diagnostics) { func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
attrs := make(zcl.Attributes) attrs := make(hcl.Attributes)
var blocks zcl.Blocks var blocks hcl.Blocks
var diags zcl.Diagnostics var diags hcl.Diagnostics
hiddenAttrs := make(map[string]struct{}) hiddenAttrs := make(map[string]struct{})
hiddenBlocks := make(map[string]struct{}) hiddenBlocks := make(map[string]struct{})
@ -145,8 +145,8 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
_, hidden := hiddenAttrs[name] _, hidden := hiddenAttrs[name]
if hidden || !exists { if hidden || !exists {
if attrS.Required { if attrS.Required {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing required attribute", Summary: "Missing required attribute",
Detail: fmt.Sprintf("The attribute %q is required, but no definition was found.", attrS.Name), Detail: fmt.Sprintf("The attribute %q is required, but no definition was found.", attrS.Name),
Subject: b.MissingItemRange().Ptr(), Subject: b.MissingItemRange().Ptr(),
@ -159,7 +159,7 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
attrs[name] = attr.AsZCLAttribute() attrs[name] = attr.AsZCLAttribute()
} }
blocksWanted := make(map[string]zcl.BlockHeaderSchema) blocksWanted := make(map[string]hcl.BlockHeaderSchema)
for _, blockS := range schema.Blocks { for _, blockS := range schema.Blocks {
blocksWanted[blockS.Type] = blockS blocksWanted[blockS.Type] = blockS
} }
@ -176,25 +176,25 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
if len(block.Labels) > len(blockS.LabelNames) { if len(block.Labels) > len(blockS.LabelNames) {
name := block.Type name := block.Type
if len(blockS.LabelNames) == 0 { if len(blockS.LabelNames) == 0 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Extraneous label for %s", name), Summary: fmt.Sprintf("Extraneous label for %s", name),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"No labels are expected for %s blocks.", name, "No labels are expected for %s blocks.", name,
), ),
Subject: block.LabelRanges[0].Ptr(), Subject: block.LabelRanges[0].Ptr(),
Context: zcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(), Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
}) })
} else { } else {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Extraneous label for %s", name), Summary: fmt.Sprintf("Extraneous label for %s", name),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Only %d labels (%s) are expected for %s blocks.", "Only %d labels (%s) are expected for %s blocks.",
len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "), name, len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "), name,
), ),
Subject: block.LabelRanges[len(blockS.LabelNames)].Ptr(), Subject: block.LabelRanges[len(blockS.LabelNames)].Ptr(),
Context: zcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(), Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
}) })
} }
continue continue
@ -202,15 +202,15 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
if len(block.Labels) < len(blockS.LabelNames) { if len(block.Labels) < len(blockS.LabelNames) {
name := block.Type name := block.Type
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Missing %s for %s", blockS.LabelNames[len(block.Labels)], name), Summary: fmt.Sprintf("Missing %s for %s", blockS.LabelNames[len(block.Labels)], name),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"All %s blocks must have %d labels (%s).", "All %s blocks must have %d labels (%s).",
name, len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "), name, len(blockS.LabelNames), strings.Join(blockS.LabelNames, ", "),
), ),
Subject: &block.OpenBraceRange, Subject: &block.OpenBraceRange,
Context: zcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(), Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),
}) })
continue continue
} }
@ -235,7 +235,7 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
EndRange: b.EndRange, EndRange: b.EndRange,
} }
return &zcl.BodyContent{ return &hcl.BodyContent{
Attributes: attrs, Attributes: attrs,
Blocks: blocks, Blocks: blocks,
@ -243,14 +243,14 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
}, remain, diags }, remain, diags
} }
func (b *Body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) { func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
attrs := make(zcl.Attributes) attrs := make(hcl.Attributes)
var diags zcl.Diagnostics var diags hcl.Diagnostics
if len(b.Blocks) > 0 { if len(b.Blocks) > 0 {
example := b.Blocks[0] example := b.Blocks[0]
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unexpected %s block", example.Type), Summary: fmt.Sprintf("Unexpected %s block", example.Type),
Detail: "Blocks are not allowed here.", Detail: "Blocks are not allowed here.",
Context: &example.TypeRange, Context: &example.TypeRange,
@ -274,7 +274,7 @@ func (b *Body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) {
return attrs, diags return attrs, diags
} }
func (b *Body) MissingItemRange() zcl.Range { func (b *Body) MissingItemRange() hcl.Range {
return b.EndRange return b.EndRange
} }
@ -292,7 +292,7 @@ func (a Attributes) walkChildNodes(w internalWalkFunc) {
// //
// This is provided only to complete the Node interface, but has no practical // This is provided only to complete the Node interface, but has no practical
// use. // use.
func (a Attributes) Range() zcl.Range { func (a Attributes) Range() hcl.Range {
// An attributes doesn't really have a useful range to report, since // An attributes doesn't really have a useful range to report, since
// it's just a grouping construct. So we'll arbitrarily take the // it's just a grouping construct. So we'll arbitrarily take the
// range of one of the attributes, or produce an invalid range if we have // range of one of the attributes, or produce an invalid range if we have
@ -301,7 +301,7 @@ func (a Attributes) Range() zcl.Range {
for _, attr := range a { for _, attr := range a {
return attr.Range() return attr.Range()
} }
return zcl.Range{ return hcl.Range{
Filename: "<unknown>", Filename: "<unknown>",
} }
} }
@ -311,22 +311,22 @@ type Attribute struct {
Name string Name string
Expr Expression Expr Expression
SrcRange zcl.Range SrcRange hcl.Range
NameRange zcl.Range NameRange hcl.Range
EqualsRange zcl.Range EqualsRange hcl.Range
} }
func (a *Attribute) walkChildNodes(w internalWalkFunc) { func (a *Attribute) walkChildNodes(w internalWalkFunc) {
a.Expr = w(a.Expr).(Expression) a.Expr = w(a.Expr).(Expression)
} }
func (a *Attribute) Range() zcl.Range { func (a *Attribute) Range() hcl.Range {
return a.SrcRange return a.SrcRange
} }
// AsZCLAttribute returns the block data expressed as a *zcl.Attribute. // AsZCLAttribute returns the block data expressed as a *hcl.Attribute.
func (a *Attribute) AsZCLAttribute() *zcl.Attribute { func (a *Attribute) AsZCLAttribute() *hcl.Attribute {
return &zcl.Attribute{ return &hcl.Attribute{
Name: a.Name, Name: a.Name,
Expr: a.Expr, Expr: a.Expr,
@ -349,11 +349,11 @@ func (bs Blocks) walkChildNodes(w internalWalkFunc) {
// //
// This is provided only to complete the Node interface, but has no practical // This is provided only to complete the Node interface, but has no practical
// use. // use.
func (bs Blocks) Range() zcl.Range { func (bs Blocks) Range() hcl.Range {
if len(bs) > 0 { if len(bs) > 0 {
return bs[0].Range() return bs[0].Range()
} }
return zcl.Range{ return hcl.Range{
Filename: "<unknown>", Filename: "<unknown>",
} }
} }
@ -364,16 +364,16 @@ type Block struct {
Labels []string Labels []string
Body *Body Body *Body
TypeRange zcl.Range TypeRange hcl.Range
LabelRanges []zcl.Range LabelRanges []hcl.Range
OpenBraceRange zcl.Range OpenBraceRange hcl.Range
CloseBraceRange zcl.Range CloseBraceRange hcl.Range
} }
func (b *Block) walkChildNodes(w internalWalkFunc) { func (b *Block) walkChildNodes(w internalWalkFunc) {
b.Body = w(b.Body).(*Body) b.Body = w(b.Body).(*Body)
} }
func (b *Block) Range() zcl.Range { func (b *Block) Range() hcl.Range {
return zcl.RangeBetween(b.TypeRange, b.CloseBraceRange) return hcl.RangeBetween(b.TypeRange, b.CloseBraceRange)
} }

View File

@ -1,11 +1,11 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/kylelemons/godebug/pretty" "github.com/kylelemons/godebug/pretty"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -13,17 +13,17 @@ import (
func TestBodyContent(t *testing.T) { func TestBodyContent(t *testing.T) {
tests := []struct { tests := []struct {
body *Body body *Body
schema *zcl.BodySchema schema *hcl.BodySchema
partial bool partial bool
want *zcl.BodyContent want *hcl.BodyContent
diagCount int diagCount int
}{ }{
{ {
&Body{}, &Body{},
&zcl.BodySchema{}, &hcl.BodySchema{},
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
0, 0,
}, },
@ -37,17 +37,17 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "foo", Name: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{ Attributes: hcl.Attributes{
"foo": &zcl.Attribute{ "foo": &hcl.Attribute{
Name: "foo", Name: "foo",
}, },
}, },
@ -62,10 +62,10 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{}, &hcl.BodySchema{},
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // attribute "foo" is not expected 1, // attribute "foo" is not expected
}, },
@ -77,10 +77,10 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{}, &hcl.BodySchema{},
true, true,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
0, // in partial mode, so extra "foo" is acceptable 0, // in partial mode, so extra "foo" is acceptable
}, },
@ -88,16 +88,16 @@ func TestBodyContent(t *testing.T) {
&Body{ &Body{
Attributes: Attributes{}, Attributes: Attributes{},
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "foo", Name: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
0, // "foo" not required, so no error 0, // "foo" not required, so no error
}, },
@ -105,8 +105,8 @@ func TestBodyContent(t *testing.T) {
&Body{ &Body{
Attributes: Attributes{}, Attributes: Attributes{},
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "foo", Name: "foo",
Required: true, Required: true,
@ -114,8 +114,8 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // "foo" is required 1, // "foo" is required
}, },
@ -127,16 +127,16 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // attribute "foo" not expected (it's defined as a block) 1, // attribute "foo" not expected (it's defined as a block)
}, },
@ -150,17 +150,17 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: (*Body)(nil), Body: (*Body)(nil),
@ -180,17 +180,17 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: (*Body)(nil), Body: (*Body)(nil),
@ -214,17 +214,17 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: (*Body)(nil), Body: (*Body)(nil),
@ -244,17 +244,17 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
true, true,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Body: (*Body)(nil), Body: (*Body)(nil),
@ -272,8 +272,8 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -281,9 +281,9 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "foo", Type: "foo",
Labels: []string{"bar"}, Labels: []string{"bar"},
@ -301,8 +301,8 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -310,8 +310,8 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // missing label "name" 1, // missing label "name"
}, },
@ -322,20 +322,20 @@ func TestBodyContent(t *testing.T) {
Type: "foo", Type: "foo",
Labels: []string{"bar"}, Labels: []string{"bar"},
LabelRanges: []zcl.Range{{}}, LabelRanges: []hcl.Range{{}},
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // no labels expected 1, // no labels expected
}, },
@ -346,12 +346,12 @@ func TestBodyContent(t *testing.T) {
Type: "foo", Type: "foo",
Labels: []string{"bar", "baz"}, Labels: []string{"bar", "baz"},
LabelRanges: []zcl.Range{{}, {}}, LabelRanges: []hcl.Range{{}, {}},
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
@ -359,8 +359,8 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // too many labels 1, // too many labels
}, },
@ -372,16 +372,16 @@ func TestBodyContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "foo", Type: "foo",
}, },
}, },
}, },
false, false,
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
1, // should've been a block, not an attribute 1, // should've been a block, not an attribute
}, },
@ -395,8 +395,8 @@ func TestBodyContent(t *testing.T) {
for i, test := range tests { for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
var got *zcl.BodyContent var got *hcl.BodyContent
var diags zcl.Diagnostics var diags hcl.Diagnostics
if test.partial { if test.partial {
got, _, diags = test.body.PartialContent(test.schema) got, _, diags = test.body.PartialContent(test.schema)
} else { } else {
@ -423,19 +423,19 @@ func TestBodyContent(t *testing.T) {
func TestBodyJustAttributes(t *testing.T) { func TestBodyJustAttributes(t *testing.T) {
tests := []struct { tests := []struct {
body *Body body *Body
want zcl.Attributes want hcl.Attributes
diagCount int diagCount int
}{ }{
{ {
&Body{}, &Body{},
zcl.Attributes{}, hcl.Attributes{},
0, 0,
}, },
{ {
&Body{ &Body{
Attributes: Attributes{}, Attributes: Attributes{},
}, },
zcl.Attributes{}, hcl.Attributes{},
0, 0,
}, },
{ {
@ -449,8 +449,8 @@ func TestBodyJustAttributes(t *testing.T) {
}, },
}, },
}, },
zcl.Attributes{ hcl.Attributes{
"foo": &zcl.Attribute{ "foo": &hcl.Attribute{
Name: "foo", Name: "foo",
Expr: &LiteralValueExpr{ Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"), Val: cty.StringVal("bar"),
@ -475,8 +475,8 @@ func TestBodyJustAttributes(t *testing.T) {
}, },
}, },
}, },
zcl.Attributes{ hcl.Attributes{
"foo": &zcl.Attribute{ "foo": &hcl.Attribute{
Name: "foo", Name: "foo",
Expr: &LiteralValueExpr{ Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"), Val: cty.StringVal("bar"),
@ -499,7 +499,7 @@ func TestBodyJustAttributes(t *testing.T) {
"foo": struct{}{}, "foo": struct{}{},
}, },
}, },
zcl.Attributes{}, hcl.Attributes{},
0, 0,
}, },
} }

View File

@ -1,10 +1,10 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
"github.com/apparentlymart/go-textseg/textseg" "github.com/apparentlymart/go-textseg/textseg"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Token represents a sequence of bytes from some zcl code that has been // Token represents a sequence of bytes from some zcl code that has been
@ -12,7 +12,7 @@ import (
type Token struct { type Token struct {
Type TokenType Type TokenType
Bytes []byte Bytes []byte
Range zcl.Range Range hcl.Range
} }
// Tokens is a slice of Token. // Tokens is a slice of Token.
@ -115,7 +115,7 @@ const (
type tokenAccum struct { type tokenAccum struct {
Filename string Filename string
Bytes []byte Bytes []byte
Pos zcl.Pos Pos hcl.Pos
Tokens []Token Tokens []Token
} }
@ -146,7 +146,7 @@ func (f *tokenAccum) emitToken(ty TokenType, startOfs, endOfs int) {
f.Tokens = append(f.Tokens, Token{ f.Tokens = append(f.Tokens, Token{
Type: ty, Type: ty,
Bytes: f.Bytes[startOfs:endOfs], Bytes: f.Bytes[startOfs:endOfs],
Range: zcl.Range{ Range: hcl.Range{
Filename: f.Filename, Filename: f.Filename,
Start: start, Start: start,
End: end, End: end,
@ -167,8 +167,8 @@ type heredocInProgress struct {
// Returns a diagnostics with no errors if everything seems acceptable. // Returns a diagnostics with no errors if everything seems acceptable.
// Otherwise, returns zero or more error diagnostics, though tries to limit // Otherwise, returns zero or more error diagnostics, though tries to limit
// repetition of the same information. // repetition of the same information.
func checkInvalidTokens(tokens Tokens) zcl.Diagnostics { func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
var diags zcl.Diagnostics var diags hcl.Diagnostics
toldBitwise := 0 toldBitwise := 0
toldExponent := 0 toldExponent := 0
@ -191,8 +191,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
suggestion = " Did you mean boolean NOT (\"!\")?" suggestion = " Did you mean boolean NOT (\"!\")?"
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsupported operator", Summary: "Unsupported operator",
Detail: fmt.Sprintf("Bitwise operators are not supported.%s", suggestion), Detail: fmt.Sprintf("Bitwise operators are not supported.%s", suggestion),
Subject: &tok.Range, Subject: &tok.Range,
@ -201,8 +201,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
} }
case TokenStarStar: case TokenStarStar:
if toldExponent < 1 { if toldExponent < 1 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unsupported operator", Summary: "Unsupported operator",
Detail: "\"**\" is not a supported operator. Exponentiation is not supported as an operator.", Detail: "\"**\" is not a supported operator. Exponentiation is not supported as an operator.",
Subject: &tok.Range, Subject: &tok.Range,
@ -214,8 +214,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
// Only report for alternating (even) backticks, so we won't report both start and ends of the same // Only report for alternating (even) backticks, so we won't report both start and ends of the same
// backtick-quoted string. // backtick-quoted string.
if toldExponent < 4 && (toldExponent%2) == 0 { if toldExponent < 4 && (toldExponent%2) == 0 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character", Summary: "Invalid character",
Detail: "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<<EOT\".", Detail: "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<<EOT\".",
Subject: &tok.Range, Subject: &tok.Range,
@ -225,8 +225,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
} }
case TokenSemicolon: case TokenSemicolon:
if toldSemicolon < 1 { if toldSemicolon < 1 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character", Summary: "Invalid character",
Detail: "The \";\" character is not valid. Use newlines to separate attributes and blocks, and commas to separate items in collection values.", Detail: "The \";\" character is not valid. Use newlines to separate attributes and blocks, and commas to separate items in collection values.",
Subject: &tok.Range, Subject: &tok.Range,
@ -236,8 +236,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
} }
case TokenTabs: case TokenTabs:
if toldTabs < 1 { if toldTabs < 1 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character", Summary: "Invalid character",
Detail: "Tab characters may not be used. The recommended indentation style is two spaces per indent.", Detail: "Tab characters may not be used. The recommended indentation style is two spaces per indent.",
Subject: &tok.Range, Subject: &tok.Range,
@ -247,8 +247,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
} }
case TokenBadUTF8: case TokenBadUTF8:
if toldBadUTF8 < 1 { if toldBadUTF8 < 1 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character encoding", Summary: "Invalid character encoding",
Detail: "All input files must be UTF-8 encoded. Ensure that UTF-8 encoding is selected in your editor.", Detail: "All input files must be UTF-8 encoded. Ensure that UTF-8 encoding is selected in your editor.",
Subject: &tok.Range, Subject: &tok.Range,
@ -257,8 +257,8 @@ func checkInvalidTokens(tokens Tokens) zcl.Diagnostics {
toldBadUTF8++ toldBadUTF8++
} }
case TokenInvalid: case TokenInvalid:
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid character", Summary: "Invalid character",
Detail: "This character is not used within the language.", Detail: "This character is not used within the language.",
Subject: &tok.Range, Subject: &tok.Range,

View File

@ -1,6 +1,6 @@
// Code generated by "stringer -type TokenType -output token_type_string.go"; DO NOT EDIT. // Code generated by "stringer -type TokenType -output token_type_string.go"; DO NOT EDIT.
package zclsyntax package hclsyntax
import "fmt" import "fmt"

View File

@ -1,18 +1,18 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Variables returns all of the variables referenced within a given experssion. // Variables returns all of the variables referenced within a given experssion.
// //
// This is the implementation of the "Variables" method on every native // This is the implementation of the "Variables" method on every native
// expression. // expression.
func Variables(expr Expression) []zcl.Traversal { func Variables(expr Expression) []hcl.Traversal {
var vars []zcl.Traversal var vars []hcl.Traversal
walker := &variablesWalker{ walker := &variablesWalker{
Callback: func(t zcl.Traversal) { Callback: func(t hcl.Traversal) {
vars = append(vars, t) vars = append(vars, t)
}, },
} }
@ -25,11 +25,11 @@ func Variables(expr Expression) []zcl.Traversal {
// variablesWalker is a Walker implementation that calls its callback for any // variablesWalker is a Walker implementation that calls its callback for any
// root scope traversal found while walking. // root scope traversal found while walking.
type variablesWalker struct { type variablesWalker struct {
Callback func(zcl.Traversal) Callback func(hcl.Traversal)
localScopes []map[string]struct{} localScopes []map[string]struct{}
} }
func (w *variablesWalker) Enter(n Node) zcl.Diagnostics { func (w *variablesWalker) Enter(n Node) hcl.Diagnostics {
switch tn := n.(type) { switch tn := n.(type) {
case *ScopeTraversalExpr: case *ScopeTraversalExpr:
t := tn.Traversal t := tn.Traversal
@ -52,7 +52,7 @@ func (w *variablesWalker) Enter(n Node) zcl.Diagnostics {
return nil return nil
} }
func (w *variablesWalker) Exit(n Node) zcl.Diagnostics { func (w *variablesWalker) Exit(n Node) hcl.Diagnostics {
switch n.(type) { switch n.(type) {
case ChildScope: case ChildScope:
// pop the latest local scope, assuming that the walker will // pop the latest local scope, assuming that the walker will
@ -81,6 +81,6 @@ func (e ChildScope) walkChildNodes(w internalWalkFunc) {
// Range returns the range of the expression that the ChildScope is // Range returns the range of the expression that the ChildScope is
// encapsulating. It isn't really very useful to call Range on a ChildScope. // encapsulating. It isn't really very useful to call Range on a ChildScope.
func (e ChildScope) Range() zcl.Range { func (e ChildScope) Range() hcl.Range {
return (*e.Expr).Range() return (*e.Expr).Range()
} }

View File

@ -1,4 +1,4 @@
package zclsyntax package hclsyntax
import ( import (
"fmt" "fmt"
@ -7,14 +7,14 @@ import (
"reflect" "reflect"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
func TestVariables(t *testing.T) { func TestVariables(t *testing.T) {
tests := []struct { tests := []struct {
Expr Expression Expr Expression
Want []zcl.Traversal Want []hcl.Traversal
}{ }{
{ {
&LiteralValueExpr{ &LiteralValueExpr{
@ -24,15 +24,15 @@ func TestVariables(t *testing.T) {
}, },
{ {
&ScopeTraversalExpr{ &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
@ -41,29 +41,29 @@ func TestVariables(t *testing.T) {
{ {
&BinaryOpExpr{ &BinaryOpExpr{
LHS: &ScopeTraversalExpr{ LHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
}, },
Op: OpAdd, Op: OpAdd,
RHS: &ScopeTraversalExpr{ RHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
@ -72,17 +72,17 @@ func TestVariables(t *testing.T) {
{ {
&UnaryOpExpr{ &UnaryOpExpr{
Val: &ScopeTraversalExpr{ Val: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
}, },
Op: OpNegate, Op: OpNegate,
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
@ -91,40 +91,40 @@ func TestVariables(t *testing.T) {
{ {
&ConditionalExpr{ &ConditionalExpr{
Condition: &ScopeTraversalExpr{ Condition: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
}, },
TrueResult: &ScopeTraversalExpr{ TrueResult: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
}, },
FalseResult: &ScopeTraversalExpr{ FalseResult: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "baz", Name: "baz",
}, },
}, },
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "baz", Name: "baz",
}, },
}, },
@ -136,24 +136,24 @@ func TestVariables(t *testing.T) {
ValVar: "v", ValVar: "v",
CollExpr: &ScopeTraversalExpr{ CollExpr: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
}, },
KeyExpr: &BinaryOpExpr{ KeyExpr: &BinaryOpExpr{
LHS: &ScopeTraversalExpr{ LHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "k", Name: "k",
}, },
}, },
}, },
Op: OpAdd, Op: OpAdd,
RHS: &ScopeTraversalExpr{ RHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
@ -161,16 +161,16 @@ func TestVariables(t *testing.T) {
}, },
ValExpr: &BinaryOpExpr{ ValExpr: &BinaryOpExpr{
LHS: &ScopeTraversalExpr{ LHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "v", Name: "v",
}, },
}, },
}, },
Op: OpAdd, Op: OpAdd,
RHS: &ScopeTraversalExpr{ RHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "baz", Name: "baz",
}, },
}, },
@ -178,40 +178,40 @@ func TestVariables(t *testing.T) {
}, },
CondExpr: &BinaryOpExpr{ CondExpr: &BinaryOpExpr{
LHS: &ScopeTraversalExpr{ LHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "k", Name: "k",
}, },
}, },
}, },
Op: OpLessThan, Op: OpLessThan,
RHS: &ScopeTraversalExpr{ RHS: &ScopeTraversalExpr{
Traversal: zcl.Traversal{ Traversal: hcl.Traversal{
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "limit", Name: "limit",
}, },
}, },
}, },
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "baz", Name: "baz",
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "limit", Name: "limit",
}, },
}, },

View File

@ -1,11 +1,11 @@
package zclsyntax package hclsyntax
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// VisitFunc is the callback signature for VisitAll. // VisitFunc is the callback signature for VisitAll.
type VisitFunc func(node Node) zcl.Diagnostics type VisitFunc func(node Node) hcl.Diagnostics
// VisitAll is a basic way to traverse the AST beginning with a particular // VisitAll is a basic way to traverse the AST beginning with a particular
// node. The given function will be called once for each AST node in // node. The given function will be called once for each AST node in
@ -13,7 +13,7 @@ type VisitFunc func(node Node) zcl.Diagnostics
// //
// The VisitFunc may return diagnostics, in which case they will be accumulated // The VisitFunc may return diagnostics, in which case they will be accumulated
// and returned as a single set. // and returned as a single set.
func VisitAll(node Node, f VisitFunc) zcl.Diagnostics { func VisitAll(node Node, f VisitFunc) hcl.Diagnostics {
diags := f(node) diags := f(node)
node.walkChildNodes(func(node Node) Node { node.walkChildNodes(func(node Node) Node {
diags = append(diags, VisitAll(node, f)...) diags = append(diags, VisitAll(node, f)...)
@ -24,14 +24,14 @@ func VisitAll(node Node, f VisitFunc) zcl.Diagnostics {
// Walker is an interface used with Walk. // Walker is an interface used with Walk.
type Walker interface { type Walker interface {
Enter(node Node) zcl.Diagnostics Enter(node Node) hcl.Diagnostics
Exit(node Node) zcl.Diagnostics Exit(node Node) hcl.Diagnostics
} }
// Walk is a more complex way to traverse the AST starting with a particular // Walk is a more complex way to traverse the AST starting with a particular
// node, which provides information about the tree structure via separate // node, which provides information about the tree structure via separate
// Enter and Exit functions. // Enter and Exit functions.
func Walk(node Node, w Walker) zcl.Diagnostics { func Walk(node Node, w Walker) hcl.Diagnostics {
diags := w.Enter(node) diags := w.Enter(node)
node.walkChildNodes(func(node Node) Node { node.walkChildNodes(func(node Node) Node {
diags = append(diags, Walk(node, w)...) diags = append(diags, Walk(node, w)...)
@ -49,20 +49,20 @@ type Transformer interface {
// //
// It is acceptable and appropriate for Transform to return the same node // It is acceptable and appropriate for Transform to return the same node
// it was given, for situations where no transform is needed. // it was given, for situations where no transform is needed.
Transform(node Node) (Node, bool, zcl.Diagnostics) Transform(node Node) (Node, bool, hcl.Diagnostics)
// TransformExit signals the end of transformations of child nodes of the // TransformExit signals the end of transformations of child nodes of the
// given node. If Transform returned a new node, the given node is the // given node. If Transform returned a new node, the given node is the
// node that was returned, rather than the node that was originally // node that was returned, rather than the node that was originally
// encountered. // encountered.
TransformExit(node Node) zcl.Diagnostics TransformExit(node Node) hcl.Diagnostics
} }
// Transform allows for in-place transformations of an AST starting with a // Transform allows for in-place transformations of an AST starting with a
// particular node. The provider Transformer implementation drives the // particular node. The provider Transformer implementation drives the
// transformation process. The return value is the node that replaced the // transformation process. The return value is the node that replaced the
// given top-level node. // given top-level node.
func Transform(node Node, t Transformer) (Node, zcl.Diagnostics) { func Transform(node Node, t Transformer) (Node, hcl.Diagnostics) {
newNode, descend, diags := t.Transform(node) newNode, descend, diags := t.Transform(node)
if !descend { if !descend {
return newNode, diags return newNode, diags

121
hcl/json/ast.go Normal file
View File

@ -0,0 +1,121 @@
package json
import (
"math/big"
"github.com/hashicorp/hcl2/hcl"
)
type node interface {
Range() hcl.Range
StartRange() hcl.Range
}
type objectVal struct {
Attrs map[string]*objectAttr
SrcRange hcl.Range // range of the entire object, brace-to-brace
OpenRange hcl.Range // range of the opening brace
CloseRange hcl.Range // range of the closing brace
}
func (n *objectVal) Range() hcl.Range {
return n.SrcRange
}
func (n *objectVal) StartRange() hcl.Range {
return n.OpenRange
}
type objectAttr struct {
Name string
Value node
NameRange hcl.Range // range of the name string
}
func (n *objectAttr) Range() hcl.Range {
return n.NameRange
}
func (n *objectAttr) StartRange() hcl.Range {
return n.NameRange
}
type arrayVal struct {
Values []node
SrcRange hcl.Range // range of the entire object, bracket-to-bracket
OpenRange hcl.Range // range of the opening bracket
}
func (n *arrayVal) Range() hcl.Range {
return n.SrcRange
}
func (n *arrayVal) StartRange() hcl.Range {
return n.OpenRange
}
type booleanVal struct {
Value bool
SrcRange hcl.Range
}
func (n *booleanVal) Range() hcl.Range {
return n.SrcRange
}
func (n *booleanVal) StartRange() hcl.Range {
return n.SrcRange
}
type numberVal struct {
Value *big.Float
SrcRange hcl.Range
}
func (n *numberVal) Range() hcl.Range {
return n.SrcRange
}
func (n *numberVal) StartRange() hcl.Range {
return n.SrcRange
}
type stringVal struct {
Value string
SrcRange hcl.Range
}
func (n *stringVal) Range() hcl.Range {
return n.SrcRange
}
func (n *stringVal) StartRange() hcl.Range {
return n.SrcRange
}
type nullVal struct {
SrcRange hcl.Range
}
func (n *nullVal) Range() hcl.Range {
return n.SrcRange
}
func (n *nullVal) StartRange() hcl.Range {
return n.SrcRange
}
// invalidVal is used as a placeholder where a value is needed for a valid
// parse tree but the input was invalid enough to prevent one from being
// created.
type invalidVal struct {
SrcRange hcl.Range
}
func (n invalidVal) Range() hcl.Range {
return n.SrcRange
}
func (n invalidVal) StartRange() hcl.Range {
return n.SrcRange
}

View File

@ -1,4 +1,4 @@
// Package json is the JSON parser for ZCL. It parses JSON files and returns // Package json is the JSON parser for hcl. It parses JSON files and returns
// implementations of the core ZCL structural interfaces in terms of the // implementations of the core ZCL structural interfaces in terms of the
// JSON data inside. // JSON data inside.
// //

View File

@ -5,13 +5,13 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
func parseFileContent(buf []byte, filename string) (node, zcl.Diagnostics) { func parseFileContent(buf []byte, filename string) (node, hcl.Diagnostics) {
tokens := scan(buf, pos{ tokens := scan(buf, pos{
Filename: filename, Filename: filename,
Pos: zcl.Pos{ Pos: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
@ -20,8 +20,8 @@ func parseFileContent(buf []byte, filename string) (node, zcl.Diagnostics) {
p := newPeeker(tokens) p := newPeeker(tokens)
node, diags := parseValue(p) node, diags := parseValue(p)
if len(diags) == 0 && p.Peek().Type != tokenEOF { if len(diags) == 0 && p.Peek().Type != tokenEOF {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extraneous data after value", Summary: "Extraneous data after value",
Detail: "Extra characters appear after the JSON value.", Detail: "Extra characters appear after the JSON value.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -30,10 +30,10 @@ func parseFileContent(buf []byte, filename string) (node, zcl.Diagnostics) {
return node, diags return node, diags
} }
func parseValue(p *peeker) (node, zcl.Diagnostics) { func parseValue(p *peeker) (node, hcl.Diagnostics) {
tok := p.Peek() tok := p.Peek()
wrapInvalid := func(n node, diags zcl.Diagnostics) (node, zcl.Diagnostics) { wrapInvalid := func(n node, diags hcl.Diagnostics) (node, hcl.Diagnostics) {
if n != nil { if n != nil {
return n, diags return n, diags
} }
@ -52,36 +52,36 @@ func parseValue(p *peeker) (node, zcl.Diagnostics) {
case tokenKeyword: case tokenKeyword:
return wrapInvalid(parseKeyword(p)) return wrapInvalid(parseKeyword(p))
case tokenBraceC: case tokenBraceC:
return wrapInvalid(nil, zcl.Diagnostics{ return wrapInvalid(nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing attribute value", Summary: "Missing attribute value",
Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.", Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.",
Subject: &tok.Range, Subject: &tok.Range,
}, },
}) })
case tokenBrackC: case tokenBrackC:
return wrapInvalid(nil, zcl.Diagnostics{ return wrapInvalid(nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing array element value", Summary: "Missing array element value",
Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.", Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.",
Subject: &tok.Range, Subject: &tok.Range,
}, },
}) })
case tokenEOF: case tokenEOF:
return wrapInvalid(nil, zcl.Diagnostics{ return wrapInvalid(nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing value", Summary: "Missing value",
Detail: "The JSON data ends prematurely.", Detail: "The JSON data ends prematurely.",
Subject: &tok.Range, Subject: &tok.Range,
}, },
}) })
default: default:
return wrapInvalid(nil, zcl.Diagnostics{ return wrapInvalid(nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid start of value", Summary: "Invalid start of value",
Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.", Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.",
Subject: &tok.Range, Subject: &tok.Range,
@ -99,8 +99,8 @@ func tokenCanStartValue(tok token) bool {
} }
} }
func parseObject(p *peeker) (node, zcl.Diagnostics) { func parseObject(p *peeker) (node, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
open := p.Read() open := p.Read()
attrs := map[string]*objectAttr{} attrs := map[string]*objectAttr{}
@ -142,8 +142,8 @@ Token:
keyStrNode, ok := keyNode.(*stringVal) keyStrNode, ok := keyNode.(*stringVal)
if !ok { if !ok {
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid object attribute name", Summary: "Invalid object attribute name",
Detail: "A JSON object attribute name must be a string", Detail: "A JSON object attribute name must be a string",
Subject: keyNode.StartRange().Ptr(), Subject: keyNode.StartRange().Ptr(),
@ -159,8 +159,8 @@ Token:
if colon.Type == tokenBraceC || colon.Type == tokenComma { if colon.Type == tokenBraceC || colon.Type == tokenComma {
// Catch common mistake of using braces instead of brackets // Catch common mistake of using braces instead of brackets
// for an object. // for an object.
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing object value", Summary: "Missing object value",
Detail: "A JSON object attribute must have a value, introduced by a colon.", Detail: "A JSON object attribute must have a value, introduced by a colon.",
Subject: &colon.Range, Subject: &colon.Range,
@ -169,16 +169,16 @@ Token:
if colon.Type == tokenEquals { if colon.Type == tokenEquals {
// Possible confusion with native zcl syntax. // Possible confusion with native zcl syntax.
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing attribute value colon", Summary: "Missing attribute value colon",
Detail: "JSON uses a colon as its name/value delimiter, not an equals sign.", Detail: "JSON uses a colon as its name/value delimiter, not an equals sign.",
Subject: &colon.Range, Subject: &colon.Range,
}) })
} }
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing attribute value colon", Summary: "Missing attribute value colon",
Detail: "A colon must appear between an object attribute's name and its value.", Detail: "A colon must appear between an object attribute's name and its value.",
Subject: &colon.Range, Subject: &colon.Range,
@ -194,8 +194,8 @@ Token:
if existing := attrs[key]; existing != nil { if existing := attrs[key]; existing != nil {
// Generate a diagnostic for the duplicate key, but continue parsing // Generate a diagnostic for the duplicate key, but continue parsing
// anyway since this is a semantic error we can recover from. // anyway since this is a semantic error we can recover from.
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Duplicate JSON object property", Summary: "Duplicate JSON object property",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"An property named %q was previously introduced at %s", "An property named %q was previously introduced at %s",
@ -215,8 +215,8 @@ Token:
comma := p.Read() comma := p.Read()
if p.Peek().Type == tokenBraceC { if p.Peek().Type == tokenBraceC {
// Special error message for this common mistake // Special error message for this common mistake
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Trailing comma in object", Summary: "Trailing comma in object",
Detail: "JSON does not permit a trailing comma after the final attribute in an object.", Detail: "JSON does not permit a trailing comma after the final attribute in an object.",
Subject: &comma.Range, Subject: &comma.Range,
@ -224,8 +224,8 @@ Token:
} }
continue Token continue Token
case tokenEOF: case tokenEOF:
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unclosed object", Summary: "Unclosed object",
Detail: "No closing brace was found for this JSON object.", Detail: "No closing brace was found for this JSON object.",
Subject: &open.Range, Subject: &open.Range,
@ -234,8 +234,8 @@ Token:
// Consume the bracket anyway, so that we don't return with the peeker // Consume the bracket anyway, so that we don't return with the peeker
// at a strange place. // at a strange place.
p.Read() p.Read()
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Mismatched braces", Summary: "Mismatched braces",
Detail: "A JSON object must be closed with a brace, not a bracket.", Detail: "A JSON object must be closed with a brace, not a bracket.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -244,8 +244,8 @@ Token:
break Token break Token
default: default:
recover(p.Read()) recover(p.Read())
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing attribute seperator comma", Summary: "Missing attribute seperator comma",
Detail: "A comma must appear between each attribute declaration in an object.", Detail: "A comma must appear between each attribute declaration in an object.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -257,14 +257,14 @@ Token:
close := p.Read() close := p.Read()
return &objectVal{ return &objectVal{
Attrs: attrs, Attrs: attrs,
SrcRange: zcl.RangeBetween(open.Range, close.Range), SrcRange: hcl.RangeBetween(open.Range, close.Range),
OpenRange: open.Range, OpenRange: open.Range,
CloseRange: close.Range, CloseRange: close.Range,
}, diags }, diags
} }
func parseArray(p *peeker) (node, zcl.Diagnostics) { func parseArray(p *peeker) (node, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
open := p.Read() open := p.Read()
vals := []node{} vals := []node{}
@ -311,8 +311,8 @@ Token:
comma := p.Read() comma := p.Read()
if p.Peek().Type == tokenBrackC { if p.Peek().Type == tokenBrackC {
// Special error message for this common mistake // Special error message for this common mistake
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Trailing comma in array", Summary: "Trailing comma in array",
Detail: "JSON does not permit a trailing comma after the final attribute in an array.", Detail: "JSON does not permit a trailing comma after the final attribute in an array.",
Subject: &comma.Range, Subject: &comma.Range,
@ -321,24 +321,24 @@ Token:
continue Token continue Token
case tokenColon: case tokenColon:
recover(p.Read()) recover(p.Read())
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid array value", Summary: "Invalid array value",
Detail: "A colon is not used to introduce values in a JSON array.", Detail: "A colon is not used to introduce values in a JSON array.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
}) })
case tokenEOF: case tokenEOF:
recover(p.Read()) recover(p.Read())
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Unclosed object", Summary: "Unclosed object",
Detail: "No closing bracket was found for this JSON array.", Detail: "No closing bracket was found for this JSON array.",
Subject: &open.Range, Subject: &open.Range,
}) })
case tokenBraceC: case tokenBraceC:
recover(p.Read()) recover(p.Read())
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Mismatched brackets", Summary: "Mismatched brackets",
Detail: "A JSON array must be closed with a bracket, not a brace.", Detail: "A JSON array must be closed with a bracket, not a brace.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -347,8 +347,8 @@ Token:
break Token break Token
default: default:
recover(p.Read()) recover(p.Read())
return nil, diags.Append(&zcl.Diagnostic{ return nil, diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing attribute seperator comma", Summary: "Missing attribute seperator comma",
Detail: "A comma must appear between each value in an array.", Detail: "A comma must appear between each value in an array.",
Subject: p.Peek().Range.Ptr(), Subject: p.Peek().Range.Ptr(),
@ -360,12 +360,12 @@ Token:
close := p.Read() close := p.Read()
return &arrayVal{ return &arrayVal{
Values: vals, Values: vals,
SrcRange: zcl.RangeBetween(open.Range, close.Range), SrcRange: hcl.RangeBetween(open.Range, close.Range),
OpenRange: open.Range, OpenRange: open.Range,
}, diags }, diags
} }
func parseNumber(p *peeker) (node, zcl.Diagnostics) { func parseNumber(p *peeker) (node, hcl.Diagnostics) {
tok := p.Read() tok := p.Read()
// Use encoding/json to validate the number syntax. // Use encoding/json to validate the number syntax.
@ -373,9 +373,9 @@ func parseNumber(p *peeker) (node, zcl.Diagnostics) {
var num json.Number var num json.Number
err := json.Unmarshal(tok.Bytes, &num) err := json.Unmarshal(tok.Bytes, &num)
if err != nil { if err != nil {
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid JSON number", Summary: "Invalid JSON number",
Detail: fmt.Sprintf("There is a syntax error in the given JSON number."), Detail: fmt.Sprintf("There is a syntax error in the given JSON number."),
Subject: &tok.Range, Subject: &tok.Range,
@ -387,9 +387,9 @@ func parseNumber(p *peeker) (node, zcl.Diagnostics) {
if err != nil { if err != nil {
// Should never happen if above passed, since JSON numbers are a subset // Should never happen if above passed, since JSON numbers are a subset
// of what big.Float can parse... // of what big.Float can parse...
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid JSON number", Summary: "Invalid JSON number",
Detail: fmt.Sprintf("There is a syntax error in the given JSON number."), Detail: fmt.Sprintf("There is a syntax error in the given JSON number."),
Subject: &tok.Range, Subject: &tok.Range,
@ -403,13 +403,13 @@ func parseNumber(p *peeker) (node, zcl.Diagnostics) {
}, nil }, nil
} }
func parseString(p *peeker) (node, zcl.Diagnostics) { func parseString(p *peeker) (node, hcl.Diagnostics) {
tok := p.Read() tok := p.Read()
var str string var str string
err := json.Unmarshal(tok.Bytes, &str) err := json.Unmarshal(tok.Bytes, &str)
if err != nil { if err != nil {
var errRange zcl.Range var errRange hcl.Range
if serr, ok := err.(*json.SyntaxError); ok { if serr, ok := err.(*json.SyntaxError); ok {
errOfs := serr.Offset errOfs := serr.Offset
errPos := tok.Range.Start errPos := tok.Range.Start
@ -424,7 +424,7 @@ func parseString(p *peeker) (node, zcl.Diagnostics) {
errEndPos.Byte++ errEndPos.Byte++
errEndPos.Column++ errEndPos.Column++
errRange = zcl.Range{ errRange = hcl.Range{
Filename: tok.Range.Filename, Filename: tok.Range.Filename,
Start: errPos, Start: errPos,
End: errEndPos, End: errEndPos,
@ -433,7 +433,7 @@ func parseString(p *peeker) (node, zcl.Diagnostics) {
errRange = tok.Range errRange = tok.Range
} }
var contextRange *zcl.Range var contextRange *hcl.Range
if errRange != tok.Range { if errRange != tok.Range {
contextRange = &tok.Range contextRange = &tok.Range
} }
@ -441,9 +441,9 @@ func parseString(p *peeker) (node, zcl.Diagnostics) {
// FIXME: Eventually we should parse strings directly here so // FIXME: Eventually we should parse strings directly here so
// we can produce a more useful error message in the face fo things // we can produce a more useful error message in the face fo things
// such as invalid escapes, etc. // such as invalid escapes, etc.
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid JSON string", Summary: "Invalid JSON string",
Detail: fmt.Sprintf("There is a syntax error in the given JSON string."), Detail: fmt.Sprintf("There is a syntax error in the given JSON string."),
Subject: &errRange, Subject: &errRange,
@ -458,7 +458,7 @@ func parseString(p *peeker) (node, zcl.Diagnostics) {
}, nil }, nil
} }
func parseKeyword(p *peeker) (node, zcl.Diagnostics) { func parseKeyword(p *peeker) (node, hcl.Diagnostics) {
tok := p.Read() tok := p.Read()
s := string(tok.Bytes) s := string(tok.Bytes)
@ -478,9 +478,9 @@ func parseKeyword(p *peeker) (node, zcl.Diagnostics) {
SrcRange: tok.Range, SrcRange: tok.Range,
}, nil }, nil
case "undefined", "NaN", "Infinity": case "undefined", "NaN", "Infinity":
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid JSON keyword", Summary: "Invalid JSON keyword",
Detail: fmt.Sprintf("The JavaScript identifier %q cannot be used in JSON.", s), Detail: fmt.Sprintf("The JavaScript identifier %q cannot be used in JSON.", s),
Subject: &tok.Range, Subject: &tok.Range,
@ -492,9 +492,9 @@ func parseKeyword(p *peeker) (node, zcl.Diagnostics) {
dym = fmt.Sprintf(" Did you mean %q?", suggest) dym = fmt.Sprintf(" Did you mean %q?", suggest)
} }
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Invalid JSON keyword", Summary: "Invalid JSON keyword",
Detail: fmt.Sprintf("%q is not a valid JSON keyword.%s", s, dym), Detail: fmt.Sprintf("%q is not a valid JSON keyword.%s", s, dym),
Subject: &tok.Range, Subject: &tok.Range,

609
hcl/json/parser_test.go Normal file
View File

@ -0,0 +1,609 @@
package json
import (
"math/big"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/hcl"
)
func TestParse(t *testing.T) {
tests := []struct {
Input string
Want node
DiagCount int
}{
// Simple, single-token constructs
{
`true`,
&booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 5, Byte: 4},
},
},
0,
},
{
`false`,
&booleanVal{
Value: false,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
0,
},
{
`null`,
&nullVal{
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 5, Byte: 4},
},
},
0,
},
{
`undefined`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 10, Byte: 9},
}},
1,
},
{
`flase`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
}},
1,
},
{
`"hello"`,
&stringVal{
Value: "hello",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
},
},
0,
},
{
`"hello\nworld"`,
&stringVal{
Value: "hello\nworld",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
0,
},
{
`"hello \"world\""`,
&stringVal{
Value: `hello "world"`,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 18, Byte: 17},
},
},
0,
},
{
`"hello \\"`,
&stringVal{
Value: "hello \\",
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 11, Byte: 10},
},
},
0,
},
{
`"hello`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
}},
1,
},
{
`"he\llo"`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
}},
1,
},
{
`1`,
&numberVal{
Value: mustBigFloat("1"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
0,
},
{
`1.2`,
&numberVal{
Value: mustBigFloat("1.2"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
},
0,
},
{
`-1`,
&numberVal{
Value: mustBigFloat("-1"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
},
},
0,
},
{
`1.2e5`,
&numberVal{
Value: mustBigFloat("120000"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
0,
},
{
`1.2e+5`,
&numberVal{
Value: mustBigFloat("120000"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
},
0,
},
{
`1.2e-5`,
&numberVal{
Value: mustBigFloat("1.2e-5"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
},
0,
},
{
`.1`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
}},
1,
},
{
`+2`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
}},
1,
},
{
`1 2`,
&numberVal{
Value: mustBigFloat("1"),
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
1,
},
// Objects
{
`{"hello": true}`,
&objectVal{
Attrs: map[string]*objectAttr{
"hello": {
Name: "hello",
Value: &booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 16, Byte: 15},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
End: hcl.Pos{Line: 1, Column: 16, Byte: 15},
},
},
0,
},
{
`{"hello": true, "bye": false}`,
&objectVal{
Attrs: map[string]*objectAttr{
"hello": {
Name: "hello",
Value: &booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},
End: hcl.Pos{Line: 1, Column: 15, Byte: 14},
},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 9, Byte: 8},
},
},
"bye": {
Name: "bye",
Value: &booleanVal{
Value: false,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 24, Byte: 23},
End: hcl.Pos{Line: 1, Column: 29, Byte: 28},
},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 17, Byte: 16},
End: hcl.Pos{Line: 1, Column: 22, Byte: 21},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 30, Byte: 29},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 29, Byte: 28},
End: hcl.Pos{Line: 1, Column: 30, Byte: 29},
},
},
0,
},
{
`{}`,
&objectVal{
Attrs: map[string]*objectAttr{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
},
},
0,
},
{
`{"hello":true`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"hello":true]`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"hello":true,}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{true:false}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"hello": true, "hello": true}`,
&objectVal{
Attrs: map[string]*objectAttr{
"hello": {
Name: "hello",
Value: &booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 26, Byte: 25},
End: hcl.Pos{Line: 1, Column: 30, Byte: 29},
},
},
NameRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 17, Byte: 16},
End: hcl.Pos{Line: 1, Column: 24, Byte: 23},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 31, Byte: 30},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
CloseRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 30, Byte: 29},
End: hcl.Pos{Line: 1, Column: 31, Byte: 30},
},
},
1,
},
{
`{"hello": true, "hello": true, "hello", true}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
2,
},
{
`{"hello", "world"}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`[]`,
&arrayVal{
Values: []node{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
0,
},
{
`[true]`,
&arrayVal{
Values: []node{
&booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 7, Byte: 6},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
0,
},
{
`[true, false]`,
&arrayVal{
Values: []node{
&booleanVal{
Value: true,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
},
&booleanVal{
Value: false,
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
End: hcl.Pos{Line: 1, Column: 13, Byte: 12},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 14, Byte: 13},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
0,
},
{
`[[]]`,
&arrayVal{
Values: []node{
&arrayVal{
Values: []node{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 4, Byte: 3},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 5, Byte: 4},
},
OpenRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
},
},
0,
},
{
`[`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
2,
},
{
`[true`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`]`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`[true,]`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`[[],]`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`["hello":true]`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`[true}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"wrong"=true}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"wrong" = true}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
{
`{"wrong" true}`,
invalidVal{hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 2, Byte: 1},
}},
1,
},
}
for _, test := range tests {
t.Run(test.Input, func(t *testing.T) {
got, diag := parseFileContent([]byte(test.Input), "")
if len(diag) != test.DiagCount {
t.Errorf("got %d diagnostics; want %d", len(diag), test.DiagCount)
for _, d := range diag {
t.Logf(" - %s", d.Error())
}
}
if !reflect.DeepEqual(got, test.Want) {
t.Errorf(
"wrong result\ninput: %s\ngot: %s\nwant: %s",
test.Input, spew.Sdump(got), spew.Sdump(test.Want),
)
}
})
}
}
func mustBigFloat(s string) *big.Float {
f, _, err := (&big.Float{}).Parse(s, 10)
if err != nil {
panic(err)
}
return f
}

View File

@ -5,11 +5,11 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Parse attempts to parse the given buffer as JSON and, if successful, returns // Parse attempts to parse the given buffer as JSON and, if successful, returns
// a zcl.File for the zcl configuration represented by it. // a hcl.File for the zcl configuration represented by it.
// //
// This is not a generic JSON parser. Instead, it deals only with the profile // This is not a generic JSON parser. Instead, it deals only with the profile
// of JSON used to express zcl configuration. // of JSON used to express zcl configuration.
@ -17,11 +17,11 @@ import (
// The returned file is valid only if the returned diagnostics returns false // The returned file is valid only if the returned diagnostics returns false
// from its HasErrors method. If HasErrors returns true, the file represents // from its HasErrors method. If HasErrors returns true, the file represents
// the subset of data that was able to be parsed, which may be none. // the subset of data that was able to be parsed, which may be none.
func Parse(src []byte, filename string) (*zcl.File, zcl.Diagnostics) { func Parse(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {
rootNode, diags := parseFileContent(src, filename) rootNode, diags := parseFileContent(src, filename)
if _, ok := rootNode.(*objectVal); !ok { if _, ok := rootNode.(*objectVal); !ok {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Root value must be object", Summary: "Root value must be object",
Detail: "The root value in a JSON-based configuration must be a JSON object.", Detail: "The root value in a JSON-based configuration must be a JSON object.",
Subject: rootNode.StartRange().Ptr(), Subject: rootNode.StartRange().Ptr(),
@ -32,12 +32,12 @@ func Parse(src []byte, filename string) (*zcl.File, zcl.Diagnostics) {
// which will try to process the returned file even if we return // which will try to process the returned file even if we return
// diagnostics of severity error. This way, they'll get a file that // diagnostics of severity error. This way, they'll get a file that
// has an empty body rather than a body that panics when probed. // has an empty body rather than a body that panics when probed.
fakePos := zcl.Pos{ fakePos := hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
} }
fakeRange := zcl.Range{ fakeRange := hcl.Range{
Filename: filename, Filename: filename,
Start: fakePos, Start: fakePos,
End: fakePos, End: fakePos,
@ -48,7 +48,7 @@ func Parse(src []byte, filename string) (*zcl.File, zcl.Diagnostics) {
OpenRange: fakeRange, OpenRange: fakeRange,
} }
} }
file := &zcl.File{ file := &hcl.File{
Body: &body{ Body: &body{
obj: rootNode.(*objectVal), obj: rootNode.(*objectVal),
}, },
@ -62,12 +62,12 @@ func Parse(src []byte, filename string) (*zcl.File, zcl.Diagnostics) {
// data from the given filename, passing the result to Parse if successful. // data from the given filename, passing the result to Parse if successful.
// //
// If the file cannot be read, an error diagnostic with nil context is returned. // If the file cannot be read, an error diagnostic with nil context is returned.
func ParseFile(filename string) (*zcl.File, zcl.Diagnostics) { func ParseFile(filename string) (*hcl.File, hcl.Diagnostics) {
f, err := os.Open(filename) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Failed to open file", Summary: "Failed to open file",
Detail: fmt.Sprintf("The file %q could not be opened.", filename), Detail: fmt.Sprintf("The file %q could not be opened.", filename),
}, },
@ -77,9 +77,9 @@ func ParseFile(filename string) (*zcl.File, zcl.Diagnostics) {
src, err := ioutil.ReadAll(f) src, err := ioutil.ReadAll(f)
if err != nil { if err != nil {
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Failed to read file", Summary: "Failed to read file",
Detail: fmt.Sprintf("The file %q was opened, but an error occured while reading it.", filename), Detail: fmt.Sprintf("The file %q was opened, but an error occured while reading it.", filename),
}, },
@ -96,7 +96,7 @@ func ParseFile(filename string) (*zcl.File, zcl.Diagnostics) {
// This is intended for providing backward compatibility for applications that // This is intended for providing backward compatibility for applications that
// used to use HCL/HIL and thus had a JSON-based format with HIL // used to use HCL/HIL and thus had a JSON-based format with HIL
// interpolations. // interpolations.
func ParseWithHIL(src []byte, filename string) (*zcl.File, zcl.Diagnostics) { func ParseWithHIL(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {
file, diags := Parse(src, filename) file, diags := Parse(src, filename)
if file != nil && file.Body != nil { if file != nil && file.Body != nil {
file.Body.(*body).useHIL = true file.Body.(*body).useHIL = true
@ -106,7 +106,7 @@ func ParseWithHIL(src []byte, filename string) (*zcl.File, zcl.Diagnostics) {
// ParseFileWithHIL is like ParseWithHIL but it reads data from a file before // ParseFileWithHIL is like ParseWithHIL but it reads data from a file before
// parsing it. // parsing it.
func ParseFileWithHIL(filename string) (*zcl.File, zcl.Diagnostics) { func ParseFileWithHIL(filename string) (*hcl.File, hcl.Diagnostics) {
file, diags := ParseFile(filename) file, diags := ParseFile(filename)
if file != nil && file.Body != nil { if file != nil && file.Body != nil {
file.Body.(*body).useHIL = true file.Body.(*body).useHIL = true

View File

@ -3,7 +3,7 @@ package json
import ( import (
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -47,7 +47,7 @@ func TestParseTemplate(t *testing.T) {
} }
} }
val, diags := attrs["greeting"].Expr.Value(&zcl.EvalContext{}) val, diags := attrs["greeting"].Expr.Value(&hcl.EvalContext{})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("got %d diagnostics on eval; want 0", len(diags)) t.Errorf("got %d diagnostics on eval; want 0", len(diags))
for _, diag := range diags { for _, diag := range diags {
@ -83,7 +83,7 @@ func TestParseTemplateUnwrap(t *testing.T) {
} }
} }
val, diags := attrs["greeting"].Expr.Value(&zcl.EvalContext{}) val, diags := attrs["greeting"].Expr.Value(&hcl.EvalContext{})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("got %d diagnostics on eval; want 0", len(diags)) t.Errorf("got %d diagnostics on eval; want 0", len(diags))
for _, diag := range diags { for _, diag := range diags {
@ -113,7 +113,7 @@ func TestParseTemplateWithHIL(t *testing.T) {
t.Errorf("got %d diagnostics on decode; want 0", len(diags)) t.Errorf("got %d diagnostics on decode; want 0", len(diags))
} }
val, diags := attrs["greeting"].Expr.Value(&zcl.EvalContext{}) val, diags := attrs["greeting"].Expr.Value(&hcl.EvalContext{})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("got %d diagnostics on eval; want 0", len(diags)) t.Errorf("got %d diagnostics on eval; want 0", len(diags))
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/apparentlymart/go-textseg/textseg" "github.com/apparentlymart/go-textseg/textseg"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
//go:generate stringer -type tokenType scanner.go //go:generate stringer -type tokenType scanner.go
@ -28,7 +28,7 @@ const (
type token struct { type token struct {
Type tokenType Type tokenType
Bytes []byte Bytes []byte
Range zcl.Range Range hcl.Range
} }
// scan returns the primary tokens for the given JSON buffer in sequence. // scan returns the primary tokens for the given JSON buffer in sequence.
@ -265,23 +265,23 @@ Byte:
type pos struct { type pos struct {
Filename string Filename string
Pos zcl.Pos Pos hcl.Pos
} }
func (p *pos) Range(byteLen, charLen int) zcl.Range { func (p *pos) Range(byteLen, charLen int) hcl.Range {
start := p.Pos start := p.Pos
end := p.Pos end := p.Pos
end.Byte += byteLen end.Byte += byteLen
end.Column += charLen end.Column += charLen
return zcl.Range{ return hcl.Range{
Filename: p.Filename, Filename: p.Filename,
Start: start, Start: start,
End: end, End: end,
} }
} }
func posRange(start, end pos) zcl.Range { func posRange(start, end pos) hcl.Range {
return zcl.Range{ return hcl.Range{
Filename: start.Filename, Filename: start.Filename,
Start: start.Pos, Start: start.Pos,
End: end.Pos, End: end.Pos,

View File

@ -6,7 +6,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
func TestScan(t *testing.T) { func TestScan(t *testing.T) {
@ -19,13 +19,13 @@ func TestScan(t *testing.T) {
[]token{ []token{
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
@ -39,13 +39,13 @@ func TestScan(t *testing.T) {
[]token{ []token{
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -60,13 +60,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBraceO, Type: tokenBraceO,
Bytes: []byte(`{`), Bytes: []byte(`{`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -76,13 +76,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBraceC, Type: tokenBraceC,
Bytes: []byte(`}`), Bytes: []byte(`}`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -91,13 +91,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -112,13 +112,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBrackC, Type: tokenBrackC,
Bytes: []byte(`]`), Bytes: []byte(`]`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -128,13 +128,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBrackO, Type: tokenBrackO,
Bytes: []byte(`[`), Bytes: []byte(`[`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -143,13 +143,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -164,13 +164,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenColon, Type: tokenColon,
Bytes: []byte(`:`), Bytes: []byte(`:`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -180,13 +180,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenComma, Type: tokenComma,
Bytes: []byte(`,`), Bytes: []byte(`,`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -195,13 +195,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -216,13 +216,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`1`), Bytes: []byte(`1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -231,13 +231,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -252,13 +252,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`1`), Bytes: []byte(`1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -267,13 +267,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -288,13 +288,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`12`), Bytes: []byte(`12`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
@ -303,13 +303,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
@ -324,13 +324,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`1`), Bytes: []byte(`1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -340,13 +340,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`2`), Bytes: []byte(`2`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -355,13 +355,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -376,13 +376,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`1`), Bytes: []byte(`1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 2, Line: 2,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 2, Line: 2,
Column: 2, Column: 2,
@ -392,13 +392,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`2`), Bytes: []byte(`2`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 4, Byte: 4,
Line: 3, Line: 3,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 5, Byte: 5,
Line: 3, Line: 3,
Column: 3, Column: 3,
@ -407,13 +407,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 5, Byte: 5,
Line: 3, Line: 3,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 5, Byte: 5,
Line: 3, Line: 3,
Column: 3, Column: 3,
@ -428,13 +428,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`-1`), Bytes: []byte(`-1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -444,13 +444,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`2.5`), Bytes: []byte(`2.5`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 3, Byte: 3,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
@ -459,13 +459,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
@ -480,13 +480,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenKeyword, Type: tokenKeyword,
Bytes: []byte(`true`), Bytes: []byte(`true`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
@ -495,13 +495,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 4, Byte: 4,
Line: 1, Line: 1,
Column: 5, Column: 5,
@ -516,13 +516,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBrackO, Type: tokenBrackO,
Bytes: []byte(`[`), Bytes: []byte(`[`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
@ -532,13 +532,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenKeyword, Type: tokenKeyword,
Bytes: []byte(`true`), Bytes: []byte(`true`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 5, Byte: 5,
Line: 1, Line: 1,
Column: 6, Column: 6,
@ -548,13 +548,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenBrackC, Type: tokenBrackC,
Bytes: []byte(`]`), Bytes: []byte(`]`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 5, Byte: 5,
Line: 1, Line: 1,
Column: 6, Column: 6,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
@ -563,13 +563,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 6, Byte: 6,
Line: 1, Line: 1,
Column: 7, Column: 7,
@ -584,13 +584,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`""`), Bytes: []byte(`""`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -599,13 +599,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 2, Byte: 2,
Line: 1, Line: 1,
Column: 3, Column: 3,
@ -620,13 +620,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`"hello"`), Bytes: []byte(`"hello"`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 7, Byte: 7,
Line: 1, Line: 1,
Column: 8, Column: 8,
@ -635,13 +635,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 7, Byte: 7,
Line: 1, Line: 1,
Column: 8, Column: 8,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 7, Byte: 7,
Line: 1, Line: 1,
Column: 8, Column: 8,
@ -656,13 +656,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`"he\"llo"`), Bytes: []byte(`"he\"llo"`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 9, Byte: 9,
Line: 1, Line: 1,
Column: 10, Column: 10,
@ -671,13 +671,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 9, Byte: 9,
Line: 1, Line: 1,
Column: 10, Column: 10,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 9, Byte: 9,
Line: 1, Line: 1,
Column: 10, Column: 10,
@ -692,13 +692,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`"hello\\"`), Bytes: []byte(`"hello\\"`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 9, Byte: 9,
Line: 1, Line: 1,
Column: 10, Column: 10,
@ -708,13 +708,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenNumber, Type: tokenNumber,
Bytes: []byte(`1`), Bytes: []byte(`1`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 10, Byte: 10,
Line: 1, Line: 1,
Column: 11, Column: 11,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
@ -723,13 +723,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
@ -744,13 +744,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`"🇬🇧"`), Bytes: []byte(`"🇬🇧"`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 10, Byte: 10,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -759,13 +759,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 10, Byte: 10,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 10, Byte: 10,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -780,13 +780,13 @@ func TestScan(t *testing.T) {
{ {
Type: tokenString, Type: tokenString,
Bytes: []byte(`"á́́́́́́́"`), Bytes: []byte(`"á́́́́́́́"`),
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 19, Byte: 19,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -795,13 +795,13 @@ func TestScan(t *testing.T) {
}, },
{ {
Type: tokenEOF, Type: tokenEOF,
Range: zcl.Range{ Range: hcl.Range{
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 19, Byte: 19,
Line: 1, Line: 1,
Column: 4, Column: 4,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 19, Byte: 19,
Line: 1, Line: 1,
Column: 4, Column: 4,
@ -817,7 +817,7 @@ func TestScan(t *testing.T) {
buf := []byte(test.Input) buf := []byte(test.Input)
start := pos{ start := pos{
Filename: "", Filename: "",
Pos: zcl.Pos{ Pos: hcl.Pos{
Byte: 0, Byte: 0,
Line: 1, Line: 1,
Column: 1, Column: 1,

View File

@ -1,6 +1,6 @@
# zcl JSON Syntax Specification # zcl JSON Syntax Specification
This is the specification for the JSON serialization for zcl. zcl is a system This is the specification for the JSON serialization for hcl. zcl is a system
for defining configuration languages for applications. The zcl information for defining configuration languages for applications. The zcl information
model is designed to support multiple concrete syntaxes for configuration, model is designed to support multiple concrete syntaxes for configuration,
and this JSON-based format complements [the native syntax](../zclsyntax/spec.md) and this JSON-based format complements [the native syntax](../zclsyntax/spec.md)

View File

@ -3,8 +3,8 @@ package json
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -31,7 +31,7 @@ type expression struct {
src node src node
} }
func (b *body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostics) { func (b *body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
content, newBody, diags := b.PartialContent(schema) content, newBody, diags := b.PartialContent(schema)
hiddenAttrs := newBody.(*body).hiddenAttrs hiddenAttrs := newBody.(*body).hiddenAttrs
@ -63,8 +63,8 @@ func (b *body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostic
fixItHint = fmt.Sprintf(" Did you mean %q?", suggestion) fixItHint = fmt.Sprintf(" Did you mean %q?", suggestion)
} }
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extraneous JSON object property", Summary: "Extraneous JSON object property",
Detail: fmt.Sprintf("No attribute or block type is named %q.%s", k, fixItHint), Detail: fmt.Sprintf("No attribute or block type is named %q.%s", k, fixItHint),
Subject: &attr.NameRange, Subject: &attr.NameRange,
@ -76,7 +76,7 @@ func (b *body) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostic
return content, diags return content, diags
} }
func (b *body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Body, zcl.Diagnostics) { func (b *body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
obj := b.obj obj := b.obj
jsonAttrs := obj.Attrs jsonAttrs := obj.Attrs
@ -86,10 +86,10 @@ func (b *body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
usedNames[k] = struct{}{} usedNames[k] = struct{}{}
} }
} }
var diags zcl.Diagnostics var diags hcl.Diagnostics
content := &zcl.BodyContent{ content := &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: nil, Blocks: nil,
MissingItemRange: b.MissingItemRange(), MissingItemRange: b.MissingItemRange(),
@ -100,8 +100,8 @@ func (b *body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
_, used := usedNames[attrS.Name] _, used := usedNames[attrS.Name]
if used || !exists { if used || !exists {
if attrS.Required { if attrS.Required {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing required attribute", Summary: "Missing required attribute",
Detail: fmt.Sprintf("The attribute %q is required, so a JSON object property must be present with this name.", attrS.Name), Detail: fmt.Sprintf("The attribute %q is required, so a JSON object property must be present with this name.", attrS.Name),
Subject: &obj.OpenRange, Subject: &obj.OpenRange,
@ -109,10 +109,10 @@ func (b *body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
} }
continue continue
} }
content.Attributes[attrS.Name] = &zcl.Attribute{ content.Attributes[attrS.Name] = &hcl.Attribute{
Name: attrS.Name, Name: attrS.Name,
Expr: &expression{src: jsonAttr.Value}, Expr: &expression{src: jsonAttr.Value},
Range: zcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()), Range: hcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()),
NameRange: jsonAttr.NameRange, NameRange: jsonAttr.NameRange,
} }
usedNames[attrS.Name] = struct{}{} usedNames[attrS.Name] = struct{}{}
@ -141,8 +141,8 @@ func (b *body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
// JustAttributes for JSON bodies interprets all properties of the wrapped // JustAttributes for JSON bodies interprets all properties of the wrapped
// JSON object as attributes and returns them. // JSON object as attributes and returns them.
func (b *body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) { func (b *body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
attrs := make(map[string]*zcl.Attribute) attrs := make(map[string]*hcl.Attribute)
for name, jsonAttr := range b.obj.Attrs { for name, jsonAttr := range b.obj.Attrs {
if name == "//" { if name == "//" {
// Ignore "//" keys in objects representing bodies, to allow // Ignore "//" keys in objects representing bodies, to allow
@ -153,10 +153,10 @@ func (b *body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) {
if _, hidden := b.hiddenAttrs[name]; hidden { if _, hidden := b.hiddenAttrs[name]; hidden {
continue continue
} }
attrs[name] = &zcl.Attribute{ attrs[name] = &hcl.Attribute{
Name: name, Name: name,
Expr: &expression{src: jsonAttr.Value}, Expr: &expression{src: jsonAttr.Value},
Range: zcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()), Range: hcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()),
NameRange: jsonAttr.NameRange, NameRange: jsonAttr.NameRange,
} }
} }
@ -166,17 +166,17 @@ func (b *body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) {
return attrs, nil return attrs, nil
} }
func (b *body) MissingItemRange() zcl.Range { func (b *body) MissingItemRange() hcl.Range {
return b.obj.CloseRange return b.obj.CloseRange
} }
func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labelsLeft []string, labelsUsed []string, labelRanges []zcl.Range, blocks *zcl.Blocks) (diags zcl.Diagnostics) { func (b *body) unpackBlock(v node, typeName string, typeRange *hcl.Range, labelsLeft []string, labelsUsed []string, labelRanges []hcl.Range, blocks *hcl.Blocks) (diags hcl.Diagnostics) {
if len(labelsLeft) > 0 { if len(labelsLeft) > 0 {
labelName := labelsLeft[0] labelName := labelsLeft[0]
ov, ok := v.(*objectVal) ov, ok := v.(*objectVal)
if !ok { if !ok {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect JSON value type", Summary: "Incorrect JSON value type",
Detail: fmt.Sprintf("A JSON object is required, whose keys represent the %s block's %s.", typeName, labelName), Detail: fmt.Sprintf("A JSON object is required, whose keys represent the %s block's %s.", typeName, labelName),
Subject: v.StartRange().Ptr(), Subject: v.StartRange().Ptr(),
@ -184,8 +184,8 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
return return
} }
if len(ov.Attrs) == 0 { if len(ov.Attrs) == 0 {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing block label", Summary: "Missing block label",
Detail: fmt.Sprintf("At least one object property is required, whose name represents the %s block's %s.", typeName, labelName), Detail: fmt.Sprintf("At least one object property is required, whose name represents the %s block's %s.", typeName, labelName),
Subject: v.StartRange().Ptr(), Subject: v.StartRange().Ptr(),
@ -193,7 +193,7 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
return return
} }
labelsUsed := append(labelsUsed, "") labelsUsed := append(labelsUsed, "")
labelRanges := append(labelRanges, zcl.Range{}) labelRanges := append(labelRanges, hcl.Range{})
for pk, p := range ov.Attrs { for pk, p := range ov.Attrs {
labelsUsed[len(labelsUsed)-1] = pk labelsUsed[len(labelsUsed)-1] = pk
labelRanges[len(labelRanges)-1] = p.NameRange labelRanges[len(labelRanges)-1] = p.NameRange
@ -209,13 +209,13 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
// continue to be mutated after we return. // continue to be mutated after we return.
labels := make([]string, len(labelsUsed)) labels := make([]string, len(labelsUsed))
copy(labels, labelsUsed) copy(labels, labelsUsed)
labelR := make([]zcl.Range, len(labelRanges)) labelR := make([]hcl.Range, len(labelRanges))
copy(labelR, labelRanges) copy(labelR, labelRanges)
switch tv := v.(type) { switch tv := v.(type) {
case *objectVal: case *objectVal:
// Single instance of the block // Single instance of the block
*blocks = append(*blocks, &zcl.Block{ *blocks = append(*blocks, &hcl.Block{
Type: typeName, Type: typeName,
Labels: labels, Labels: labels,
Body: &body{ Body: &body{
@ -232,8 +232,8 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
for _, av := range tv.Values { for _, av := range tv.Values {
ov, ok := av.(*objectVal) ov, ok := av.(*objectVal)
if !ok { if !ok {
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect JSON value type", Summary: "Incorrect JSON value type",
Detail: fmt.Sprintf("A JSON object is required, representing the contents of a %q block.", typeName), Detail: fmt.Sprintf("A JSON object is required, representing the contents of a %q block.", typeName),
Subject: v.StartRange().Ptr(), Subject: v.StartRange().Ptr(),
@ -241,7 +241,7 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
continue continue
} }
*blocks = append(*blocks, &zcl.Block{ *blocks = append(*blocks, &hcl.Block{
Type: typeName, Type: typeName,
Labels: labels, Labels: labels,
Body: &body{ Body: &body{
@ -255,8 +255,8 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
}) })
} }
default: default:
diags = diags.Append(&zcl.Diagnostic{ diags = diags.Append(&hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect JSON value type", Summary: "Incorrect JSON value type",
Detail: fmt.Sprintf("Either a JSON object or a JSON array is required, representing the contents of one or more %q blocks.", typeName), Detail: fmt.Sprintf("Either a JSON object or a JSON array is required, representing the contents of one or more %q blocks.", typeName),
Subject: v.StartRange().Ptr(), Subject: v.StartRange().Ptr(),
@ -265,7 +265,7 @@ func (b *body) unpackBlock(v node, typeName string, typeRange *zcl.Range, labels
return return
} }
func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e *expression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
switch v := e.src.(type) { switch v := e.src.(type) {
case *stringVal: case *stringVal:
if ctx != nil { if ctx != nil {
@ -274,14 +274,14 @@ func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
// is how the caller specifies that interpolations are not allowed // is how the caller specifies that interpolations are not allowed
// and that the string should just be returned verbatim. // and that the string should just be returned verbatim.
templateSrc := v.Value templateSrc := v.Value
expr, diags := zclsyntax.ParseTemplate( expr, diags := hclsyntax.ParseTemplate(
[]byte(templateSrc), []byte(templateSrc),
v.SrcRange.Filename, v.SrcRange.Filename,
// This won't produce _exactly_ the right result, since // This won't produce _exactly_ the right result, since
// the zclsyntax parser can't "see" any escapes we removed // the zclsyntax parser can't "see" any escapes we removed
// while parsing JSON, but it's better than nothing. // while parsing JSON, but it's better than nothing.
zcl.Pos{ hcl.Pos{
Line: v.SrcRange.Start.Line, Line: v.SrcRange.Start.Line,
// skip over the opening quote mark // skip over the opening quote mark
@ -325,8 +325,8 @@ func (e *expression) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
} }
} }
func (e *expression) Variables() []zcl.Traversal { func (e *expression) Variables() []hcl.Traversal {
var vars []zcl.Traversal var vars []hcl.Traversal
switch v := e.src.(type) { switch v := e.src.(type) {
case *stringVal: case *stringVal:
@ -346,10 +346,10 @@ func (e *expression) Variables() []zcl.Traversal {
return vars return vars
} }
func (e *expression) Range() zcl.Range { func (e *expression) Range() hcl.Range {
return e.src.Range() return e.src.Range()
} }
func (e *expression) StartRange() zcl.Range { func (e *expression) StartRange() hcl.Range {
return e.src.StartRange() return e.src.StartRange()
} }

View File

@ -6,66 +6,66 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
func TestBodyPartialContent(t *testing.T) { func TestBodyPartialContent(t *testing.T) {
tests := []struct { tests := []struct {
src string src string
schema *zcl.BodySchema schema *hcl.BodySchema
want *zcl.BodyContent want *hcl.BodyContent
diagCount int diagCount int
}{ }{
{ {
`{}`, `{}`,
&zcl.BodySchema{}, &hcl.BodySchema{},
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 2, Byte: 1}, Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},
End: zcl.Pos{Line: 1, Column: 3, Byte: 2}, End: hcl.Pos{Line: 1, Column: 3, Byte: 2},
}, },
}, },
0, 0,
}, },
{ {
`{"//": "comment that should be ignored"}`, `{"//": "comment that should be ignored"}`,
&zcl.BodySchema{}, &hcl.BodySchema{},
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 40, Byte: 39}, Start: hcl.Pos{Line: 1, Column: 40, Byte: 39},
End: zcl.Pos{Line: 1, Column: 41, Byte: 40}, End: hcl.Pos{Line: 1, Column: 41, Byte: 40},
}, },
}, },
0, 0,
}, },
{ {
`{"name":"Ermintrude"}`, `{"name":"Ermintrude"}`,
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "name", Name: "name",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{ Attributes: map[string]*hcl.Attribute{
"name": &zcl.Attribute{ "name": &hcl.Attribute{
Name: "name", Name: "name",
Expr: &expression{ Expr: &expression{
src: &stringVal{ src: &stringVal{
Value: "Ermintrude", Value: "Ermintrude",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 8, Byte: 8,
Line: 1, Line: 1,
Column: 9, Column: 9,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 20, Byte: 20,
Line: 1, Line: 1,
Column: 21, Column: 21,
@ -73,27 +73,27 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
Range: zcl.Range{ Range: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 20, Byte: 20,
Line: 1, Line: 1,
Column: 21, Column: 21,
}, },
}, },
NameRange: zcl.Range{ NameRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 7, Byte: 7,
Line: 1, Line: 1,
Column: 8, Column: 8,
@ -101,18 +101,18 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 21, Byte: 20}, Start: hcl.Pos{Line: 1, Column: 21, Byte: 20},
End: zcl.Pos{Line: 1, Column: 22, Byte: 21}, End: hcl.Pos{Line: 1, Column: 22, Byte: 21},
}, },
}, },
0, 0,
}, },
{ {
`{"name":"Ermintrude"}`, `{"name":"Ermintrude"}`,
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "name", Name: "name",
Required: true, Required: true,
@ -123,21 +123,21 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{ Attributes: map[string]*hcl.Attribute{
"name": &zcl.Attribute{ "name": &hcl.Attribute{
Name: "name", Name: "name",
Expr: &expression{ Expr: &expression{
src: &stringVal{ src: &stringVal{
Value: "Ermintrude", Value: "Ermintrude",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 8, Byte: 8,
Line: 1, Line: 1,
Column: 9, Column: 9,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 20, Byte: 20,
Line: 1, Line: 1,
Column: 21, Column: 21,
@ -145,27 +145,27 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
Range: zcl.Range{ Range: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 20, Byte: 20,
Line: 1, Line: 1,
Column: 21, Column: 21,
}, },
}, },
NameRange: zcl.Range{ NameRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 7, Byte: 7,
Line: 1, Line: 1,
Column: 8, Column: 8,
@ -173,66 +173,66 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 21, Byte: 20}, Start: hcl.Pos{Line: 1, Column: 21, Byte: 20},
End: zcl.Pos{Line: 1, Column: 22, Byte: 21}, End: hcl.Pos{Line: 1, Column: 22, Byte: 21},
}, },
}, },
1, 1,
}, },
{ {
`{"resource":{}}`, `{"resource":{}}`,
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "resource", Type: "resource",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "resource", Type: "resource",
Labels: []string{}, Labels: []string{},
Body: &body{ Body: &body{
obj: &objectVal{ obj: &objectVal{
Attrs: map[string]*objectAttr{}, Attrs: map[string]*objectAttr{},
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 12, Byte: 12,
Line: 1, Line: 1,
Column: 13, Column: 13,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 14, Byte: 14,
Line: 1, Line: 1,
Column: 15, Column: 15,
}, },
}, },
OpenRange: zcl.Range{ OpenRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 12, Byte: 12,
Line: 1, Line: 1,
Column: 13, Column: 13,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
}, },
CloseRange: zcl.Range{ CloseRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 14, Byte: 14,
Line: 1, Line: 1,
Column: 15, Column: 15,
@ -241,95 +241,95 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
DefRange: zcl.Range{ DefRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 12, Byte: 12,
Line: 1, Line: 1,
Column: 13, Column: 13,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
}, },
TypeRange: zcl.Range{ TypeRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
}, },
}, },
LabelRanges: []zcl.Range{}, LabelRanges: []hcl.Range{},
}, },
}, },
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 15, Byte: 14}, Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
End: zcl.Pos{Line: 1, Column: 16, Byte: 15}, End: hcl.Pos{Line: 1, Column: 16, Byte: 15},
}, },
}, },
0, 0,
}, },
{ {
`{"resource":[{},{}]}`, `{"resource":[{},{}]}`,
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "resource", Type: "resource",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "resource", Type: "resource",
Labels: []string{}, Labels: []string{},
Body: &body{ Body: &body{
obj: &objectVal{ obj: &objectVal{
Attrs: map[string]*objectAttr{}, Attrs: map[string]*objectAttr{},
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 15, Byte: 15,
Line: 1, Line: 1,
Column: 16, Column: 16,
}, },
}, },
OpenRange: zcl.Range{ OpenRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 14, Byte: 14,
Line: 1, Line: 1,
Column: 15, Column: 15,
}, },
}, },
CloseRange: zcl.Range{ CloseRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 14, Byte: 14,
Line: 1, Line: 1,
Column: 15, Column: 15,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 15, Byte: 15,
Line: 1, Line: 1,
Column: 16, Column: 16,
@ -338,33 +338,33 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
DefRange: zcl.Range{ DefRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 12, Byte: 12,
Line: 1, Line: 1,
Column: 13, Column: 13,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
}, },
TypeRange: zcl.Range{ TypeRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
}, },
}, },
LabelRanges: []zcl.Range{}, LabelRanges: []hcl.Range{},
}, },
{ {
Type: "resource", Type: "resource",
@ -372,40 +372,40 @@ func TestBodyPartialContent(t *testing.T) {
Body: &body{ Body: &body{
obj: &objectVal{ obj: &objectVal{
Attrs: map[string]*objectAttr{}, Attrs: map[string]*objectAttr{},
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 16, Byte: 16,
Line: 1, Line: 1,
Column: 17, Column: 17,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 18, Byte: 18,
Line: 1, Line: 1,
Column: 19, Column: 19,
}, },
}, },
OpenRange: zcl.Range{ OpenRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 16, Byte: 16,
Line: 1, Line: 1,
Column: 17, Column: 17,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 17, Byte: 17,
Line: 1, Line: 1,
Column: 18, Column: 18,
}, },
}, },
CloseRange: zcl.Range{ CloseRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 17, Byte: 17,
Line: 1, Line: 1,
Column: 18, Column: 18,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 18, Byte: 18,
Line: 1, Line: 1,
Column: 19, Column: 19,
@ -414,96 +414,96 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
DefRange: zcl.Range{ DefRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 12, Byte: 12,
Line: 1, Line: 1,
Column: 13, Column: 13,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
}, },
TypeRange: zcl.Range{ TypeRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
}, },
}, },
LabelRanges: []zcl.Range{}, LabelRanges: []hcl.Range{},
}, },
}, },
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 20, Byte: 19}, Start: hcl.Pos{Line: 1, Column: 20, Byte: 19},
End: zcl.Pos{Line: 1, Column: 21, Byte: 20}, End: hcl.Pos{Line: 1, Column: 21, Byte: 20},
}, },
}, },
0, 0,
}, },
{ {
`{"resource":{"foo_instance":{"bar":{}}}}`, `{"resource":{"foo_instance":{"bar":{}}}}`,
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "resource", Type: "resource",
LabelNames: []string{"type", "name"}, LabelNames: []string{"type", "name"},
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "resource", Type: "resource",
Labels: []string{"foo_instance", "bar"}, Labels: []string{"foo_instance", "bar"},
Body: &body{ Body: &body{
obj: &objectVal{ obj: &objectVal{
Attrs: map[string]*objectAttr{}, Attrs: map[string]*objectAttr{},
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 35, Byte: 35,
Line: 1, Line: 1,
Column: 36, Column: 36,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 37, Byte: 37,
Line: 1, Line: 1,
Column: 38, Column: 38,
}, },
}, },
OpenRange: zcl.Range{ OpenRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 35, Byte: 35,
Line: 1, Line: 1,
Column: 36, Column: 36,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 36, Byte: 36,
Line: 1, Line: 1,
Column: 37, Column: 37,
}, },
}, },
CloseRange: zcl.Range{ CloseRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 36, Byte: 36,
Line: 1, Line: 1,
Column: 37, Column: 37,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 37, Byte: 37,
Line: 1, Line: 1,
Column: 38, Column: 38,
@ -512,41 +512,41 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
DefRange: zcl.Range{ DefRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 35, Byte: 35,
Line: 1, Line: 1,
Column: 36, Column: 36,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 36, Byte: 36,
Line: 1, Line: 1,
Column: 37, Column: 37,
}, },
}, },
TypeRange: zcl.Range{ TypeRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 1, Byte: 1,
Line: 1, Line: 1,
Column: 2, Column: 2,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 11, Byte: 11,
Line: 1, Line: 1,
Column: 12, Column: 12,
}, },
}, },
LabelRanges: []zcl.Range{ LabelRanges: []hcl.Range{
{ {
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 13, Byte: 13,
Line: 1, Line: 1,
Column: 14, Column: 14,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 27, Byte: 27,
Line: 1, Line: 1,
Column: 28, Column: 28,
@ -554,12 +554,12 @@ func TestBodyPartialContent(t *testing.T) {
}, },
{ {
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{ Start: hcl.Pos{
Byte: 29, Byte: 29,
Line: 1, Line: 1,
Column: 30, Column: 30,
}, },
End: zcl.Pos{ End: hcl.Pos{
Byte: 34, Byte: 34,
Line: 1, Line: 1,
Column: 35, Column: 35,
@ -568,29 +568,29 @@ func TestBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 40, Byte: 39}, Start: hcl.Pos{Line: 1, Column: 40, Byte: 39},
End: zcl.Pos{Line: 1, Column: 41, Byte: 40}, End: hcl.Pos{Line: 1, Column: 41, Byte: 40},
}, },
}, },
0, 0,
}, },
{ {
`{"name":"Ermintrude"}`, `{"name":"Ermintrude"}`,
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "name", Type: "name",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
MissingItemRange: zcl.Range{ MissingItemRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Line: 1, Column: 21, Byte: 20}, Start: hcl.Pos{Line: 1, Column: 21, Byte: 20},
End: zcl.Pos{Line: 1, Column: 22, Byte: 21}, End: hcl.Pos{Line: 1, Column: 22, Byte: 21},
}, },
}, },
1, 1,
@ -623,23 +623,23 @@ func TestBodyContent(t *testing.T) {
// this test focuses on the handling of extraneous attributes. // this test focuses on the handling of extraneous attributes.
tests := []struct { tests := []struct {
src string src string
schema *zcl.BodySchema schema *hcl.BodySchema
diagCount int diagCount int
}{ }{
{ {
`{"unknown": true}`, `{"unknown": true}`,
&zcl.BodySchema{}, &hcl.BodySchema{},
1, 1,
}, },
{ {
`{"//": "comment that should be ignored"}`, `{"//": "comment that should be ignored"}`,
&zcl.BodySchema{}, &hcl.BodySchema{},
0, 0,
}, },
{ {
`{"unknow": true}`, `{"unknow": true}`,
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "unknown", Name: "unknown",
}, },
@ -649,8 +649,8 @@ func TestBodyContent(t *testing.T) {
}, },
{ {
`{"unknow": true, "unnown": true}`, `{"unknow": true, "unnown": true}`,
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "unknown", Name: "unknown",
}, },
@ -682,43 +682,43 @@ func TestJustAttributes(t *testing.T) {
// this test focuses on the handling of extraneous attributes. // this test focuses on the handling of extraneous attributes.
tests := []struct { tests := []struct {
src string src string
want zcl.Attributes want hcl.Attributes
}{ }{
{ {
`{}`, `{}`,
map[string]*zcl.Attribute{}, map[string]*hcl.Attribute{},
}, },
{ {
`{"foo": true}`, `{"foo": true}`,
map[string]*zcl.Attribute{ map[string]*hcl.Attribute{
"foo": { "foo": {
Name: "foo", Name: "foo",
Expr: &expression{ Expr: &expression{
src: &booleanVal{ src: &booleanVal{
Value: true, Value: true,
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Byte: 8, Line: 1, Column: 9}, Start: hcl.Pos{Byte: 8, Line: 1, Column: 9},
End: zcl.Pos{Byte: 12, Line: 1, Column: 13}, End: hcl.Pos{Byte: 12, Line: 1, Column: 13},
}, },
}, },
}, },
Range: zcl.Range{ Range: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2}, Start: hcl.Pos{Byte: 1, Line: 1, Column: 2},
End: zcl.Pos{Byte: 12, Line: 1, Column: 13}, End: hcl.Pos{Byte: 12, Line: 1, Column: 13},
}, },
NameRange: zcl.Range{ NameRange: hcl.Range{
Filename: "test.json", Filename: "test.json",
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2}, Start: hcl.Pos{Byte: 1, Line: 1, Column: 2},
End: zcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7},
}, },
}, },
}, },
}, },
{ {
`{"//": "comment that should be ignored"}`, `{"//": "comment that should be ignored"}`,
map[string]*zcl.Attribute{}, map[string]*hcl.Attribute{},
}, },
} }

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import "fmt" import "fmt"

View File

@ -1,4 +1,4 @@
package zcl package hcl
// BlockHeaderSchema represents the shape of a block header, and is // BlockHeaderSchema represents the shape of a block header, and is
// used for matching blocks within bodies. // used for matching blocks within bodies.

View File

@ -1,7 +1,7 @@
# zcl Syntax-Agnostic Information Model # zcl Syntax-Agnostic Information Model
This is the specification for the general information model (abstract types and This is the specification for the general information model (abstract types and
semantics) for zcl. zcl is a system for defining configuration languages for semantics) for hcl. zcl is a system for defining configuration languages for
applications. The zcl information model is designed to support multiple applications. The zcl information model is designed to support multiple
concrete syntaxes for configuration, each with a mapping to the model defined concrete syntaxes for configuration, each with a mapping to the model defined
in this specification. in this specification.

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"

View File

@ -1,4 +1,4 @@
package zcl package hcl
import ( import (
"fmt" "fmt"

View File

@ -1,16 +1,16 @@
package hcldec package hcldec
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
func decode(body zcl.Body, block *zcl.Block, ctx *zcl.EvalContext, spec Spec, partial bool) (cty.Value, zcl.Body, zcl.Diagnostics) { func decode(body hcl.Body, block *hcl.Block, ctx *hcl.EvalContext, spec Spec, partial bool) (cty.Value, hcl.Body, hcl.Diagnostics) {
schema := ImpliedSchema(spec) schema := ImpliedSchema(spec)
var content *zcl.BodyContent var content *hcl.BodyContent
var diags zcl.Diagnostics var diags hcl.Diagnostics
var leftovers zcl.Body var leftovers hcl.Body
if partial { if partial {
content, leftovers, diags = body.PartialContent(schema) content, leftovers, diags = body.PartialContent(schema)
@ -24,7 +24,7 @@ func decode(body zcl.Body, block *zcl.Block, ctx *zcl.EvalContext, spec Spec, pa
return val, leftovers, diags return val, leftovers, diags
} }
func sourceRange(body zcl.Body, block *zcl.Block, spec Spec) zcl.Range { func sourceRange(body hcl.Body, block *hcl.Block, spec Spec) hcl.Range {
schema := ImpliedSchema(spec) schema := ImpliedSchema(spec)
content, _, _ := body.PartialContent(schema) content, _, _ := body.PartialContent(schema)

View File

@ -1,7 +1,7 @@
package hcldec package hcldec
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -11,7 +11,7 @@ import (
// //
// The ctx argument may be nil, in which case any references to variables or // The ctx argument may be nil, in which case any references to variables or
// functions will produce error diagnostics. // functions will produce error diagnostics.
func Decode(body zcl.Body, spec Spec, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
val, _, diags := decode(body, nil, ctx, spec, false) val, _, diags := decode(body, nil, ctx, spec, false)
return val, diags return val, diags
} }
@ -22,7 +22,7 @@ func Decode(body zcl.Body, spec Spec, ctx *zcl.EvalContext) (cty.Value, zcl.Diag
// //
// Any descendent block bodies are _not_ decoded partially and thus must // Any descendent block bodies are _not_ decoded partially and thus must
// be fully described by the given specification. // be fully described by the given specification.
func PartialDecode(body zcl.Body, spec Spec, ctx *zcl.EvalContext) (cty.Value, zcl.Body, zcl.Diagnostics) { func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics) {
return decode(body, nil, ctx, spec, true) return decode(body, nil, ctx, spec, true)
} }
@ -42,6 +42,6 @@ func PartialDecode(body zcl.Body, spec Spec, ctx *zcl.EvalContext) (cty.Value, z
// and may not actually be something ideal. It's expected that an application // and may not actually be something ideal. It's expected that an application
// will already have used Decode or PartialDecode earlier and thus had an // will already have used Decode or PartialDecode earlier and thus had an
// opportunity to detect and report spec violations. // opportunity to detect and report spec violations.
func SourceRange(body zcl.Body, spec Spec) zcl.Range { func SourceRange(body hcl.Body, spec Spec) hcl.Range {
return sourceRange(body, nil, spec) return sourceRange(body, nil, spec)
} }

View File

@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -14,7 +14,7 @@ func TestDecode(t *testing.T) {
tests := []struct { tests := []struct {
config string config string
spec Spec spec Spec
ctx *zcl.EvalContext ctx *hcl.EvalContext
want cty.Value want cty.Value
diagCount int diagCount int
}{ }{
@ -202,11 +202,11 @@ b {}
for i, test := range tests { for i, test := range tests {
t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) { t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) {
file, parseDiags := zclsyntax.ParseConfig([]byte(test.config), "", zcl.Pos{Line: 1, Column: 1, Byte: 0}) file, parseDiags := hclsyntax.ParseConfig([]byte(test.config), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
body := file.Body body := file.Body
got, valDiags := Decode(body, test.spec, test.ctx) got, valDiags := Decode(body, test.spec, test.ctx)
var diags zcl.Diagnostics var diags hcl.Diagnostics
diags = append(diags, parseDiags...) diags = append(diags, parseDiags...)
diags = append(diags, valDiags...) diags = append(diags, valDiags...)
@ -228,16 +228,16 @@ func TestSourceRange(t *testing.T) {
tests := []struct { tests := []struct {
config string config string
spec Spec spec Spec
want zcl.Range want hcl.Range
}{ }{
{ {
"a = 1\n", "a = 1\n",
&AttrSpec{ &AttrSpec{
Name: "a", Name: "a",
}, },
zcl.Range{ hcl.Range{
Start: zcl.Pos{Line: 1, Column: 5, Byte: 4}, Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: zcl.Pos{Line: 1, Column: 6, Byte: 5}, End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
}, },
}, },
{ {
@ -252,9 +252,9 @@ b {
Name: "a", Name: "a",
}, },
}, },
zcl.Range{ hcl.Range{
Start: zcl.Pos{Line: 3, Column: 7, Byte: 11}, Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},
End: zcl.Pos{Line: 3, Column: 8, Byte: 12}, End: hcl.Pos{Line: 3, Column: 8, Byte: 12},
}, },
}, },
{ {
@ -274,16 +274,16 @@ b {
}, },
}, },
}, },
zcl.Range{ hcl.Range{
Start: zcl.Pos{Line: 4, Column: 9, Byte: 19}, Start: hcl.Pos{Line: 4, Column: 9, Byte: 19},
End: zcl.Pos{Line: 4, Column: 10, Byte: 20}, End: hcl.Pos{Line: 4, Column: 10, Byte: 20},
}, },
}, },
} }
for i, test := range tests { for i, test := range tests {
t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) { t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) {
file, diags := zclsyntax.ParseConfig([]byte(test.config), "", zcl.Pos{Line: 1, Column: 1, Byte: 0}) file, diags := hclsyntax.ParseConfig([]byte(test.config), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), 0) t.Errorf("wrong number of diagnostics %d; want %d", len(diags), 0)
for _, diag := range diags { for _, diag := range diags {

View File

@ -1,15 +1,15 @@
package hcldec package hcldec
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// ImpliedSchema returns the *zcl.BodySchema implied by the given specification. // ImpliedSchema returns the *hcl.BodySchema implied by the given specification.
// This is the schema that the Decode function will use internally to // This is the schema that the Decode function will use internally to
// access the content of a given body. // access the content of a given body.
func ImpliedSchema(spec Spec) *zcl.BodySchema { func ImpliedSchema(spec Spec) *hcl.BodySchema {
var attrs []zcl.AttributeSchema var attrs []hcl.AttributeSchema
var blocks []zcl.BlockHeaderSchema var blocks []hcl.BlockHeaderSchema
// visitSameBodyChildren walks through the spec structure, calling // visitSameBodyChildren walks through the spec structure, calling
// the given callback for each descendent spec encountered. We are // the given callback for each descendent spec encountered. We are
@ -27,7 +27,7 @@ func ImpliedSchema(spec Spec) *zcl.BodySchema {
visit(spec) visit(spec)
spec.visitSameBodyChildren(visit) spec.visitSameBodyChildren(visit)
return &zcl.BodySchema{ return &hcl.BodySchema{
Attributes: attrs, Attributes: attrs,
Blocks: blocks, Blocks: blocks,
} }

View File

@ -3,12 +3,12 @@ package hcldec
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
) )
// A Spec is a description of how to decode a zcl.Body to a cty.Value. // A Spec is a description of how to decode a hcl.Body to a cty.Value.
// //
// The various other types in this package whose names end in "Spec" are // The various other types in this package whose names end in "Spec" are
// the spec implementations. The most common top-level spec is ObjectSpec, // the spec implementations. The most common top-level spec is ObjectSpec,
@ -19,7 +19,7 @@ type Spec interface {
// //
// "block" is provided only by the nested calls performed by the spec // "block" is provided only by the nested calls performed by the spec
// types that work on block bodies. // types that work on block bodies.
decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
// Call the given callback once for each of the nested specs that would // Call the given callback once for each of the nested specs that would
// get decoded with the same body and block as the receiver. This should // get decoded with the same body and block as the receiver. This should
@ -30,7 +30,7 @@ type Spec interface {
// spec in the given content, in the context of the given block // spec in the given content, in the context of the given block
// (which might be null). If the corresponding item is missing, return // (which might be null). If the corresponding item is missing, return
// a place where it might be inserted. // a place where it might be inserted.
sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range
} }
type visitFunc func(spec Spec) type visitFunc func(spec Spec)
@ -41,18 +41,18 @@ type ObjectSpec map[string]Spec
// attrSpec is implemented by specs that require attributes from the body. // attrSpec is implemented by specs that require attributes from the body.
type attrSpec interface { type attrSpec interface {
attrSchemata() []zcl.AttributeSchema attrSchemata() []hcl.AttributeSchema
} }
// blockSpec is implemented by specs that require blocks from the body. // blockSpec is implemented by specs that require blocks from the body.
type blockSpec interface { type blockSpec interface {
blockHeaderSchemata() []zcl.BlockHeaderSchema blockHeaderSchemata() []hcl.BlockHeaderSchema
} }
// specNeedingVariables is implemented by specs that can use variables // specNeedingVariables is implemented by specs that can use variables
// from the EvalContext, to declare which variables they need. // from the EvalContext, to declare which variables they need.
type specNeedingVariables interface { type specNeedingVariables interface {
variablesNeeded(content *zcl.BodyContent) []zcl.Traversal variablesNeeded(content *hcl.BodyContent) []hcl.Traversal
} }
func (s ObjectSpec) visitSameBodyChildren(cb visitFunc) { func (s ObjectSpec) visitSameBodyChildren(cb visitFunc) {
@ -61,12 +61,12 @@ func (s ObjectSpec) visitSameBodyChildren(cb visitFunc) {
} }
} }
func (s ObjectSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s ObjectSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
vals := make(map[string]cty.Value, len(s)) vals := make(map[string]cty.Value, len(s))
var diags zcl.Diagnostics var diags hcl.Diagnostics
for k, spec := range s { for k, spec := range s {
var kd zcl.Diagnostics var kd hcl.Diagnostics
vals[k], kd = spec.decode(content, block, ctx) vals[k], kd = spec.decode(content, block, ctx)
diags = append(diags, kd...) diags = append(diags, kd...)
} }
@ -74,7 +74,7 @@ func (s ObjectSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.
return cty.ObjectVal(vals), diags return cty.ObjectVal(vals), diags
} }
func (s ObjectSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s ObjectSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
if block != nil { if block != nil {
return block.DefRange return block.DefRange
} }
@ -95,12 +95,12 @@ func (s TupleSpec) visitSameBodyChildren(cb visitFunc) {
} }
} }
func (s TupleSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s TupleSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
vals := make([]cty.Value, len(s)) vals := make([]cty.Value, len(s))
var diags zcl.Diagnostics var diags hcl.Diagnostics
for i, spec := range s { for i, spec := range s {
var ed zcl.Diagnostics var ed hcl.Diagnostics
vals[i], ed = spec.decode(content, block, ctx) vals[i], ed = spec.decode(content, block, ctx)
diags = append(diags, ed...) diags = append(diags, ed...)
} }
@ -108,7 +108,7 @@ func (s TupleSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.E
return cty.TupleVal(vals), diags return cty.TupleVal(vals), diags
} }
func (s TupleSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s TupleSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
if block != nil { if block != nil {
return block.DefRange return block.DefRange
} }
@ -133,7 +133,7 @@ func (s *AttrSpec) visitSameBodyChildren(cb visitFunc) {
} }
// specNeedingVariables implementation // specNeedingVariables implementation
func (s *AttrSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal { func (s *AttrSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
attr, exists := content.Attributes[s.Name] attr, exists := content.Attributes[s.Name]
if !exists { if !exists {
return nil return nil
@ -143,8 +143,8 @@ func (s *AttrSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal {
} }
// attrSpec implementation // attrSpec implementation
func (s *AttrSpec) attrSchemata() []zcl.AttributeSchema { func (s *AttrSpec) attrSchemata() []hcl.AttributeSchema {
return []zcl.AttributeSchema{ return []hcl.AttributeSchema{
{ {
Name: s.Name, Name: s.Name,
Required: s.Required, Required: s.Required,
@ -152,7 +152,7 @@ func (s *AttrSpec) attrSchemata() []zcl.AttributeSchema {
} }
} }
func (s *AttrSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *AttrSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
attr, exists := content.Attributes[s.Name] attr, exists := content.Attributes[s.Name]
if !exists { if !exists {
return content.MissingItemRange return content.MissingItemRange
@ -161,7 +161,7 @@ func (s *AttrSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.R
return attr.Expr.Range() return attr.Expr.Range()
} }
func (s *AttrSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *AttrSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
attr, exists := content.Attributes[s.Name] attr, exists := content.Attributes[s.Name]
if !exists { if !exists {
// We don't need to check required and emit a diagnostic here, because // We don't need to check required and emit a diagnostic here, because
@ -173,15 +173,15 @@ func (s *AttrSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.E
convVal, err := convert.Convert(val, s.Type) convVal, err := convert.Convert(val, s.Type)
if err != nil { if err != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Incorrect attribute value type", Summary: "Incorrect attribute value type",
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Inappropriate value for attribute %q: %s.", "Inappropriate value for attribute %q: %s.",
s.Name, err.Error(), s.Name, err.Error(),
), ),
Subject: attr.Expr.StartRange().Ptr(), Subject: attr.Expr.StartRange().Ptr(),
Context: zcl.RangeBetween(attr.NameRange, attr.Expr.StartRange()).Ptr(), Context: hcl.RangeBetween(attr.NameRange, attr.Expr.StartRange()).Ptr(),
}) })
// We'll return an unknown value of the _correct_ type so that the // We'll return an unknown value of the _correct_ type so that the
// incomplete result can still be used for some analysis use-cases. // incomplete result can still be used for some analysis use-cases.
@ -203,14 +203,14 @@ func (s *LiteralSpec) visitSameBodyChildren(cb visitFunc) {
// leaf node // leaf node
} }
func (s *LiteralSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *LiteralSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return s.Value, nil return s.Value, nil
} }
func (s *LiteralSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *LiteralSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
// No sensible range to return for a literal, so the caller had better // No sensible range to return for a literal, so the caller had better
// ensure it doesn't cause any diagnostics. // ensure it doesn't cause any diagnostics.
return zcl.Range{ return hcl.Range{
Filename: "<unknown>", Filename: "<unknown>",
} }
} }
@ -218,7 +218,7 @@ func (s *LiteralSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zc
// An ExprSpec is a Spec that evaluates the given expression, ignoring the // An ExprSpec is a Spec that evaluates the given expression, ignoring the
// given body. // given body.
type ExprSpec struct { type ExprSpec struct {
Expr zcl.Expression Expr hcl.Expression
} }
func (s *ExprSpec) visitSameBodyChildren(cb visitFunc) { func (s *ExprSpec) visitSameBodyChildren(cb visitFunc) {
@ -226,15 +226,15 @@ func (s *ExprSpec) visitSameBodyChildren(cb visitFunc) {
} }
// specNeedingVariables implementation // specNeedingVariables implementation
func (s *ExprSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal { func (s *ExprSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
return s.Expr.Variables() return s.Expr.Variables()
} }
func (s *ExprSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *ExprSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return s.Expr.Value(ctx) return s.Expr.Value(ctx)
} }
func (s *ExprSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *ExprSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
return s.Expr.Range() return s.Expr.Range()
} }
@ -255,8 +255,8 @@ func (s *BlockSpec) visitSameBodyChildren(cb visitFunc) {
} }
// blockSpec implementation // blockSpec implementation
func (s *BlockSpec) blockHeaderSchemata() []zcl.BlockHeaderSchema { func (s *BlockSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
return []zcl.BlockHeaderSchema{ return []hcl.BlockHeaderSchema{
{ {
Type: s.TypeName, Type: s.TypeName,
}, },
@ -264,8 +264,8 @@ func (s *BlockSpec) blockHeaderSchemata() []zcl.BlockHeaderSchema {
} }
// specNeedingVariables implementation // specNeedingVariables implementation
func (s *BlockSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal { func (s *BlockSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
@ -282,18 +282,18 @@ func (s *BlockSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal {
return Variables(childBlock.Body, s.Nested) return Variables(childBlock.Body, s.Nested)
} }
func (s *BlockSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *BlockSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
} }
if childBlock != nil { if childBlock != nil {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Duplicate %s block", s.TypeName), Summary: fmt.Sprintf("Duplicate %s block", s.TypeName),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"Only one block of type %q is allowed. Previous definition was at %s.", "Only one block of type %q is allowed. Previous definition was at %s.",
@ -309,8 +309,8 @@ func (s *BlockSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.
if childBlock == nil { if childBlock == nil {
if s.Required { if s.Required {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("Missing %s block", s.TypeName), Summary: fmt.Sprintf("Missing %s block", s.TypeName),
Detail: fmt.Sprintf( Detail: fmt.Sprintf(
"A block of type %q is required here.", s.TypeName, "A block of type %q is required here.", s.TypeName,
@ -329,8 +329,8 @@ func (s *BlockSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.
return val, diags return val, diags
} }
func (s *BlockSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *BlockSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
@ -361,8 +361,8 @@ func (s *BlockListSpec) visitSameBodyChildren(cb visitFunc) {
} }
// blockSpec implementation // blockSpec implementation
func (s *BlockListSpec) blockHeaderSchemata() []zcl.BlockHeaderSchema { func (s *BlockListSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
return []zcl.BlockHeaderSchema{ return []hcl.BlockHeaderSchema{
{ {
Type: s.TypeName, Type: s.TypeName,
// FIXME: Need to peek into s.Nested to see if it has any // FIXME: Need to peek into s.Nested to see if it has any
@ -373,8 +373,8 @@ func (s *BlockListSpec) blockHeaderSchemata() []zcl.BlockHeaderSchema {
} }
// specNeedingVariables implementation // specNeedingVariables implementation
func (s *BlockListSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversal { func (s *BlockListSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
var ret []zcl.Traversal var ret []hcl.Traversal
for _, childBlock := range content.Blocks { for _, childBlock := range content.Blocks {
if childBlock.Type != s.TypeName { if childBlock.Type != s.TypeName {
@ -387,15 +387,15 @@ func (s *BlockListSpec) variablesNeeded(content *zcl.BodyContent) []zcl.Traversa
return ret return ret
} }
func (s *BlockListSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *BlockListSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
if s.Nested == nil { if s.Nested == nil {
panic("BlockSpec with no Nested Spec") panic("BlockSpec with no Nested Spec")
} }
var elems []cty.Value var elems []cty.Value
var sourceRanges []zcl.Range var sourceRanges []hcl.Range
for _, childBlock := range content.Blocks { for _, childBlock := range content.Blocks {
if childBlock.Type != s.TypeName { if childBlock.Type != s.TypeName {
continue continue
@ -408,15 +408,15 @@ func (s *BlockListSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *
} }
if len(elems) < s.MinItems { if len(elems) < s.MinItems {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("insufficient %s blocks", s.TypeName), Summary: fmt.Sprintf("insufficient %s blocks", s.TypeName),
Detail: fmt.Sprintf("at least %d blocks are required", s.MinItems), Detail: fmt.Sprintf("at least %d blocks are required", s.MinItems),
Subject: &content.MissingItemRange, Subject: &content.MissingItemRange,
}) })
} else if s.MaxItems > 0 && len(elems) > s.MaxItems { } else if s.MaxItems > 0 && len(elems) > s.MaxItems {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: fmt.Sprintf("too many %s blocks", s.TypeName), Summary: fmt.Sprintf("too many %s blocks", s.TypeName),
Detail: fmt.Sprintf("no more than %d blocks are allowed", s.MaxItems), Detail: fmt.Sprintf("no more than %d blocks are allowed", s.MaxItems),
Subject: &sourceRanges[s.MaxItems], Subject: &sourceRanges[s.MaxItems],
@ -436,11 +436,11 @@ func (s *BlockListSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *
return ret, diags return ret, diags
} }
func (s *BlockListSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *BlockListSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
// We return the source range of the _first_ block of the given type, // We return the source range of the _first_ block of the given type,
// since they are not guaranteed to form a contiguous range. // since they are not guaranteed to form a contiguous range.
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
@ -470,15 +470,15 @@ func (s *BlockSetSpec) visitSameBodyChildren(cb visitFunc) {
// leaf node ("Nested" does not use the same body) // leaf node ("Nested" does not use the same body)
} }
func (s *BlockSetSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *BlockSetSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
panic("BlockSetSpec.decode not yet implemented") panic("BlockSetSpec.decode not yet implemented")
} }
func (s *BlockSetSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *BlockSetSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
// We return the source range of the _first_ block of the given type, // We return the source range of the _first_ block of the given type,
// since they are not guaranteed to form a contiguous range. // since they are not guaranteed to form a contiguous range.
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
@ -510,15 +510,15 @@ func (s *BlockMapSpec) visitSameBodyChildren(cb visitFunc) {
// leaf node ("Nested" does not use the same body) // leaf node ("Nested" does not use the same body)
} }
func (s *BlockMapSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *BlockMapSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
panic("BlockMapSpec.decode not yet implemented") panic("BlockMapSpec.decode not yet implemented")
} }
func (s *BlockMapSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *BlockMapSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
// We return the source range of the _first_ block of the given type, // We return the source range of the _first_ block of the given type,
// since they are not guaranteed to form a contiguous range. // since they are not guaranteed to form a contiguous range.
var childBlock *zcl.Block var childBlock *hcl.Block
for _, candidate := range content.Blocks { for _, candidate := range content.Blocks {
if candidate.Type != s.TypeName { if candidate.Type != s.TypeName {
continue continue
@ -555,11 +555,11 @@ func (s *BlockLabelSpec) visitSameBodyChildren(cb visitFunc) {
// leaf node // leaf node
} }
func (s *BlockLabelSpec) decode(content *zcl.BodyContent, block *zcl.Block, ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (s *BlockLabelSpec) decode(content *hcl.BodyContent, block *hcl.Block, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
panic("BlockLabelSpec.decode not yet implemented") panic("BlockLabelSpec.decode not yet implemented")
} }
func (s *BlockLabelSpec) sourceRange(content *zcl.BodyContent, block *zcl.Block) zcl.Range { func (s *BlockLabelSpec) sourceRange(content *hcl.BodyContent, block *hcl.Block) hcl.Range {
if block == nil { if block == nil {
panic("BlockListSpec used in non-block context") panic("BlockListSpec used in non-block context")
} }

View File

@ -1,7 +1,7 @@
package hcldec package hcldec
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
// Variables processes the given body with the given spec and returns a // Variables processes the given body with the given spec and returns a
@ -14,12 +14,12 @@ import (
// If the given body is not compliant with the given schema, the result may // If the given body is not compliant with the given schema, the result may
// be incomplete, but that's assumed to be okay because the eventual call // be incomplete, but that's assumed to be okay because the eventual call
// to Decode will produce error diagnostics anyway. // to Decode will produce error diagnostics anyway.
func Variables(body zcl.Body, spec Spec) []zcl.Traversal { func Variables(body hcl.Body, spec Spec) []hcl.Traversal {
schema := ImpliedSchema(spec) schema := ImpliedSchema(spec)
content, _, _ := body.PartialContent(schema) content, _, _ := body.PartialContent(schema)
var vars []zcl.Traversal var vars []hcl.Traversal
if vs, ok := spec.(specNeedingVariables); ok { if vs, ok := spec.(specNeedingVariables); ok {
vars = append(vars, vs.variablesNeeded(content)...) vars = append(vars, vs.variablesNeeded(content)...)

View File

@ -5,15 +5,15 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
) )
func TestVariables(t *testing.T) { func TestVariables(t *testing.T) {
tests := []struct { tests := []struct {
config string config string
spec Spec spec Spec
want []zcl.Traversal want []hcl.Traversal
}{ }{
{ {
``, ``,
@ -30,13 +30,13 @@ func TestVariables(t *testing.T) {
&AttrSpec{ &AttrSpec{
Name: "a", Name: "a",
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Start: zcl.Pos{Line: 1, Column: 5, Byte: 4}, Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: zcl.Pos{Line: 1, Column: 8, Byte: 7}, End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
}, },
}, },
}, },
@ -49,13 +49,13 @@ func TestVariables(t *testing.T) {
Name: "a", Name: "a",
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Start: zcl.Pos{Line: 1, Column: 5, Byte: 4}, Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},
End: zcl.Pos{Line: 1, Column: 8, Byte: 7}, End: hcl.Pos{Line: 1, Column: 8, Byte: 7},
}, },
}, },
}, },
@ -73,13 +73,13 @@ b {
Name: "a", Name: "a",
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Start: zcl.Pos{Line: 3, Column: 7, Byte: 11}, Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},
End: zcl.Pos{Line: 3, Column: 10, Byte: 14}, End: hcl.Pos{Line: 3, Column: 10, Byte: 14},
}, },
}, },
}, },
@ -103,22 +103,22 @@ c {
Name: "a", Name: "a",
}, },
}, },
[]zcl.Traversal{ []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "foo", Name: "foo",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Start: zcl.Pos{Line: 3, Column: 7, Byte: 11}, Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},
End: zcl.Pos{Line: 3, Column: 10, Byte: 14}, End: hcl.Pos{Line: 3, Column: 10, Byte: 14},
}, },
}, },
}, },
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: "bar", Name: "bar",
SrcRange: zcl.Range{ SrcRange: hcl.Range{
Start: zcl.Pos{Line: 6, Column: 7, Byte: 27}, Start: hcl.Pos{Line: 6, Column: 7, Byte: 27},
End: zcl.Pos{Line: 6, Column: 10, Byte: 30}, End: hcl.Pos{Line: 6, Column: 10, Byte: 30},
}, },
}, },
}, },
@ -128,7 +128,7 @@ c {
for i, test := range tests { for i, test := range tests {
t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) { t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) {
file, diags := zclsyntax.ParseConfig([]byte(test.config), "", zcl.Pos{Line: 1, Column: 1, Byte: 0}) file, diags := hclsyntax.ParseConfig([]byte(test.config), "", hcl.Pos{Line: 1, Column: 1, Byte: 0})
if len(diags) != 0 { if len(diags) != 0 {
t.Errorf("wrong number of diagnostics from ParseConfig %d; want %d", len(diags), 0) t.Errorf("wrong number of diagnostics from ParseConfig %d; want %d", len(diags), 0)
for _, diag := range diags { for _, diag := range diags {

View File

@ -1,7 +1,7 @@
package hcled package hcled
import ( import (
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
) )
type contextStringer interface { type contextStringer interface {
@ -12,7 +12,7 @@ type contextStringer interface {
// offset, if available. An empty string is returned if no such information // offset, if available. An empty string is returned if no such information
// is available, or otherwise the returned string is in a form that depends // is available, or otherwise the returned string is in a form that depends
// on the language used to write the referenced file. // on the language used to write the referenced file.
func ContextString(file *zcl.File, offset int) string { func ContextString(file *hcl.File, offset int) string {
if cser, ok := file.Nav.(contextStringer); ok { if cser, ok := file.Nav.(contextStringer); ok {
return cser.ContextString(offset) return cser.ContextString(offset)
} }

View File

@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/json" "github.com/hashicorp/hcl2/hcl/json"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
) )
// NOTE: This is the public interface for parsing. The actual parsers are // NOTE: This is the public interface for parsing. The actual parsers are
@ -24,25 +24,25 @@ import (
// and present them together, so returning diagnostics for the same file // and present them together, so returning diagnostics for the same file
// multiple times would create a confusing result. // multiple times would create a confusing result.
type Parser struct { type Parser struct {
files map[string]*zcl.File files map[string]*hcl.File
} }
// NewParser creates a new parser, ready to parse configuration files. // NewParser creates a new parser, ready to parse configuration files.
func NewParser() *Parser { func NewParser() *Parser {
return &Parser{ return &Parser{
files: map[string]*zcl.File{}, files: map[string]*hcl.File{},
} }
} }
// ParseZCL parses the given buffer (which is assumed to have been loaded from // ParseZCL parses the given buffer (which is assumed to have been loaded from
// the given filename) as a native-syntax configuration file and returns the // the given filename) as a native-syntax configuration file and returns the
// zcl.File object representing it. // hcl.File object representing it.
func (p *Parser) ParseZCL(src []byte, filename string) (*zcl.File, zcl.Diagnostics) { func (p *Parser) ParseZCL(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {
if existing := p.files[filename]; existing != nil { if existing := p.files[filename]; existing != nil {
return existing, nil return existing, nil
} }
file, diags := zclsyntax.ParseConfig(src, filename, zcl.Pos{Byte: 0, Line: 1, Column: 1}) file, diags := hclsyntax.ParseConfig(src, filename, hcl.Pos{Byte: 0, Line: 1, Column: 1})
p.files[filename] = file p.files[filename] = file
return file, diags return file, diags
} }
@ -50,16 +50,16 @@ func (p *Parser) ParseZCL(src []byte, filename string) (*zcl.File, zcl.Diagnosti
// ParseZCLFile reads the given filename and parses it as a native-syntax zcl // ParseZCLFile reads the given filename and parses it as a native-syntax zcl
// configuration file. An error diagnostic is returned if the given file // configuration file. An error diagnostic is returned if the given file
// cannot be read. // cannot be read.
func (p *Parser) ParseZCLFile(filename string) (*zcl.File, zcl.Diagnostics) { func (p *Parser) ParseZCLFile(filename string) (*hcl.File, hcl.Diagnostics) {
if existing := p.files[filename]; existing != nil { if existing := p.files[filename]; existing != nil {
return existing, nil return existing, nil
} }
src, err := ioutil.ReadFile(filename) src, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, zcl.Diagnostics{ return nil, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Failed to read file", Summary: "Failed to read file",
Detail: fmt.Sprintf("The configuration file %q could not be read.", filename), Detail: fmt.Sprintf("The configuration file %q could not be read.", filename),
}, },
@ -70,8 +70,8 @@ func (p *Parser) ParseZCLFile(filename string) (*zcl.File, zcl.Diagnostics) {
} }
// ParseJSON parses the given JSON buffer (which is assumed to have been loaded // ParseJSON parses the given JSON buffer (which is assumed to have been loaded
// from the given filename) and returns the zcl.File object representing it. // from the given filename) and returns the hcl.File object representing it.
func (p *Parser) ParseJSON(src []byte, filename string) (*zcl.File, zcl.Diagnostics) { func (p *Parser) ParseJSON(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {
if existing := p.files[filename]; existing != nil { if existing := p.files[filename]; existing != nil {
return existing, nil return existing, nil
} }
@ -83,7 +83,7 @@ func (p *Parser) ParseJSON(src []byte, filename string) (*zcl.File, zcl.Diagnost
// ParseJSONFile reads the given filename and parses it as JSON, similarly to // ParseJSONFile reads the given filename and parses it as JSON, similarly to
// ParseJSON. An error diagnostic is returned if the given file cannot be read. // ParseJSON. An error diagnostic is returned if the given file cannot be read.
func (p *Parser) ParseJSONFile(filename string) (*zcl.File, zcl.Diagnostics) { func (p *Parser) ParseJSONFile(filename string) (*hcl.File, hcl.Diagnostics) {
if existing := p.files[filename]; existing != nil { if existing := p.files[filename]; existing != nil {
return existing, nil return existing, nil
} }
@ -95,7 +95,7 @@ func (p *Parser) ParseJSONFile(filename string) (*zcl.File, zcl.Diagnostics) {
// AddFile allows a caller to record in a parser a file that was parsed some // AddFile allows a caller to record in a parser a file that was parsed some
// other way, thus allowing it to be included in the registry of sources. // other way, thus allowing it to be included in the registry of sources.
func (p *Parser) AddFile(filename string, file *zcl.File) { func (p *Parser) AddFile(filename string, file *hcl.File) {
p.files[filename] = file p.files[filename] = file
} }
@ -118,6 +118,6 @@ func (p *Parser) Sources() map[string][]byte {
// //
// The returned map and all of the objects it refers to directly or indirectly // The returned map and all of the objects it refers to directly or indirectly
// must not be modified. // must not be modified.
func (p *Parser) Files() map[string]*zcl.File { func (p *Parser) Files() map[string]*hcl.File {
return p.files return p.files
} }

View File

@ -3,35 +3,35 @@ package hcltest
import ( import (
"fmt" "fmt"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
// MockBody returns a zcl.Body implementation that works in terms of a // MockBody returns a hcl.Body implementation that works in terms of a
// caller-constructed zcl.BodyContent, thus avoiding the need to parse // caller-constructed hcl.BodyContent, thus avoiding the need to parse
// a "real" zcl config file to use as input to a test. // a "real" zcl config file to use as input to a test.
func MockBody(content *zcl.BodyContent) zcl.Body { func MockBody(content *hcl.BodyContent) hcl.Body {
return mockBody{content} return mockBody{content}
} }
type mockBody struct { type mockBody struct {
C *zcl.BodyContent C *hcl.BodyContent
} }
func (b mockBody) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnostics) { func (b mockBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
content, remainI, diags := b.PartialContent(schema) content, remainI, diags := b.PartialContent(schema)
remain := remainI.(mockBody) remain := remainI.(mockBody)
for _, attr := range remain.C.Attributes { for _, attr := range remain.C.Attributes {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extraneous attribute in mock body", Summary: "Extraneous attribute in mock body",
Detail: fmt.Sprintf("Mock body has extraneous attribute %q.", attr.Name), Detail: fmt.Sprintf("Mock body has extraneous attribute %q.", attr.Name),
Subject: &attr.NameRange, Subject: &attr.NameRange,
}) })
} }
for _, block := range remain.C.Blocks { for _, block := range remain.C.Blocks {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Extraneous block in mock body", Summary: "Extraneous block in mock body",
Detail: fmt.Sprintf("Mock body has extraneous block of type %q.", block.Type), Detail: fmt.Sprintf("Mock body has extraneous block of type %q.", block.Type),
Subject: &block.DefRange, Subject: &block.DefRange,
@ -40,18 +40,18 @@ func (b mockBody) Content(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Diagnos
return content, diags return content, diags
} }
func (b mockBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Body, zcl.Diagnostics) { func (b mockBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
ret := &zcl.BodyContent{ ret := &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: []*zcl.Block{}, Blocks: []*hcl.Block{},
MissingItemRange: b.C.MissingItemRange, MissingItemRange: b.C.MissingItemRange,
} }
remain := &zcl.BodyContent{ remain := &hcl.BodyContent{
Attributes: map[string]*zcl.Attribute{}, Attributes: map[string]*hcl.Attribute{},
Blocks: []*zcl.Block{}, Blocks: []*hcl.Block{},
MissingItemRange: b.C.MissingItemRange, MissingItemRange: b.C.MissingItemRange,
} }
var diags zcl.Diagnostics var diags hcl.Diagnostics
if len(schema.Attributes) != 0 { if len(schema.Attributes) != 0 {
for _, attrS := range schema.Attributes { for _, attrS := range schema.Attributes {
@ -59,8 +59,8 @@ func (b mockBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.
attr, ok := b.C.Attributes[name] attr, ok := b.C.Attributes[name]
if !ok { if !ok {
if attrS.Required { if attrS.Required {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Missing required attribute", Summary: "Missing required attribute",
Detail: fmt.Sprintf("Mock body doesn't have attribute %q", name), Detail: fmt.Sprintf("Mock body doesn't have attribute %q", name),
Subject: b.C.MissingItemRange.Ptr(), Subject: b.C.MissingItemRange.Ptr(),
@ -78,7 +78,7 @@ func (b mockBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.
} }
} }
wantedBlocks := map[string]zcl.BlockHeaderSchema{} wantedBlocks := map[string]hcl.BlockHeaderSchema{}
for _, blockS := range schema.Blocks { for _, blockS := range schema.Blocks {
wantedBlocks[blockS.Type] = blockS wantedBlocks[blockS.Type] = blockS
} }
@ -86,8 +86,8 @@ func (b mockBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.
for _, block := range b.C.Blocks { for _, block := range b.C.Blocks {
if blockS, ok := wantedBlocks[block.Type]; ok { if blockS, ok := wantedBlocks[block.Type]; ok {
if len(block.Labels) != len(blockS.LabelNames) { if len(block.Labels) != len(blockS.LabelNames) {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Wrong number of block labels", Summary: "Wrong number of block labels",
Detail: fmt.Sprintf("Block of type %q requires %d labels, but got %d", blockS.Type, len(blockS.LabelNames), len(block.Labels)), Detail: fmt.Sprintf("Block of type %q requires %d labels, but got %d", blockS.Type, len(blockS.LabelNames), len(block.Labels)),
Subject: b.C.MissingItemRange.Ptr(), Subject: b.C.MissingItemRange.Ptr(),
@ -103,11 +103,11 @@ func (b mockBody) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.
return ret, mockBody{remain}, diags return ret, mockBody{remain}, diags
} }
func (b mockBody) JustAttributes() (zcl.Attributes, zcl.Diagnostics) { func (b mockBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
var diags zcl.Diagnostics var diags hcl.Diagnostics
if len(b.C.Blocks) != 0 { if len(b.C.Blocks) != 0 {
diags = append(diags, &zcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Mock body has blocks", Summary: "Mock body has blocks",
Detail: "Can't use JustAttributes on a mock body with blocks.", Detail: "Can't use JustAttributes on a mock body with blocks.",
Subject: b.C.MissingItemRange.Ptr(), Subject: b.C.MissingItemRange.Ptr(),
@ -117,13 +117,13 @@ func (b mockBody) JustAttributes() (zcl.Attributes, zcl.Diagnostics) {
return b.C.Attributes, diags return b.C.Attributes, diags
} }
func (b mockBody) MissingItemRange() zcl.Range { func (b mockBody) MissingItemRange() hcl.Range {
return b.C.MissingItemRange return b.C.MissingItemRange
} }
// MockExprLiteral returns a zcl.Expression that evaluates to the given literal // MockExprLiteral returns a hcl.Expression that evaluates to the given literal
// value. // value.
func MockExprLiteral(val cty.Value) zcl.Expression { func MockExprLiteral(val cty.Value) hcl.Expression {
return mockExprLiteral{val} return mockExprLiteral{val}
} }
@ -131,33 +131,33 @@ type mockExprLiteral struct {
V cty.Value V cty.Value
} }
func (e mockExprLiteral) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e mockExprLiteral) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return e.V, nil return e.V, nil
} }
func (e mockExprLiteral) Variables() []zcl.Traversal { func (e mockExprLiteral) Variables() []hcl.Traversal {
return nil return nil
} }
func (e mockExprLiteral) Range() zcl.Range { func (e mockExprLiteral) Range() hcl.Range {
return zcl.Range{ return hcl.Range{
Filename: "MockExprLiteral", Filename: "MockExprLiteral",
} }
} }
func (e mockExprLiteral) StartRange() zcl.Range { func (e mockExprLiteral) StartRange() hcl.Range {
return e.Range() return e.Range()
} }
// MockExprVariable returns a zcl.Expression that evaluates to the value of // MockExprVariable returns a hcl.Expression that evaluates to the value of
// the variable with the given name. // the variable with the given name.
func MockExprVariable(name string) zcl.Expression { func MockExprVariable(name string) hcl.Expression {
return mockExprVariable(name) return mockExprVariable(name)
} }
type mockExprVariable string type mockExprVariable string
func (e mockExprVariable) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) { func (e mockExprVariable) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
name := string(e) name := string(e)
for ctx != nil { for ctx != nil {
if val, ok := ctx.Variables[name]; ok { if val, ok := ctx.Variables[name]; ok {
@ -167,19 +167,19 @@ func (e mockExprVariable) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostic
} }
// If we fall out here then there is no variable with the given name // If we fall out here then there is no variable with the given name
return cty.DynamicVal, zcl.Diagnostics{ return cty.DynamicVal, hcl.Diagnostics{
{ {
Severity: zcl.DiagError, Severity: hcl.DiagError,
Summary: "Reference to undefined variable", Summary: "Reference to undefined variable",
Detail: fmt.Sprintf("Variable %q is not defined.", name), Detail: fmt.Sprintf("Variable %q is not defined.", name),
}, },
} }
} }
func (e mockExprVariable) Variables() []zcl.Traversal { func (e mockExprVariable) Variables() []hcl.Traversal {
return []zcl.Traversal{ return []hcl.Traversal{
{ {
zcl.TraverseRoot{ hcl.TraverseRoot{
Name: string(e), Name: string(e),
SrcRange: e.Range(), SrcRange: e.Range(),
}, },
@ -187,31 +187,31 @@ func (e mockExprVariable) Variables() []zcl.Traversal {
} }
} }
func (e mockExprVariable) Range() zcl.Range { func (e mockExprVariable) Range() hcl.Range {
return zcl.Range{ return hcl.Range{
Filename: "MockExprVariable", Filename: "MockExprVariable",
} }
} }
func (e mockExprVariable) StartRange() zcl.Range { func (e mockExprVariable) StartRange() hcl.Range {
return e.Range() return e.Range()
} }
// MockAttrs constructs and returns a zcl.Attributes map with attributes // MockAttrs constructs and returns a hcl.Attributes map with attributes
// derived from the given expression map. // derived from the given expression map.
// //
// Each entry in the map becomes an attribute whose name is the key and // Each entry in the map becomes an attribute whose name is the key and
// whose expression is the value. // whose expression is the value.
func MockAttrs(exprs map[string]zcl.Expression) zcl.Attributes { func MockAttrs(exprs map[string]hcl.Expression) hcl.Attributes {
ret := make(zcl.Attributes) ret := make(hcl.Attributes)
for name, expr := range exprs { for name, expr := range exprs {
ret[name] = &zcl.Attribute{ ret[name] = &hcl.Attribute{
Name: name, Name: name,
Expr: expr, Expr: expr,
Range: zcl.Range{ Range: hcl.Range{
Filename: "MockAttrs", Filename: "MockAttrs",
}, },
NameRange: zcl.Range{ NameRange: hcl.Range{
Filename: "MockAttrs", Filename: "MockAttrs",
}, },
} }

View File

@ -5,176 +5,176 @@ import (
"reflect" "reflect"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
var mockBodyIsBody zcl.Body = mockBody{} var mockBodyIsBody hcl.Body = mockBody{}
var mockExprLiteralIsExpr zcl.Expression = mockExprLiteral{} var mockExprLiteralIsExpr hcl.Expression = mockExprLiteral{}
var mockExprVariableIsExpr zcl.Expression = mockExprVariable("") var mockExprVariableIsExpr hcl.Expression = mockExprVariable("")
func TestMockBodyPartialContent(t *testing.T) { func TestMockBodyPartialContent(t *testing.T) {
tests := map[string]struct { tests := map[string]struct {
In *zcl.BodyContent In *hcl.BodyContent
Schema *zcl.BodySchema Schema *hcl.BodySchema
Want *zcl.BodyContent Want *hcl.BodyContent
Remain *zcl.BodyContent Remain *hcl.BodyContent
DiagCount int DiagCount int
}{ }{
"empty": { "empty": {
&zcl.BodyContent{}, &hcl.BodyContent{},
&zcl.BodySchema{}, &hcl.BodySchema{},
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
0, 0,
}, },
"attribute requested": { "attribute requested": {
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
}), }),
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "name", Name: "name",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
}), }),
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
0, 0,
}, },
"attribute remains": { "attribute remains": {
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
}), }),
}, },
&zcl.BodySchema{}, &hcl.BodySchema{},
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
}), }),
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
0, 0,
}, },
"attribute missing": { "attribute missing": {
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "name", Name: "name",
Required: true, Required: true,
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
1, // missing attribute "name" 1, // missing attribute "name"
}, },
"block requested, no labels": { "block requested, no labels": {
&zcl.BodyContent{ &hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
0, 0,
}, },
"block requested, wrong labels": { "block requested, wrong labels": {
&zcl.BodyContent{ &hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "baz", Type: "baz",
LabelNames: []string{"foo"}, LabelNames: []string{"foo"},
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
1, // "baz" requires 1 label 1, // "baz" requires 1 label
}, },
"block remains": { "block remains": {
&zcl.BodyContent{ &hcl.BodyContent{
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
}, },
}, },
&zcl.BodySchema{}, &hcl.BodySchema{},
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{}, Blocks: hcl.Blocks{},
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: zcl.Attributes{}, Attributes: hcl.Attributes{},
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
@ -183,12 +183,12 @@ func TestMockBodyPartialContent(t *testing.T) {
0, 0,
}, },
"various": { "various": {
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
"age": MockExprLiteral(cty.NumberIntVal(32)), "age": MockExprLiteral(cty.NumberIntVal(32)),
}), }),
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },
@ -202,24 +202,24 @@ func TestMockBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodySchema{ &hcl.BodySchema{
Attributes: []zcl.AttributeSchema{ Attributes: []hcl.AttributeSchema{
{ {
Name: "name", Name: "name",
}, },
}, },
Blocks: []zcl.BlockHeaderSchema{ Blocks: []hcl.BlockHeaderSchema{
{ {
Type: "bar", Type: "bar",
LabelNames: []string{"name"}, LabelNames: []string{"name"},
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")), "name": MockExprLiteral(cty.StringVal("Ermintrude")),
}), }),
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "bar", Type: "bar",
Labels: []string{"foo1"}, Labels: []string{"foo1"},
@ -230,11 +230,11 @@ func TestMockBodyPartialContent(t *testing.T) {
}, },
}, },
}, },
&zcl.BodyContent{ &hcl.BodyContent{
Attributes: MockAttrs(map[string]zcl.Expression{ Attributes: MockAttrs(map[string]hcl.Expression{
"age": MockExprLiteral(cty.NumberIntVal(32)), "age": MockExprLiteral(cty.NumberIntVal(32)),
}), }),
Blocks: zcl.Blocks{ Blocks: hcl.Blocks{
{ {
Type: "baz", Type: "baz",
}, },

View File

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
"io" "io"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -112,12 +112,12 @@ func (n *Body) SetAttributeValue(name string, val cty.Value) *Attribute {
// SetAttributeTraversal either replaces the expression of an existing attribute // SetAttributeTraversal either replaces the expression of an existing attribute
// of the given name or adds a new attribute definition to the end of the block. // of the given name or adds a new attribute definition to the end of the block.
// //
// The new expression is given as a zcl.Traversal, which must be an absolute // The new expression is given as a hcl.Traversal, which must be an absolute
// traversal. To set a literal value, use SetAttributeValue. // traversal. To set a literal value, use SetAttributeValue.
// //
// The return value is the attribute that was either modified in-place or // The return value is the attribute that was either modified in-place or
// created. // created.
func (n *Body) SetAttributeTraversal(name string, traversal zcl.Traversal) *Attribute { func (n *Body) SetAttributeTraversal(name string, traversal hcl.Traversal) *Attribute {
panic("Body.SetAttributeTraversal not yet implemented") panic("Body.SetAttributeTraversal not yet implemented")
} }

View File

@ -6,8 +6,8 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/zcl" "github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/zcl/zclsyntax" "github.com/hashicorp/hcl2/hcl"
) )
func TestBodyFindAttribute(t *testing.T) { func TestBodyFindAttribute(t *testing.T) {
@ -27,7 +27,7 @@ func TestBodyFindAttribute(t *testing.T) {
&TokenSeq{ &TokenSeq{
Tokens{ Tokens{
{ {
Type: zclsyntax.TokenIdent, Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'}, Bytes: []byte{'a'},
}, },
}, },
@ -39,7 +39,7 @@ func TestBodyFindAttribute(t *testing.T) {
&TokenSeq{ &TokenSeq{
Tokens{ Tokens{
{ {
Type: zclsyntax.TokenIdent, Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'}, Bytes: []byte{'a'},
}, },
}, },
@ -51,7 +51,7 @@ func TestBodyFindAttribute(t *testing.T) {
&TokenSeq{ &TokenSeq{
Tokens{ Tokens{
{ {
Type: zclsyntax.TokenIdent, Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'}, Bytes: []byte{'b'},
}, },
}, },
@ -63,7 +63,7 @@ func TestBodyFindAttribute(t *testing.T) {
&TokenSeq{ &TokenSeq{
Tokens{ Tokens{
{ {
Type: zclsyntax.TokenIdent, Type: hclsyntax.TokenIdent,
Bytes: []byte{'c'}, Bytes: []byte{'c'},
}, },
}, },
@ -73,7 +73,7 @@ func TestBodyFindAttribute(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(fmt.Sprintf("%s in %s", test.name, test.src), func(t *testing.T) { t.Run(fmt.Sprintf("%s in %s", test.name, test.src), func(t *testing.T) {
f, diags := ParseConfig([]byte(test.src), "", zcl.Pos{Line: 1, Column: 1}) f, diags := ParseConfig([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
if len(diags) != 0 { if len(diags) != 0 {
for _, diag := range diags { for _, diag := range diags {
t.Logf("- %s", diag.Error()) t.Logf("- %s", diag.Error())

Some files were not shown because too many files have changed in this diff Show More