In recent years, a
Birth of Arianne K
A prospective, coh
Rachel Maddow repo
As many of you kno
Bangla
The Bangla
Revealing insights
There are various
---
title: Gatsby
Q:
How to set up package hclwrite
import (
"fmt"
"sort"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/hcl/v2/hclsyntax/hcltoken"
"github.com/zclconf/go-cty/cty"
)
// Our tags re-export some of the internal types from hcl to make them easier
// to use inside static analysis tools, but more importantly to make it
// possible to re-synthesize any of the types during tests.
//go:generate go run -tags codegen hclwrite_fexec.go
//go:generate go run -tags codegen hclwrite_csynth.go
//go:generate go run -tags codegen hclwrite_ccc.go
//go:generate go run -tags codegen hclwrite_models.go
type Token struct {
Type hcltoken.Type
Value string
Sema hcl.Range
}
type Attribute struct {
Name string
Sensitive bool
Expr cty.Value
}
type BinOp struct {
Op string
LHS, RHS *Attribute
}
type Range struct {
Start, End int
}
type Number struct {
Value cty.Value
SrcRange hcl.Range
IsLiteral bool
}
type String struct {
Value cty.Value
SrcRange hcl.Range
IsLiteral bool
}
type Bool struct {
Value cty.Value
SrcRange hcl.Range
IsLiteral bool
}
type Char struct {
Value cty.Value
SrcRange hcl.Range
IsLiteral bool
}
type AttributeValue struct {
Val cty.Value
}
type InvalidAttributeValueError struct {
SrcRange hcl.Range
Detail string
}
func (e *InvalidAttributeValueError) Error() string {
return fmt.Sprintf("invalid attribute value: %s", e.Detail)
}
type BadComparisonError struct {
SrcRange hcl.Range
Expr string
}
func (e *BadComparisonError) Error() string {
return fmt.Sprintf(
"invalid comparison: %s (for %q) %s",
e.Expr, e.SrcRange, e.SrcRange.String(),
)
}
type InvalidOperationError struct {
SrcRange hcl.Range
OpName string
Expr string
}
func (e *InvalidOperationError) Error() string {
return fmt.Sprintf(
"invalid operation %q for %q: %s",
e.OpName, e.SrcRange, e.Expr,
)
}
type MismatchedTypeError struct {
SrcRange hcl.Range
Expected cty.Type
Actual cty.Type
}
func (e *MismatchedTypeError) Error() string {
// We don't know what type was expected, so we'll just print the
// range here and let the good folks working on GOLang find the bug.
return fmt.Sprintf("incorrect type for %q: expected %#v, actual %#v",
e.SrcRange, cty.TypeName(e.Expected), cty.TypeName(e.Actual))
}
// The keywords for the HCL native syntax are listed here, so that the
// parser can properly parse the keywords.
var hclKeywords = [...]string{
"$else", "$fallthrough", "$if", "$elseif",
"$switch", "$case", "$default", "$range",
"$with", "$||", "$POSIX_SEMAPHORES",
}
var hclFunctions = [...]string{
"_characters", "_each", "_escape", "_extract",
"_scan",
}
var hclPunctuation = [...]string{
"(", ")", "[", "]", "{", "}",
"<", ">", "=", "<>", ":",
"!", ",", "+", "-", "*", "/",
"%", "&", "|", "~",
}
var hclType = [...]string{
"any", "array", "bool", "boolean", "integer",
"number", "string", "symbol", "unit",
}
// hclParser is the main entry-point for parsing HCL files and using the
// resulting AST to populate a Developer's understanding of the file.
//
// The secondary entry-point for parsing is parseFile, which takes a filename
// string and produces a similar AST with fewer details populated in some
// cases. It's intended to be used to bootstrap parsing when the full details
// aren't required, as it will use the hclparse package's AST implementation
// for parsing.
//
// The hclparse package contains more detailed AST wrappers for the HCL AST,
// which are useful for working with ASTs directly.
//
// In most HCL files, this is the only part that will be called directly;
// most of the work will be performed by the hclparse package.
func hclParser(src []byte, filename string, start hcl.Pos) (*hclparse.File, hcl.Diagnostics) {
tokens := scan(src, filename, start)
p := &hclParser{
Tokens: tokens,
SrcRange: hcl.RangeBetween(tokens.Pos(), tokens.End()),
EndRange: tokens.Pos(),
File: new(hclparse.File),
Project: filename,
LineRange: tokens.LineRange(),
}
return p, parse(p)
}
// TypeExpression = "type" ExprSingle *Type
// Type = LiteralType | StaticType | PrimitiveType
//
// LiteralType: "null", "true", "false"
// StaticType: ExprSingle
type TypeExpression struct {
Type Type
SrcRange hcl.Range
Expr Expression
}
var typeKeywordTokens = [...]string{
"bool",
"string",
"number",
"any",
"array",
"object",
}
func (e *TypeExpression) diagnose() hcl.Diagnostics {
var ret hcl.Diagnostics
// Render the start token for each of the keyword kinds followed
// by the token representing the type in literal form. This is so
// that we can tell if the type keyword appears before or after an
// identifier, for example.
for _, kw := range typeKeywordTokens {
start := e.SrcRange.Start
end := e.SrcRange.Start
for _, tok := range e.Tokens {
if kw == tok.Type {
ret = ret.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Extraneous type",
Detail: "The type keyword is unnecessary.",
Subject: &start,
Context: &e.SrcRange,
})
end = e.SrcRange.End
} else {
end = tok.Range.End
}
}
ret.Append(&hcl.Diagnostic{
// This is deprecated and will be going away soon
Severity: hcl.DiagError,
Summary: "Missing type field name",
Detail: "A type annotation often looks like a variable name, such as \"resource\" or \"aws_instance\". The correct syntax for type annotation is a literal type, such as \"string\".",
Subject: &start,
Context: &e.SrcRange,
})
}
return ret
}
// Type = (LiteralType | StaticType | "?" | OptionType) [ "?" ]
// or "?"
//
// LiteralType: "null", "any"
// StaticType: "string", "number", "boolean", "array", "map"
// OptionType: "string"
type Type struct {
LiteralType Type
StaticType bool
OptionTypeName string
}
var typeTokens = [...]string{
"null",
"any",
"string",
"number",
"boolean",
"array",
"map",
"string",
"boolean",
"any",