2017-05-24 15:50:44 +00:00
|
|
|
// This is a 'go generate'-oriented program for producing the "Variables"
|
|
|
|
// method on every Expression implementation found within this package.
|
|
|
|
// All expressions share the same implementation for this method, which
|
|
|
|
// just wraps the package-level function "Variables" and uses an AST walk
|
|
|
|
// to do its work.
|
|
|
|
|
|
|
|
// +build ignore
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"go/ast"
|
|
|
|
"go/parser"
|
|
|
|
"go/token"
|
|
|
|
"os"
|
|
|
|
"sort"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
fs := token.NewFileSet()
|
|
|
|
pkgs, err := parser.ParseDir(fs, ".", nil, 0)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "error while parsing: %s\n", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2018-01-24 05:54:38 +00:00
|
|
|
pkg := pkgs["hclsyntax"]
|
2017-05-24 15:50:44 +00:00
|
|
|
|
|
|
|
// Walk all the files and collect the receivers of any "Value" methods
|
|
|
|
// that look like they are trying to implement Expression.
|
|
|
|
var recvs []string
|
|
|
|
for _, f := range pkg.Files {
|
|
|
|
for _, decl := range f.Decls {
|
|
|
|
fd, ok := decl.(*ast.FuncDecl)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if fd.Name.Name != "Value" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
results := fd.Type.Results.List
|
|
|
|
if len(results) != 2 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
valResult := fd.Type.Results.List[0].Type.(*ast.SelectorExpr).X.(*ast.Ident)
|
|
|
|
diagsResult := fd.Type.Results.List[1].Type.(*ast.SelectorExpr).X.(*ast.Ident)
|
|
|
|
|
2018-01-27 18:42:01 +00:00
|
|
|
if valResult.Name != "cty" && diagsResult.Name != "hcl" {
|
2017-05-24 15:50:44 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2018-01-27 18:42:01 +00:00
|
|
|
// If we have a method called Value and it returns something in
|
|
|
|
// "cty" followed by something in "hcl" then that's specific enough
|
2017-05-24 15:50:44 +00:00
|
|
|
// for now, even though this is not 100% exact as a correct
|
|
|
|
// implementation of Value.
|
|
|
|
|
|
|
|
recvTy := fd.Recv.List[0].Type
|
|
|
|
|
|
|
|
switch rtt := recvTy.(type) {
|
|
|
|
case *ast.StarExpr:
|
|
|
|
name := rtt.X.(*ast.Ident).Name
|
|
|
|
recvs = append(recvs, fmt.Sprintf("*%s", name))
|
|
|
|
default:
|
|
|
|
fmt.Fprintf(os.Stderr, "don't know what to do with a %T receiver\n", recvTy)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(recvs)
|
|
|
|
|
|
|
|
of, err := os.OpenFile("expression_vars.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "failed to open output file: %s\n", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprint(of, outputPreamble)
|
|
|
|
for _, recv := range recvs {
|
|
|
|
fmt.Fprintf(of, outputMethodFmt, recv)
|
|
|
|
}
|
|
|
|
fmt.Fprint(of, "\n")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-01-24 05:54:38 +00:00
|
|
|
const outputPreamble = `package hclsyntax
|
2017-05-24 15:50:44 +00:00
|
|
|
|
|
|
|
// Generated by expression_vars_get.go. DO NOT EDIT.
|
|
|
|
// Run 'go generate' on this package to update the set of functions here.
|
|
|
|
|
|
|
|
import (
|
2019-09-09 23:08:19 +00:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
2017-05-24 15:50:44 +00:00
|
|
|
)`
|
|
|
|
|
|
|
|
const outputMethodFmt = `
|
|
|
|
|
2017-09-11 23:40:37 +00:00
|
|
|
func (e %s) Variables() []hcl.Traversal {
|
2017-05-24 15:50:44 +00:00
|
|
|
return Variables(e)
|
|
|
|
}`
|