bump dependencies

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2024-10-18 17:35:30 +02:00
parent 290477b494
commit ca113f5751
522 changed files with 93151 additions and 33036 deletions
+1 -1
View File
@@ -520,7 +520,7 @@ func attachRuleAnnotations(mod *Module) {
var j int
var found bool
for i, a := range cpy {
if rule.Ref().Equal(a.GetTargetPath()) {
if rule.Ref().GroundPrefix().Equal(a.GetTargetPath()) {
if a.Scope == annotationScopeDocument {
rule.Annotations = append(rule.Annotations, a)
} else if a.Scope == annotationScopeRule && rule.Loc().Row > a.Location.Row {
+36 -11
View File
@@ -33,15 +33,18 @@ type typeChecker struct {
allowNet []string
input types.Type
allowUndefinedFuncs bool
schemaTypes map[string]types.Type
}
// newTypeChecker returns a new typeChecker object that has no errors.
func newTypeChecker() *typeChecker {
tc := &typeChecker{}
tc.exprCheckers = map[string]exprChecker{
"eq": tc.checkExprEq,
return &typeChecker{
builtins: make(map[string]*Builtin),
schemaTypes: make(map[string]types.Type),
exprCheckers: map[string]exprChecker{
"eq": checkExprEq,
},
}
return tc
}
func (tc *typeChecker) newEnv(exist *TypeEnv) *TypeEnv {
@@ -196,20 +199,42 @@ func (tc *typeChecker) checkClosures(env *TypeEnv, expr *Expr) Errors {
return result
}
func (tc *typeChecker) getSchemaType(schemaAnnot *SchemaAnnotation, rule *Rule) (types.Type, *Error) {
if refType, exists := tc.schemaTypes[schemaAnnot.Schema.String()]; exists {
return refType, nil
}
refType, err := processAnnotation(tc.ss, schemaAnnot, rule, tc.allowNet)
if err != nil {
return nil, err
}
if refType == nil {
return nil, nil
}
tc.schemaTypes[schemaAnnot.Schema.String()] = refType
return refType, nil
}
func (tc *typeChecker) checkRule(env *TypeEnv, as *AnnotationSet, rule *Rule) {
env = env.wrap()
schemaAnnots := getRuleAnnotation(as, rule)
for _, schemaAnnot := range schemaAnnots {
ref, refType, err := processAnnotation(tc.ss, schemaAnnot, rule, tc.allowNet)
refType, err := tc.getSchemaType(schemaAnnot, rule)
if err != nil {
tc.err([]*Error{err})
continue
}
ref := schemaAnnot.Path
if ref == nil && refType == nil {
continue
}
prefixRef, t := getPrefix(env, ref)
if t == nil || len(prefixRef) == len(ref) {
env.tree.Put(ref, refType)
@@ -404,7 +429,7 @@ func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error {
return nil
}
func (tc *typeChecker) checkExprEq(env *TypeEnv, expr *Expr) *Error {
func checkExprEq(env *TypeEnv, expr *Expr) *Error {
pre := getArgTypes(env, expr.Operands())
exp := Equality.Decl.FuncArgs()
@@ -1266,17 +1291,17 @@ func getRuleAnnotation(as *AnnotationSet, rule *Rule) (result []*SchemaAnnotatio
return result
}
func processAnnotation(ss *SchemaSet, annot *SchemaAnnotation, rule *Rule, allowNet []string) (Ref, types.Type, *Error) {
func processAnnotation(ss *SchemaSet, annot *SchemaAnnotation, rule *Rule, allowNet []string) (types.Type, *Error) {
var schema interface{}
if annot.Schema != nil {
if ss == nil {
return nil, nil, nil
return nil, nil
}
schema = ss.Get(annot.Schema)
if schema == nil {
return nil, nil, NewError(TypeErr, rule.Location, "undefined schema: %v", annot.Schema)
return nil, NewError(TypeErr, rule.Location, "undefined schema: %v", annot.Schema)
}
} else if annot.Definition != nil {
schema = *annot.Definition
@@ -1284,10 +1309,10 @@ func processAnnotation(ss *SchemaSet, annot *SchemaAnnotation, rule *Rule, allow
tpe, err := loadSchema(schema, allowNet)
if err != nil {
return nil, nil, NewError(TypeErr, rule.Location, err.Error())
return nil, NewError(TypeErr, rule.Location, err.Error())
}
return annot.Path, tpe, nil
return tpe, nil
}
func errAnnotationRedeclared(a *Annotations, other *Location) *Error {
+27 -10
View File
@@ -5332,8 +5332,7 @@ func rewriteDeclaredVarsInExpr(g *localVarGenerator, stack *localDeclaredVars, e
case *Term:
stop, errs = rewriteDeclaredVarsInTerm(g, stack, x, errs, strict)
case *With:
errs = rewriteDeclaredVarsInTermRecursive(g, stack, x.Value, errs, strict)
stop = true
stop, errs = true, rewriteDeclaredVarsInWithRecursive(g, stack, x, errs, strict)
}
return stop
})
@@ -5466,20 +5465,38 @@ func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, t
}
func rewriteDeclaredVarsInTermRecursive(g *localVarGenerator, stack *localDeclaredVars, term *Term, errs Errors, strict bool) Errors {
WalkNodes(term, func(n Node) bool {
WalkTerms(term, func(t *Term) bool {
var stop bool
switch n := n.(type) {
case *With:
errs = rewriteDeclaredVarsInTermRecursive(g, stack, n.Value, errs, strict)
stop = true
case *Term:
stop, errs = rewriteDeclaredVarsInTerm(g, stack, n, errs, strict)
}
stop, errs = rewriteDeclaredVarsInTerm(g, stack, t, errs, strict)
return stop
})
return errs
}
func rewriteDeclaredVarsInWithRecursive(g *localVarGenerator, stack *localDeclaredVars, w *With, errs Errors, strict bool) Errors {
// NOTE(sr): `with input as` and `with input.a.b.c as` are deliberately skipped here: `input` could
// have been shadowed by a local variable/argument but should NOT be replaced in the `with` target.
//
// We cannot drop `input` from the stack since it's conceivable to do `with input[input] as` where
// the second input is meant to be the local var. It's a terrible idea, but when you're shadowing
// `input` those might be your thing.
errs = rewriteDeclaredVarsInTermRecursive(g, stack, w.Target, errs, strict)
if sdwInput, ok := stack.Declared(InputRootDocument.Value.(Var)); ok { // Was "input" shadowed...
switch value := w.Target.Value.(type) {
case Var:
if sdwInput.Equal(value) { // ...and replaced? If so, fix it
w.Target.Value = InputRootRef
}
case Ref:
if sdwInput.Equal(value[0].Value.(Var)) {
w.Target.Value.(Ref)[0].Value = InputRootDocument.Value
}
}
}
// No special handling of the `with` value
return rewriteDeclaredVarsInTermRecursive(g, stack, w.Value, errs, strict)
}
func rewriteDeclaredVarsInArrayComprehension(g *localVarGenerator, stack *localDeclaredVars, v *ArrayComprehension, errs Errors, strict bool) Errors {
used := NewVarSet()
used.Update(v.Term.Vars())
+38 -6
View File
@@ -30,6 +30,8 @@ var RegoV1CompatibleRef = Ref{VarTerm("rego"), StringTerm("v1")}
// RegoVersion defines the Rego syntax requirements for a module.
type RegoVersion int
const DefaultRegoVersion = RegoVersion(0)
const (
// RegoV0 is the default, original Rego syntax.
RegoV0 RegoVersion = iota
@@ -317,6 +319,31 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) {
for k, v := range futureKeywords {
allowedFutureKeywords[k] = v
}
// For sake of error reporting, we still need to check that keywords in capabilities are known,
for _, kw := range p.po.Capabilities.FutureKeywords {
if _, ok := futureKeywords[kw]; !ok {
return nil, nil, Errors{
&Error{
Code: ParseErr,
Message: fmt.Sprintf("illegal capabilities: unknown keyword: %v", kw),
Location: nil,
},
}
}
}
// and that explicitly requested future keywords are known.
for _, kw := range p.po.FutureKeywords {
if _, ok := allowedFutureKeywords[kw]; !ok {
return nil, nil, Errors{
&Error{
Code: ParseErr,
Message: fmt.Sprintf("unknown future keyword: %v", kw),
Location: nil,
},
}
}
}
} else {
for _, kw := range p.po.Capabilities.FutureKeywords {
var ok bool
@@ -686,6 +713,10 @@ func (p *Parser) parseRules() []*Rule {
// p[x] if ... becomes a single-value rule p[x]
if hasIf && !usesContains && len(rule.Head.Ref()) == 2 {
if !rule.Head.Ref()[1].IsGround() && len(rule.Head.Args) == 0 {
rule.Head.Key = rule.Head.Ref()[1]
}
if rule.Head.Value == nil {
rule.Head.generatedValue = true
rule.Head.Value = BooleanTerm(true).SetLocation(rule.Head.Location)
@@ -2665,15 +2696,16 @@ func (p *Parser) regoV1Import(imp *Import) {
return
}
if p.po.RegoVersion == RegoV1 {
// We're parsing for Rego v1, where the 'rego.v1' import is a no-op.
path := imp.Path.Value.(Ref)
// v1 is only valid option
if len(path) == 1 || !path[1].Equal(RegoV1CompatibleRef[1]) || len(path) > 2 {
p.errorf(imp.Path.Location, "invalid import `%s`, must be `%s`", path, RegoV1CompatibleRef)
return
}
path := imp.Path.Value.(Ref)
if len(path) == 1 || !path[1].Equal(RegoV1CompatibleRef[1]) || len(path) > 2 {
p.errorf(imp.Path.Location, "invalid import `%s`, must be `%s`", path, RegoV1CompatibleRef)
if p.po.RegoVersion == RegoV1 {
// We're parsing for Rego v1, where the 'rego.v1' import is a no-op.
return
}
+35 -5
View File
@@ -103,6 +103,14 @@ func MustParseStatement(input string) Statement {
return parsed
}
func MustParseStatementWithOpts(input string, popts ParserOptions) Statement {
parsed, err := ParseStatementWithOpts(input, popts)
if err != nil {
panic(err)
}
return parsed
}
// MustParseRef returns a parsed reference.
// If an error occurs during parsing, panic.
func MustParseRef(input string) Ref {
@@ -123,6 +131,16 @@ func MustParseRule(input string) *Rule {
return parsed
}
// MustParseRuleWithOpts returns a parsed rule.
// If an error occurs during parsing, panic.
func MustParseRuleWithOpts(input string, opts ParserOptions) *Rule {
parsed, err := ParseRuleWithOpts(input, opts)
if err != nil {
panic(err)
}
return parsed
}
// MustParseTerm returns a parsed term.
// If an error occurs during parsing, panic.
func MustParseTerm(input string) *Term {
@@ -269,11 +287,12 @@ func ParseCompleteDocRuleFromEqExpr(module *Module, lhs, rhs *Term) (*Rule, erro
setJSONOptions(body, &rhs.jsonOptions)
return &Rule{
Location: lhs.Location,
Head: head,
Body: body,
Module: module,
jsonOptions: lhs.jsonOptions,
Location: lhs.Location,
Head: head,
Body: body,
Module: module,
jsonOptions: lhs.jsonOptions,
generatedBody: true,
}, nil
}
@@ -608,6 +627,17 @@ func ParseStatement(input string) (Statement, error) {
return stmts[0], nil
}
func ParseStatementWithOpts(input string, popts ParserOptions) (Statement, error) {
stmts, _, err := ParseStatementsWithOpts("", input, popts)
if err != nil {
return nil, err
}
if len(stmts) != 1 {
return nil, fmt.Errorf("expected exactly one statement")
}
return stmts[0], nil
}
// ParseStatements is deprecated. Use ParseStatementWithOpts instead.
func ParseStatements(filename, input string) ([]Statement, []*Comment, error) {
return ParseStatementsWithOpts(filename, input, ParserOptions{})
+54 -11
View File
@@ -100,7 +100,7 @@ var Wildcard = &Term{Value: Var("_")}
var WildcardPrefix = "$"
// Keywords contains strings that map to language keywords.
var Keywords = KeywordsV0
var Keywords = KeywordsForRegoVersion(DefaultRegoVersion)
var KeywordsV0 = [...]string{
"not",
@@ -134,9 +134,23 @@ var KeywordsV1 = [...]string{
"every",
}
func KeywordsForRegoVersion(v RegoVersion) []string {
switch v {
case RegoV0:
return KeywordsV0[:]
case RegoV1, RegoV0CompatV1:
return KeywordsV1[:]
}
return nil
}
// IsKeyword returns true if s is a language keyword.
func IsKeyword(s string) bool {
for _, x := range Keywords {
return IsInKeywords(s, Keywords)
}
func IsInKeywords(s string, keywords []string) bool {
for _, x := range keywords {
if x == s {
return true
}
@@ -405,7 +419,7 @@ func (mod *Module) String() string {
buf = append(buf, "")
for _, rule := range mod.Rules {
buf = appendAnnotationStrings(buf, rule)
buf = append(buf, rule.String())
buf = append(buf, rule.stringWithOpts(toStringOpts{regoVersion: mod.regoVersion}))
}
}
return strings.Join(buf, "\n")
@@ -770,18 +784,30 @@ func (rule *Rule) Ref() Ref {
}
func (rule *Rule) String() string {
return rule.stringWithOpts(toStringOpts{})
}
type toStringOpts struct {
regoVersion RegoVersion
}
func (rule *Rule) stringWithOpts(opts toStringOpts) string {
buf := []string{}
if rule.Default {
buf = append(buf, "default")
}
buf = append(buf, rule.Head.String())
buf = append(buf, rule.Head.stringWithOpts(opts))
if !rule.Default {
switch opts.regoVersion {
case RegoV1, RegoV0CompatV1:
buf = append(buf, "if")
}
buf = append(buf, "{")
buf = append(buf, rule.Body.String())
buf = append(buf, "}")
}
if rule.Else != nil {
buf = append(buf, rule.Else.elseString())
buf = append(buf, rule.Else.elseString(opts))
}
return strings.Join(buf, " ")
}
@@ -824,7 +850,7 @@ func (rule *Rule) MarshalJSON() ([]byte, error) {
return json.Marshal(data)
}
func (rule *Rule) elseString() string {
func (rule *Rule) elseString(opts toStringOpts) string {
var buf []string
buf = append(buf, "else")
@@ -835,12 +861,17 @@ func (rule *Rule) elseString() string {
buf = append(buf, value.String())
}
switch opts.regoVersion {
case RegoV1, RegoV0CompatV1:
buf = append(buf, "if")
}
buf = append(buf, "{")
buf = append(buf, rule.Body.String())
buf = append(buf, "}")
if rule.Else != nil {
buf = append(buf, rule.Else.elseString())
buf = append(buf, rule.Else.elseString(opts))
}
return strings.Join(buf, " ")
@@ -1000,16 +1031,28 @@ func (head *Head) Equal(other *Head) bool {
}
func (head *Head) String() string {
return head.stringWithOpts(toStringOpts{})
}
func (head *Head) stringWithOpts(opts toStringOpts) string {
buf := strings.Builder{}
buf.WriteString(head.Ref().String())
containsAdded := false
switch {
case len(head.Args) != 0:
buf.WriteString(head.Args.String())
case len(head.Reference) == 1 && head.Key != nil:
buf.WriteRune('[')
buf.WriteString(head.Key.String())
buf.WriteRune(']')
switch opts.regoVersion {
case RegoV0:
buf.WriteRune('[')
buf.WriteString(head.Key.String())
buf.WriteRune(']')
default:
containsAdded = true
buf.WriteString(" contains ")
buf.WriteString(head.Key.String())
}
}
if head.Value != nil {
if head.Assign {
@@ -1018,7 +1061,7 @@ func (head *Head) String() string {
buf.WriteString(" = ")
}
buf.WriteString(head.Value.String())
} else if head.Name == "" && head.Key != nil {
} else if !containsAdded && head.Name == "" && head.Key != nil {
buf.WriteString(" contains ")
buf.WriteString(head.Key.String())
}
+6 -3
View File
@@ -50,9 +50,12 @@ func checkRootDocumentOverrides(node interface{}) Errors {
WalkExprs(node, func(expr *Expr) bool {
if expr.IsAssignment() {
name := expr.Operand(0).String()
if RootDocumentRefs.Contains(RefTerm(VarTerm(name))) {
errors = append(errors, NewError(CompileErr, expr.Location, "variables must not shadow %v (use a different variable name)", name))
// assign() can be called directly, so we need to assert its given first operand exists before checking its name.
if nameOp := expr.Operand(0); nameOp != nil {
name := nameOp.String()
if RootDocumentRefs.Contains(RefTerm(VarTerm(name))) {
errors = append(errors, NewError(CompileErr, expr.Location, "variables must not shadow %v (use a different variable name)", name))
}
}
}
return false