Files
releases/cmd/parse.go
T
Torin Sandall d3adb906f0 ast: Misc. refactoring on annotations support
This commit combines a bunch of refactoring on annotations to support
future work.

Specifically:

* Annotations are now normal AST nodes/statements. This means that
  annotations store locations and also implement String() and
  Compare(). Annotations are now correctly compared during module
  comparison and annotations are included in the module string
  representation (before annotations would be dropped when the module
  String() function was called.) Also, the visitor and transformer
  functions support annotations now.

* Annotations are no longer hidden behind an interface. Instead, there
  is a single annotation struct that we can evolve over
  time. It was unclear how the Annotations interface was going to work
  in the long-term (e.g., callers would not be able to define their
  own annotation types since the parser needs to be aware of them.)
  With this change, Annotations are just structs now. We can extend
  the struct as needed going forward. Custom data can be stored in a
  dedicated field.

* Annotation parsing has been refactored. We now attach annotations to
  the statement following the annotation. The parser will reject
  METADATA blocks that contain whitespace between the METADATA hint
  and the YAML block. Similarly, we no longer support trailing
  unindented comments that follow the METADATA block. Users can inject
  whitespace after the YAML block if they want to include trailing
  comments.

* The opa parse subcommand now enables annotation processing.

Signed-off-by: Torin Sandall <torinsandall@gmail.com>
2021-04-27 09:06:08 -04:00

82 lines
1.8 KiB
Go

// Copyright 2018 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package cmd
import (
"encoding/json"
"fmt"
"io"
"os"
"github.com/spf13/cobra"
"github.com/open-policy-agent/opa/ast"
pr "github.com/open-policy-agent/opa/internal/presentation"
"github.com/open-policy-agent/opa/loader"
"github.com/open-policy-agent/opa/util"
)
const (
parseFormatPretty = "pretty"
parseFormatJSON = "json"
)
var parseParams = struct {
format *util.EnumFlag
}{
format: util.NewEnumFlag(parseFormatPretty, []string{parseFormatPretty, parseFormatJSON}),
}
var parseCommand = &cobra.Command{
Use: "parse <path>",
Short: "Parse Rego source file",
Long: `Parse Rego source file and print AST.`,
PreRunE: func(Cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("no source file specified")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
os.Exit(parse(args, os.Stdout, os.Stderr))
},
}
func parse(args []string, stdout io.Writer, stderr io.Writer) int {
if len(args) == 0 {
return 0
}
result, err := loader.RegoWithOpts(args[0], ast.ParserOptions{ProcessAnnotation: true})
switch parseParams.format.String() {
case parseFormatJSON:
if err != nil {
pr.JSON(stderr, pr.Output{Errors: pr.NewOutputErrors(err)})
return 1
}
bs, err := json.MarshalIndent(result.Parsed, "", " ")
if err != nil {
fmt.Fprintln(stderr, err)
return 1
}
fmt.Println(string(bs))
default:
if err != nil {
fmt.Fprintln(stderr, err)
return 1
}
ast.Pretty(stdout, result.Parsed)
}
return 0
}
func init() {
parseCommand.Flags().VarP(parseParams.format, "format", "f", "set output format")
RootCommand.AddCommand(parseCommand)
}