build(deps): bump github.com/open-policy-agent/opa from 0.51.0 to 0.59.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.51.0 to 0.59.0. - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-policy-agent/opa/compare/v0.51.0...v0.59.0) --- updated-dependencies: - dependency-name: github.com/open-policy-agent/opa dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
a6a6c22c14
commit
1f069c7c00
+117
-28
@@ -11,6 +11,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
"github.com/open-policy-agent/opa/internal/future"
|
||||
@@ -24,6 +25,8 @@ type Opts struct {
|
||||
// of partial evaluation, arguments maybe have been shuffled around, but still
|
||||
// carry along their original source locations.
|
||||
IgnoreLocations bool
|
||||
|
||||
RegoV1 bool
|
||||
}
|
||||
|
||||
// defaultLocationFile is the file name used in `Ast()` for terms
|
||||
@@ -35,15 +38,27 @@ const defaultLocationFile = "__format_default__"
|
||||
// Rego module. If they don't, Source will return an error resulting from the attempt
|
||||
// to parse the bytes.
|
||||
func Source(filename string, src []byte) ([]byte, error) {
|
||||
return SourceWithOpts(filename, src, Opts{})
|
||||
}
|
||||
|
||||
func SourceWithOpts(filename string, src []byte, opts Opts) ([]byte, error) {
|
||||
module, err := ast.ParseModule(filename, string(src))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
formatted, err := Ast(module)
|
||||
if opts.RegoV1 {
|
||||
errors := ast.CheckRegoV1(module)
|
||||
if len(errors) > 0 {
|
||||
return nil, errors
|
||||
}
|
||||
}
|
||||
|
||||
formatted, err := AstWithOpts(module, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %v", filename, err)
|
||||
}
|
||||
|
||||
return formatted, nil
|
||||
}
|
||||
|
||||
@@ -80,6 +95,8 @@ type fmtOpts struct {
|
||||
// for ref heads -- if they do, we'll print all of them in a different way
|
||||
// than if they don't.
|
||||
refHeads bool
|
||||
|
||||
regoV1 bool
|
||||
}
|
||||
|
||||
func AstWithOpts(x interface{}, opts Opts) ([]byte, error) {
|
||||
@@ -98,6 +115,12 @@ func AstWithOpts(x interface{}, opts Opts) ([]byte, error) {
|
||||
|
||||
o := fmtOpts{}
|
||||
|
||||
if opts.RegoV1 {
|
||||
o.regoV1 = true
|
||||
o.ifs = true
|
||||
o.contains = true
|
||||
}
|
||||
|
||||
// Preprocess the AST. Set any required defaults and calculate
|
||||
// values required for printing the formatted output.
|
||||
ast.WalkNodes(x, func(x ast.Node) bool {
|
||||
@@ -119,6 +142,9 @@ func AstWithOpts(x interface{}, opts Opts) ([]byte, error) {
|
||||
|
||||
case *ast.Import:
|
||||
switch {
|
||||
case isRegoV1Compatible(n):
|
||||
o.contains = true
|
||||
o.ifs = true
|
||||
case future.IsAllFutureKeywords(n):
|
||||
o.contains = true
|
||||
o.ifs = true
|
||||
@@ -150,8 +176,15 @@ func AstWithOpts(x interface{}, opts Opts) ([]byte, error) {
|
||||
|
||||
switch x := x.(type) {
|
||||
case *ast.Module:
|
||||
for kw := range extraFutureKeywordImports {
|
||||
x.Imports = ensureFutureKeywordImport(x.Imports, kw)
|
||||
if o.regoV1 {
|
||||
x.Imports = ensureRegoV1Import(x.Imports)
|
||||
}
|
||||
if o.regoV1 || moduleIsRegoV1Compatible(x) {
|
||||
x.Imports = future.FilterFutureImports(x.Imports)
|
||||
} else {
|
||||
for kw := range extraFutureKeywordImports {
|
||||
x.Imports = ensureFutureKeywordImport(x.Imports, kw)
|
||||
}
|
||||
}
|
||||
w.writeModule(x, o)
|
||||
case *ast.Package:
|
||||
@@ -263,13 +296,12 @@ func (w *writer) writeModule(module *ast.Module, o fmtOpts) {
|
||||
return locLess(comments[i], comments[j])
|
||||
})
|
||||
|
||||
// XXX: The parser currently duplicates comments for some reason, so we need
|
||||
// to remove duplicates here.
|
||||
comments = dedupComments(comments)
|
||||
sort.Slice(others, func(i, j int) bool {
|
||||
return locLess(others[i], others[j])
|
||||
})
|
||||
|
||||
comments = trimTrailingWhitespaceInComments(comments)
|
||||
|
||||
comments = w.writePackage(pkg, comments)
|
||||
var imports []*ast.Import
|
||||
var rules []*ast.Rule
|
||||
@@ -288,6 +320,14 @@ func (w *writer) writeModule(module *ast.Module, o fmtOpts) {
|
||||
}
|
||||
}
|
||||
|
||||
func trimTrailingWhitespaceInComments(comments []*ast.Comment) []*ast.Comment {
|
||||
for _, c := range comments {
|
||||
c.Text = bytes.TrimRightFunc(c.Text, unicode.IsSpace)
|
||||
}
|
||||
|
||||
return comments
|
||||
}
|
||||
|
||||
func (w *writer) writePackage(pkg *ast.Package, comments []*ast.Comment) []*ast.Comment {
|
||||
comments = w.insertComments(comments, pkg.Location)
|
||||
|
||||
@@ -345,7 +385,7 @@ func (w *writer) writeRule(rule *ast.Rule, isElse bool, o fmtOpts, comments []*a
|
||||
return comments
|
||||
}
|
||||
|
||||
if o.ifs && partialSetException {
|
||||
if (o.regoV1 || o.ifs) && partialSetException {
|
||||
w.write(" if")
|
||||
if len(rule.Body) == 1 {
|
||||
if rule.Body[0].Location.Row == rule.Head.Location.Row {
|
||||
@@ -453,7 +493,7 @@ func (w *writer) writeElse(rule *ast.Rule, o fmtOpts, comments []*ast.Comment) [
|
||||
|
||||
func (w *writer) writeHead(head *ast.Head, isDefault, isExpandedConst bool, o fmtOpts, comments []*ast.Comment) []*ast.Comment {
|
||||
ref := head.Ref()
|
||||
if head.Key != nil && head.Value == nil {
|
||||
if head.Key != nil && head.Value == nil && !head.HasDynamicRef() {
|
||||
ref = ref.GroundPrefix()
|
||||
}
|
||||
if o.refHeads || len(ref) == 1 {
|
||||
@@ -484,8 +524,26 @@ func (w *writer) writeHead(head *ast.Head, isDefault, isExpandedConst bool, o fm
|
||||
w.write("]")
|
||||
}
|
||||
}
|
||||
if head.Value != nil && (head.Key != nil || ast.Compare(head.Value, ast.BooleanTerm(true)) != 0 || isExpandedConst || isDefault) {
|
||||
if head.Assign {
|
||||
|
||||
if head.Value != nil &&
|
||||
(head.Key != nil || ast.Compare(head.Value, ast.BooleanTerm(true)) != 0 || isExpandedConst || isDefault) {
|
||||
|
||||
// in rego v1, explicitly print value for ref-head constants that aren't partial set assignments, e.g.:
|
||||
// * a -> parser error, won't reach here
|
||||
// * a.b -> a contains "b"
|
||||
// * a.b.c -> a.b.c := true
|
||||
// * a.b.c.d -> a.b.c.d := true
|
||||
isRegoV1RefConst := o.regoV1 && isExpandedConst && head.Key == nil && len(head.Args) == 0
|
||||
|
||||
if head.Location == head.Value.Location && head.Name != "else" && !isRegoV1RefConst {
|
||||
// If the value location is the same as the location of the head,
|
||||
// we know that the value is generated, i.e. f(1)
|
||||
// Don't print the value (` = true`) as it is implied.
|
||||
return comments
|
||||
}
|
||||
|
||||
if head.Assign || o.regoV1 {
|
||||
// preserve assignment operator, and enforce it if formatting for Rego v1
|
||||
w.write(" := ")
|
||||
} else {
|
||||
w.write(" = ")
|
||||
@@ -732,7 +790,12 @@ func (w *writer) writeTermParens(parens bool, term *ast.Term, comments []*ast.Co
|
||||
|
||||
func (w *writer) writeRef(x ast.Ref) {
|
||||
if len(x) > 0 {
|
||||
w.writeTerm(x[0], nil)
|
||||
parens := false
|
||||
_, ok := x[0].Value.(ast.Call)
|
||||
if ok {
|
||||
parens = x[0].Location.Text[0] == 40 // Starts with "("
|
||||
}
|
||||
w.writeTermParens(parens, x[0], nil)
|
||||
path := x[1:]
|
||||
for _, t := range path {
|
||||
switch p := t.Value.(type) {
|
||||
@@ -807,6 +870,7 @@ func (w *writer) writeCall(parens bool, x ast.Call, loc *ast.Location, comments
|
||||
}
|
||||
|
||||
func (w *writer) writeInOperator(parens bool, operands []*ast.Term, comments []*ast.Comment, loc *ast.Location, f *types.Function) []*ast.Comment {
|
||||
|
||||
if len(operands) != len(f.Args()) {
|
||||
// The number of operands does not math the arity of the `in` operator
|
||||
operator := ast.Member.Name
|
||||
@@ -909,12 +973,17 @@ func (w *writer) writeObjectComprehension(object *ast.ObjectComprehension, loc *
|
||||
}
|
||||
|
||||
func (w *writer) writeComprehension(open, close byte, term *ast.Term, body ast.Body, loc *ast.Location, comments []*ast.Comment) []*ast.Comment {
|
||||
if term.Location.Row-loc.Row > 1 {
|
||||
if term.Location.Row-loc.Row >= 1 {
|
||||
w.endLine()
|
||||
w.startLine()
|
||||
}
|
||||
|
||||
comments = w.writeTerm(term, comments)
|
||||
parens := false
|
||||
_, ok := term.Value.(ast.Call)
|
||||
if ok {
|
||||
parens = term.Location.Text[0] == 40 // Starts with "("
|
||||
}
|
||||
comments = w.writeTermParens(parens, term, comments)
|
||||
w.write(" |")
|
||||
|
||||
return w.writeComprehensionBody(open, close, body, term.Location, loc, comments)
|
||||
@@ -1280,21 +1349,6 @@ func skipPast(open, close byte, loc *ast.Location) (int, int) {
|
||||
return i, offset
|
||||
}
|
||||
|
||||
func dedupComments(comments []*ast.Comment) []*ast.Comment {
|
||||
if len(comments) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
filtered := []*ast.Comment{comments[0]}
|
||||
for i := 1; i < len(comments); i++ {
|
||||
if comments[i].Location.Equal(comments[i-1].Location) {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, comments[i])
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// startLine begins a line with the current indentation level.
|
||||
func (w *writer) startLine() {
|
||||
w.inline = true
|
||||
@@ -1386,6 +1440,24 @@ func ensureFutureKeywordImport(imps []*ast.Import, kw string) []*ast.Import {
|
||||
return append(imps, imp)
|
||||
}
|
||||
|
||||
func ensureRegoV1Import(imps []*ast.Import) []*ast.Import {
|
||||
return ensureImport(imps, ast.RegoV1CompatibleRef)
|
||||
}
|
||||
|
||||
func ensureImport(imps []*ast.Import, path ast.Ref) []*ast.Import {
|
||||
for _, imp := range imps {
|
||||
p := imp.Path.Value.(ast.Ref)
|
||||
if p.Equal(path) {
|
||||
return imps
|
||||
}
|
||||
}
|
||||
imp := &ast.Import{
|
||||
Path: ast.NewTerm(path),
|
||||
}
|
||||
imp.Location = defaultLocation(imp)
|
||||
return append(imps, imp)
|
||||
}
|
||||
|
||||
// ArgErrDetail but for `fmt` checks since compiler has not run yet.
|
||||
type ArityFormatErrDetail struct {
|
||||
Have []string `json:"have"`
|
||||
@@ -1418,3 +1490,20 @@ func (d *ArityFormatErrDetail) Lines() []string {
|
||||
"want: " + "(" + strings.Join(d.Want, ",") + ")",
|
||||
}
|
||||
}
|
||||
|
||||
func moduleIsRegoV1Compatible(m *ast.Module) bool {
|
||||
for _, imp := range m.Imports {
|
||||
if isRegoV1Compatible(imp) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isRegoV1Compatible returns true if the passed *ast.Import is `rego.v1`
|
||||
func isRegoV1Compatible(imp *ast.Import) bool {
|
||||
path := imp.Path.Value.(ast.Ref)
|
||||
return len(path) == 2 &&
|
||||
ast.RegoRootDocument.Equal(path[0]) &&
|
||||
path[1].Equal(ast.StringTerm("v1"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user