From f28ac7df9f7ace03699253e5e96e8d8a4d8618f2 Mon Sep 17 00:00:00 2001 From: Anders Eknert Date: Wed, 21 Aug 2024 10:14:07 +0200 Subject: [PATCH] Use new Roast library for custom AST serialization (#1001) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And the `jsoniter` library for any JSON handling. This is quite a big win for linting performance: ``` ➜ hyperfine --warmup 2 'regal_main lint bundle' 'regal_jsoniter lint bundle' Benchmark 1: regal_main lint bundle Time (mean ± σ): 2.707 s ± 0.035 s [User: 19.171 s, System: 0.636 s] Range (min … max): 2.662 s … 2.785 s 10 runs Benchmark 2: regal_jsoniter lint bundle Time (mean ± σ): 2.185 s ± 0.019 s [User: 14.932 s, System: 0.466 s] Range (min … max): 2.147 s … 2.207 s 10 runs Summary regal_jsoniter lint bundle ran 1.24 ± 0.02 times faster than regal_main lint bundle ``` But importantly, it doesn't make the AST harder to read or work with — quite the opposite actually! See the Roast README for all the details: https://github.com/anderseknert/roast Signed-off-by: Anders Eknert --- README.md | 2 +- bundle/regal/ast/ast.rego | 45 +++------- bundle/regal/ast/ast_test.rego | 32 ++----- bundle/regal/ast/comments.rego | 13 +-- bundle/regal/ast/keywords.rego | 52 ++++++----- bundle/regal/ast/keywords_test.rego | 2 +- ...le_heads.rego => rule_head_locations.rego} | 9 +- ...est.rego => rule_head_locations_test.rego} | 0 bundle/regal/ast/search.rego | 40 +++++---- .../lsp/completion/location/location.rego | 8 +- bundle/regal/main.rego | 4 +- bundle/regal/result.rego | 27 +++--- .../bugs/annotation_without_metadata.rego | 7 +- .../regal/rules/bugs/constant_condition.rego | 2 +- bundle/regal/rules/bugs/duplicate_rule.rego | 4 +- bundle/regal/rules/bugs/impossible_not.rego | 5 +- .../regal/rules/bugs/inconsistent_args.rego | 5 +- .../bugs/invalid_metadata_attribute.rego | 6 +- .../regal/rules/bugs/zero_arity_function.rego | 3 +- bundle/regal/rules/custom/one_liner_rule.rego | 12 ++- .../rules/idiomatic/ambiguous_scope.rego | 5 +- .../idiomatic/equals_pattern_matching.rego | 4 +- .../idiomatic/no_defined_entrypoint.rego | 3 +- .../idiomatic/non_raw_regex_pattern.rego | 3 +- .../idiomatic/prefer_set_or_object_rule.rego | 2 +- .../regal/rules/idiomatic/use_contains.rego | 3 +- bundle/regal/rules/idiomatic/use_if.rego | 8 +- .../regal/rules/imports/circular_import.rego | 9 +- .../rules/imports/import_after_rule.rego | 5 +- .../regal/rules/style/default_over_else.rego | 7 +- .../regal/rules/style/default_over_not.rego | 2 +- .../regal/rules/style/detached_metadata.rego | 9 +- .../rules/style/no_whitespace_comment.rego | 2 +- .../rules/style/pointless_reassignment.rego | 2 +- .../rules/style/prefer_some_in_iteration.rego | 9 +- .../style/prefer_some_in_iteration_test.rego | 12 +++ bundle/regal/rules/style/rule_length.rego | 14 +-- bundle/regal/rules/style/todo_comment.rego | 2 +- .../rules/style/use_assignment_operator.rego | 7 +- bundle/regal/util/util.rego | 7 ++ cmd/capabilities.go | 4 +- cmd/parse.go | 4 +- cmd/version.go | 4 +- go.mod | 34 ++++--- go.sum | 88 +++++++++++-------- internal/embeds/schemas/regal-ast.json | 26 +----- internal/io/io.go | 15 +--- .../lsp/completions/providers/policy_test.go | 17 ++-- internal/lsp/connection.go | 6 +- internal/lsp/eval.go | 5 +- internal/lsp/examples/examples.go | 5 +- internal/lsp/lint.go | 5 +- internal/lsp/server.go | 47 +++++----- internal/lsp/server_test.go | 16 ++-- internal/lsp/store.go | 6 +- internal/parse/parse.go | 21 ----- internal/update/update.go | 7 +- pkg/builtins/builtins.go | 5 +- pkg/config/config.go | 8 +- pkg/linter/linter.go | 2 +- pkg/linter/linter_test.go | 4 +- pkg/reporter/reporter.go | 4 +- 62 files changed, 380 insertions(+), 346 deletions(-) rename bundle/regal/ast/{rule_heads.rego => rule_head_locations.rego} (67%) rename bundle/regal/ast/{rule_heads_test.rego => rule_head_locations_test.rego} (100%) diff --git a/README.md b/README.md index 9be41f9d..9a7caee6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Regal [![Build Status](https://github.com/styrainc/regal/workflows/Build/badge.svg?branch=main)](https://github.com/styrainc/regal/actions) -![OPA v0.67.0](https://openpolicyagent.org/badge/v0.67.0) +![OPA v0.67.1](https://openpolicyagent.org/badge/v0.67.1) Regal is a linter and language server for [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), helping you write better policies and have fun while doing it! diff --git a/bundle/regal/ast/ast.rego b/bundle/regal/ast/ast.rego index ebe6aee2..48150dbe 100644 --- a/bundle/regal/ast/ast.rego +++ b/bundle/regal/ast/ast.rego @@ -3,6 +3,7 @@ package regal.ast import rego.v1 import data.regal.config +import data.regal.util scalar_types := {"boolean", "null", "number", "string"} @@ -62,34 +63,6 @@ _is_name(ref, pos) if { ref.type == "string" } -# METADATA -# description: | -# answers if the body was generated or not, i.e. not seen -# in the original Rego file — for example `x := 1` -# scope: document - -# METADATA -# description: covers case of allow := true, which expands to allow = true { true } -generated_body(rule) if rule.body[0].location == rule.head.value.location - -# METADATA -# description: covers case of default rules -generated_body(rule) if rule["default"] == true - -# METADATA -# description: covers case of rule["message"] or rule contains "message" -generated_body(rule) if { - rule.body[0].location.row == rule.head.key.location.row - - # this is a quirk in the AST — the generated body will have a location - # set before the key, i.e. "message" - rule.body[0].location.col < rule.head.key.location.col -} - -# METADATA -# description: covers case of f("x") -generated_body(rule) if rule.body[0].location == rule.head.location - # METADATA # description: all the rules (excluding functions) in the input AST rules := [rule | @@ -168,7 +141,7 @@ function_calls[rule_index] contains call if { call := { "name": ref_to_string(ref[0].value), - "location": ref[0].location, + "location": util.to_location_object(ref[0].location), "args": args, } } @@ -270,8 +243,7 @@ function_ret_in_args(fn_name, terms) if { } # METADATA -# description: | -# answers if provided rule is implicitly assigned boolean true, i.e. allow { .. } or not +# description: answers if provided rule is implicitly assigned boolean true, i.e. allow { .. } or not # scope: document implicit_boolean_assignment(rule) if { # note the missing location attribute here, which is how we distinguish @@ -279,6 +251,10 @@ implicit_boolean_assignment(rule) if { rule.head.value == {"type": "boolean", "value": true} } +# or sometimes, like this... +implicit_boolean_assignment(rule) if rule.head.value.location == rule.head.location + +# or like this... implicit_boolean_assignment(rule) if { # This handles the *quite* special case of # `a.b if true`, which is "rewritten" to `a.b = true` *and* where a location is still added to the value @@ -293,6 +269,7 @@ implicit_boolean_assignment(rule) if { # If you write Rego like that — you're not going to use Regal anyway, are you? ¯\_(ツ)_/¯ rule.head.value.type == "boolean" rule.head.value.value == true + rule.head.value.location.col == 1 } @@ -325,8 +302,10 @@ negated_expressions[rule] contains value if { # input.baz # } is_chained_rule_body(rule, lines) if { - row_text := lines[rule.head.location.row - 1] - col_text := substring(row_text, rule.head.location.col - 1, -1) + head_loc := util.to_location_object(rule.head.location) + + row_text := lines[head_loc.row - 1] + col_text := substring(row_text, head_loc.col - 1, -1) startswith(col_text, "{") } diff --git a/bundle/regal/ast/ast_test.rego b/bundle/regal/ast/ast_test.rego index a330605b..59d7e523 100644 --- a/bundle/regal/ast/ast_test.rego +++ b/bundle/regal/ast/ast_test.rego @@ -4,6 +4,7 @@ import rego.v1 import data.regal.ast import data.regal.capabilities +import data.regal.util # regal ignore:rule-length test_find_vars if { @@ -138,21 +139,14 @@ allow := true blocks := ast.comment_blocks(module.comments) blocks == [ [ - { - "Location": { - "col": 1, - "row": 3, - "text": "IyBNRVRBREFUQQojIHRpdGxlOiBmb28KIyBiYXI6IGludmFsaWQ=", - }, - "Text": "IE1FVEFEQVRB", - }, - {"Location": {"col": 1, "file": "p.rego", "row": 4}, "Text": "IHRpdGxlOiBmb28="}, - {"Location": {"col": 1, "file": "p.rego", "row": 5}, "Text": "IGJhcjogaW52YWxpZA=="}, + {"location": "3:1:IyBNRVRBREFUQQojIHRpdGxlOiBmb28KIyBiYXI6IGludmFsaWQ=", "text": "IE1FVEFEQVRB"}, + {"location": "4:1:IyB0aXRsZTogZm9v", "text": "IHRpdGxlOiBmb28="}, + {"location": "5:1:IyBiYXI6IGludmFsaWQ=", "text": "IGJhcjogaW52YWxpZA=="}, ], - [{"Location": {"col": 1, "file": "p.rego", "row": 8}, "Text": "IG5vdCBtZXRhZGF0YQ=="}], + [{"location": "8:1:IyBub3QgbWV0YWRhdGE=", "text": "IG5vdCBtZXRhZGF0YQ=="}], [ - {"Location": {"col": 1, "file": "p.rego", "row": 10}, "Text": "IGFub3RoZXI="}, - {"Location": {"col": 1, "file": "p.rego", "row": 11}, "Text": "IGJsb2Nr"}, + {"location": "10:1:IyBhbm90aGVy", "text": "IGFub3RoZXI="}, + {"location": "11:1:IyBibG9jaw==", "text": "IGJsb2Nr"}, ], ] } @@ -269,16 +263,6 @@ test_find_some_decl_names_in_scope if { var_names(vars) := {var.value | some var in vars} -test_generated_body_function if { - policy := `package p - - f("x")` - - module := regal.parse_module("p.rego", policy) - - ast.generated_body(module.rules[0]) -} - test_all_refs if { policy := `package policy @@ -295,7 +279,7 @@ test_all_refs if { r := ast.all_refs with input as module - text_refs := {base64.decode(ref.location.text) | some ref in r} + text_refs := {base64.decode(util.to_location_object(ref.location).text) | some ref in r} text_refs == {":=", "data.foo.bar", "data.foo.bax", "data.foo.baz"} } diff --git a/bundle/regal/ast/comments.rego b/bundle/regal/ast/comments.rego index 0e481bd3..461f52eb 100644 --- a/bundle/regal/ast/comments.rego +++ b/bundle/regal/ast/comments.rego @@ -2,11 +2,13 @@ package regal.ast import rego.v1 +import data.regal.util + # METADATA -# description: all comments in the input AST with their "Text" attribute base64 decoded +# description: all comments in the input AST with their `text` attribute base64 decoded comments_decoded := [decoded | some comment in input.comments - decoded := object.union(comment, {"Text": base64.decode(comment.Text)}) + decoded := object.union(comment, {"text": base64.decode(comment.text)}) ] # METADATA @@ -39,14 +41,15 @@ comments["annotation_match"](str) if regex.match( # found in input AST, indexed by the row they're at ignore_directives[row] := rules if { some comment in comments_decoded - text := trim_space(comment.Text) + text := trim_space(comment.text) i := indexof(text, "regal ignore:") i != -1 list := regex.replace(substring(text, i + 13, -1), `\s`, "") + loc := util.to_location_object(comment.location) - row := comment.Location.row + 1 + row := loc.row + 1 rules := split(list, ",") } @@ -57,7 +60,7 @@ ignore_directives[row] := rules if { comment_blocks(comments) := [partition | rows := [row | some comment in comments - row := comment.Location.row + row := util.to_location_object(comment.location).row ] breaks := _splits(rows) diff --git a/bundle/regal/ast/keywords.rego b/bundle/regal/ast/keywords.rego index 9c3ba45f..4058ad55 100644 --- a/bundle/regal/ast/keywords.rego +++ b/bundle/regal/ast/keywords.rego @@ -2,6 +2,8 @@ package regal.ast import rego.v1 +import data.regal.util + keywords[row] contains keyword if { some idx, line in input.regal.file.lines @@ -21,26 +23,29 @@ keywords[row] contains keyword if { } } -keywords[pkg.location.row] contains keyword if { +keywords[loc.row] contains keyword if { pkg := input["package"] + loc := util.to_location_object(pkg.location) keyword := { "name": "package", "location": { - "row": pkg.location.row, - "col": pkg.location.col, + "row": loc.row, + "col": loc.col, }, } } -keywords[imp.location.row] contains keyword if { +keywords[loc.row] contains keyword if { some imp in input.imports + loc := util.to_location_object(imp.location) + keyword := { "name": "import", "location": { - "row": imp.location.row, - "col": imp.location.col, + "row": loc.row, + "col": loc.col, }, } } @@ -48,8 +53,7 @@ keywords[imp.location.row] contains keyword if { keywords[loc.row] contains keyword if { some rule in input.rules - loc := rule.head.location - + loc := util.to_location_object(rule.head.location) col := indexof(base64.decode(loc.text), " contains ") col > 0 @@ -63,37 +67,38 @@ keywords[loc.row] contains keyword if { } } -keywords[value.row] contains keyword if { - some expr in exprs[_] +keywords[loc.row] contains keyword if { + expr := exprs[_][_] walk(expr.terms, [path, value]) - value.col - value.row + regal.last(path) == "location" - name := _keyword_b64s[value.text] + loc := util.to_location_object(value) + name := _keyword_b64s[loc.text] parent_path := array.slice(path, 0, count(path) - 1) context := object.get(expr.terms, parent_path, {}) - some keyword in _determine_keywords(context, value, name) + some keyword in _determine_keywords(context, loc, name) } -keywords[value.row] contains keyword if { +keywords[loc.row] contains keyword if { some rule in input.rules rule.head.assign walk(rule.head.value, [path, value]) - value.col - value.row + regal.last(path) == "location" - name := _keyword_b64s[value.text] + loc := util.to_location_object(value) + + name := _keyword_b64s[loc.text] parent_path := array.slice(path, 0, count(path) - 1) context := object.get(rule.head.value, parent_path, {}) - some keyword in _determine_keywords(context, value, name) + some keyword in _determine_keywords(context, loc, name) } _determine_keywords(_, value, name) := {keyword} if { @@ -109,7 +114,8 @@ _determine_keywords(_, value, name) := {keyword} if { } _determine_keywords(context, value, "every") := keywords if { - text := base64.decode(context.value.location.text) + ctx_loc := util.to_location_object(context.value.location) + text := base64.decode(ctx_loc.text) keywords := { { @@ -123,15 +129,13 @@ _determine_keywords(context, value, "every") := keywords if { "name": "in", "location": { "row": value.row, - "col": (context.value.location.col + count(text)) + 1, + "col": (ctx_loc.col + count(text)) + 1, }, }, } } -_comment_row_index contains comment.Location.row if { - some comment in object.get(input, "comments", []) -} +_comment_row_index contains util.to_location_object(comment.location).row if some comment in input.comments _keyword_b64s := { "aW4=": "in", diff --git a/bundle/regal/ast/keywords_test.rego b/bundle/regal/ast/keywords_test.rego index cd811d3e..5433e09d 100644 --- a/bundle/regal/ast/keywords_test.rego +++ b/bundle/regal/ast/keywords_test.rego @@ -215,7 +215,7 @@ allow if { } _keyword_on_row(kwds, row, keyword) if { - some kwd in object.get(kwds, row, {}) + some kwd in kwds[row] kwd.name == keyword.name kwd.location.row == keyword.location.row diff --git a/bundle/regal/ast/rule_heads.rego b/bundle/regal/ast/rule_head_locations.rego similarity index 67% rename from bundle/regal/ast/rule_heads.rego rename to bundle/regal/ast/rule_head_locations.rego index 29c08097..17cd582b 100644 --- a/bundle/regal/ast/rule_heads.rego +++ b/bundle/regal/ast/rule_head_locations.rego @@ -2,11 +2,13 @@ package regal.ast import rego.v1 +import data.regal.util + # METADATA # description: | # For a given rule head name, this rule contains a list of locations where # there is a rule head with that name. -rule_head_locations[name] contains info if { +rule_head_locations[name] contains {"row": loc.row, "col": loc.col} if { some rule in input.rules name := concat(".", [ @@ -15,8 +17,5 @@ rule_head_locations[name] contains info if { ref_static_to_string(rule.head.ref), ]) - info := { - "row": rule.head.location.row, - "col": rule.head.location.col, - } + loc := util.to_location_object(rule.head.location) } diff --git a/bundle/regal/ast/rule_heads_test.rego b/bundle/regal/ast/rule_head_locations_test.rego similarity index 100% rename from bundle/regal/ast/rule_heads_test.rego rename to bundle/regal/ast/rule_head_locations_test.rego diff --git a/bundle/regal/ast/search.rego b/bundle/regal/ast/search.rego index 4f118350..ffcf7715 100644 --- a/bundle/regal/ast/search.rego +++ b/bundle/regal/ast/search.rego @@ -2,6 +2,8 @@ package regal.ast import rego.v1 +import data.regal.util + _find_nested_vars(obj) := [value | walk(obj, [_, value]) value.type == "var" @@ -223,41 +225,49 @@ find_vars_in_local_scope(rule, location) := [var | var := found.vars[_rule_index(rule)][_][_] # regal ignore:external-reference not startswith(var.value, "$") - _before_location(rule, var, location) + _before_location(rule, var, util.to_location_object(location)) ] _end_location(location) := end if { - lines := split(base64.decode(location.text), "\n") + loc := util.to_location_object(location) + lines := split(base64.decode(loc.text), "\n") end := { - "row": (location.row + count(lines)) - 1, - "col": location.col + count(regal.last(lines)), + "row": (loc.row + count(lines)) - 1, + "col": loc.col + count(regal.last(lines)), } } # special case — the value location of the rule head "sees" # all local variables declared in the rule body _before_location(rule, _, location) if { - value_start := rule.head.value.location - value_end := _end_location(rule.head.value.location) + loc := util.to_location_object(location) + + value_start := util.to_location_object(rule.head.value.location) + value_end := _end_location(util.to_location_object(rule.head.value.location)) - location.row >= value_start.row - location.col >= value_start.col - location.row <= value_end.row - location.col <= value_end.col + loc.row >= value_start.row + loc.col >= value_start.col + loc.row <= value_end.row + loc.col <= value_end.col } -_before_location(_, var, location) if var.location.row < location.row +_before_location(_, var, location) if { + util.to_location_object(var.location).row < util.to_location_object(location).row +} _before_location(_, var, location) if { - var.location.row == location.row - var.location.col < location.col + var_loc := util.to_location_object(var.location) + loc := util.to_location_object(location) + + var_loc.row == loc.row + var_loc.col < loc.col } # METADATA # description: find *only* names in the local scope, and not e.g. rule names find_names_in_local_scope(rule, location) := names if { fn_arg_names := _function_arg_names(rule) - var_names := {var.value | some var in find_vars_in_local_scope(rule, location)} + var_names := {var.value | some var in find_vars_in_local_scope(rule, util.to_location_object(location))} names := fn_arg_names | var_names } @@ -272,7 +282,7 @@ _function_arg_names(rule) := {arg.value | # similar to `find_vars_in_local_scope`, but returns all variable names in scope # of the given location *and* the rule names present in the scope (i.e. module) find_names_in_scope(rule, location) := names if { - locals := find_names_in_local_scope(rule, location) + locals := find_names_in_local_scope(rule, util.to_location_object(location)) # parens below added by opa-fmt :) names := (rule_names | imported_identifiers) | locals diff --git a/bundle/regal/lsp/completion/location/location.rego b/bundle/regal/lsp/completion/location/location.rego index 7e86be91..7d62866d 100644 --- a/bundle/regal/lsp/completion/location/location.rego +++ b/bundle/regal/lsp/completion/location/location.rego @@ -5,6 +5,7 @@ package regal.lsp.completion.location import rego.v1 import data.regal.ast +import data.regal.util # METADATA # description: best-effort helper to determine if the current line is in a rule body @@ -57,8 +58,11 @@ end_location_estimate(location) := end if { # undefined if provided location is not within the range of a rule find_rule(rules, location) := [rule | some i, rule in rules - end_location := end_location_estimate(rule.location) - location.row >= rule.location.row + + start_location := util.to_location_object(rule.location) + end_location := end_location_estimate(start_location) + + location.row >= start_location.row location.row <= end_location.row ][0] diff --git a/bundle/regal/main.rego b/bundle/regal/main.rego index 8ccf2935..2229419a 100644 --- a/bundle/regal/main.rego +++ b/bundle/regal/main.rego @@ -160,11 +160,11 @@ aggregate_report contains violation if { } ignored(violation, directives) if { - ignored_rules := directives[violation.location.row] + ignored_rules := directives[util.to_location_object(violation.location).row] violation.title in ignored_rules } ignored(violation, directives) if { - ignored_rules := directives[violation.location.row + 1] + ignored_rules := directives[util.to_location_object(violation.location).row + 1] violation.title in ignored_rules } diff --git a/bundle/regal/result.rego b/bundle/regal/result.rego index 2af55588..5c071133 100644 --- a/bundle/regal/result.rego +++ b/bundle/regal/result.rego @@ -3,6 +3,7 @@ package regal.result import rego.v1 import data.regal.config +import data.regal.util # METADATA # description: | @@ -175,31 +176,27 @@ resource_urls(related_resources, category) := [r | r := object.union(object.remove(item, ["ref"]), {"ref": config.docs.resolve_url(item.ref, category)}) ] -_with_text(location) := {"location": object.union( - location, - { +_with_text(loc_obj) := loc if { + loc := {"location": object.union(loc_obj, { "file": input.regal.file.name, # regal ignore:external-reference - "text": input.regal.file.lines[location.row - 1], # regal ignore:external-reference - }, -)} if { - location.row -} else := {"location": location} + "text": input.regal.file.lines[loc_obj.row - 1], # regal ignore:external-reference + })} -location(x) := _with_text(x.location) if x.location + loc_obj.row +} else := {"location": loc_obj} -location(x) := _with_text(x[0].location) if is_array(x) +location(x) := _with_text(util.to_location_object(x.location)) -# Special case for comments, where this typo sadly is hard to change at this point -location(x) := _with_text(x.Location) if x.Location +location(x) := _with_text(util.to_location_object(x[0].location)) if is_array(x) # Special case for rule refs, where location is currently only assigned to the value # In this case, we'll just assume that the column is 1, as that's the most likely place # See: https://github.com/open-policy-agent/opa/issues/5790 -location(x) := _with_text(location) if { +location(x) := _with_text(loc_obj) if { not x.location count(x.ref) == 1 x.ref[0].type == "var" - location := object.union(x.value.location, {"col": 1}) + loc_obj := object.union(util.to_location_object(x.value.location), {"col": 1}) } location(x) := {} if { @@ -214,7 +211,7 @@ location(x) := {} if { # value as x.location.row, and `end.col` is the start col + the length of the text # original attribute value base64 decoded from x.location ranged_location_from_text(x) := end if { - otext := base64.decode(x.location.text) + otext := base64.decode(util.to_location_object(x.location).text) lines := split(otext, "\n") loc := location(x) diff --git a/bundle/regal/rules/bugs/annotation_without_metadata.rego b/bundle/regal/rules/bugs/annotation_without_metadata.rego index a706b5c7..9391ef0f 100644 --- a/bundle/regal/rules/bugs/annotation_without_metadata.rego +++ b/bundle/regal/rules/bugs/annotation_without_metadata.rego @@ -6,12 +6,15 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util report contains violation if { some block in ast.comments.blocks - block[0].Location.col == 1 - ast.comments.annotation_match(trim_space(block[0].Text)) + location := util.to_location_object(block[0].location) + + location.col == 1 + ast.comments.annotation_match(trim_space(block[0].text)) violation := result.fail(rego.metadata.chain(), result.location(block[0])) } diff --git a/bundle/regal/rules/bugs/constant_condition.rego b/bundle/regal/rules/bugs/constant_condition.rego index d83eceea..6570eba2 100644 --- a/bundle/regal/rules/bugs/constant_condition.rego +++ b/bundle/regal/rules/bugs/constant_condition.rego @@ -15,7 +15,7 @@ _operators := {"equal", "gt", "gte", "lt", "lte", "neq"} _rules_with_bodies := [rule | some rule in input.rules - not ast.generated_body(rule) + rule.body ] # METADATA diff --git a/bundle/regal/rules/bugs/duplicate_rule.rego b/bundle/regal/rules/bugs/duplicate_rule.rego index 8ac1b7cd..60bd8b92 100644 --- a/bundle/regal/rules/bugs/duplicate_rule.rego +++ b/bundle/regal/rules/bugs/duplicate_rule.rego @@ -15,7 +15,7 @@ report contains violation if { dup_locations := [location | some index in rest - location := input.rules[index].location + location := util.to_location_object(input.rules[index].location) ] violation := result.fail(rego.metadata.chain(), object.union( @@ -36,7 +36,7 @@ message(locations) := sprintf( count(locations) > 1 } -rules_as_text := [base64.decode(rule.location.text) | some rule in input.rules] +rules_as_text := [base64.decode(util.to_location_object(rule.location).text) | some rule in input.rules] duplicates contains indices if { # Remove whitespace from textual representation of rule and create a hash from the result. diff --git a/bundle/regal/rules/bugs/impossible_not.rego b/bundle/regal/rules/bugs/impossible_not.rego index 220c8fb2..6ea5d830 100644 --- a/bundle/regal/rules/bugs/impossible_not.rego +++ b/bundle/regal/rules/bugs/impossible_not.rego @@ -6,6 +6,7 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util package_path := [part.value | some part in input["package"].path] @@ -43,7 +44,9 @@ negated_refs contains negated_ref if { # ignore negated local vars not ref[0].value in ast.function_arg_names(rule) - not ref[0].value in {var.value | some var in ast.find_vars_in_local_scope(rule, value.location)} + not ref[0].value in {var.value | + some var in ast.find_vars_in_local_scope(rule, util.to_location_object(value.location)) + } negated_ref := { "ref": ref, diff --git a/bundle/regal/rules/bugs/inconsistent_args.rego b/bundle/regal/rules/bugs/inconsistent_args.rego index a603f085..13b355c7 100644 --- a/bundle/regal/rules/bugs/inconsistent_args.rego +++ b/bundle/regal/rules/bugs/inconsistent_args.rego @@ -6,6 +6,7 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util report contains violation if { count(ast.functions) > 0 @@ -42,8 +43,8 @@ _args_location(fn) := loc if { # mostly to get the `text` attribute oloc := result.location(fn) - farg := fn.head.args[0].location - larg := regal.last(fn.head.args).location + farg := util.to_location_object(fn.head.args[0].location) + larg := util.to_location_object(regal.last(fn.head.args).location) # use the location of the first and last arg for highlighting loc := object.union(oloc, {"location": { diff --git a/bundle/regal/rules/bugs/invalid_metadata_attribute.rego b/bundle/regal/rules/bugs/invalid_metadata_attribute.rego index 026aa786..2e5f3a72 100644 --- a/bundle/regal/rules/bugs/invalid_metadata_attribute.rego +++ b/bundle/regal/rules/bugs/invalid_metadata_attribute.rego @@ -10,7 +10,7 @@ import data.regal.result report contains violation if { some block in ast.comments.blocks - startswith(trim_space(block[0].Text), "METADATA") + startswith(trim_space(block[0].text), "METADATA") text := _block_to_string(block) attributes := object.keys(yaml.unmarshal(text)) @@ -27,10 +27,10 @@ report contains violation if { _block_to_string(block) := concat("\n", [line | some i, entry in block i > 0 - line := entry.Text + line := entry.text ]) _find_line(block, attribute) := [line | some line in block - startswith(trim_space(line.Text), sprintf("%s:", [attribute])) + startswith(trim_space(line.text), sprintf("%s:", [attribute])) ][0] diff --git a/bundle/regal/rules/bugs/zero_arity_function.rego b/bundle/regal/rules/bugs/zero_arity_function.rego index 6dcc16d8..f509f776 100644 --- a/bundle/regal/rules/bugs/zero_arity_function.rego +++ b/bundle/regal/rules/bugs/zero_arity_function.rego @@ -6,13 +6,14 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util report contains violation if { # notably, not ast.functions, as zero-arity functions are treated # as regular rules (i.e. they have no `args` key in the head) some rule in ast.rules - text := base64.decode(rule.location.text) + text := base64.decode(util.to_location_object(rule.location).text) regex.match(`^[a-zA-z1-9_\.\[\]"]+\(\)`, text) diff --git a/bundle/regal/rules/custom/one_liner_rule.rego b/bundle/regal/rules/custom/one_liner_rule.rego index 9dffbef7..2b45982c 100644 --- a/bundle/regal/rules/custom/one_liner_rule.rego +++ b/bundle/regal/rules/custom/one_liner_rule.rego @@ -8,6 +8,7 @@ import data.regal.ast import data.regal.capabilities import data.regal.config import data.regal.result +import data.regal.util cfg := config.for_rule("custom", "one-liner-rule") @@ -35,7 +36,7 @@ report contains violation if { # Note that this will give us the text representation of the whole rule, # which we'll need as the "if" is only visible here ¯\_(ツ)_/¯ - text := base64.decode(rule.location.text) + text := base64.decode(util.to_location_object(rule.location).text) lines := [line | some s in split(text, "\n") line := trim_space(s) @@ -65,9 +66,14 @@ rule_body_brackets(lines) if { } comment_in_body(rule, comments, lines) if { + rule_location := util.to_location_object(rule.location) + some comment in comments - comment.Location.row > rule.location.row - comment.Location.row < rule.location.row + count(lines) + + comment_location := util.to_location_object(comment.location) + + comment_location.row > rule_location.row + comment_location.row < rule_location.row + count(lines) } default max_line_length := 120 diff --git a/bundle/regal/rules/idiomatic/ambiguous_scope.rego b/bundle/regal/rules/idiomatic/ambiguous_scope.rego index 6fb69bd6..3500ce1c 100644 --- a/bundle/regal/rules/idiomatic/ambiguous_scope.rego +++ b/bundle/regal/rules/idiomatic/ambiguous_scope.rego @@ -50,7 +50,10 @@ _incremental_rules[name] contains rule if { _rule_names := [ast.ref_to_string(rule.head.ref) | some rule in input.rules] _explicit_scope(rule, lines) if { - some i in numbers.range(rule.annotations[0].location.row - 1, rule.head.location.row - 2) + some i in numbers.range( + util.to_location_object(rule.annotations[0].location).row - 1, + util.to_location_object(rule.head.location).row - 2, + ) line := lines[i] startswith(line, "# scope:") diff --git a/bundle/regal/rules/idiomatic/equals_pattern_matching.rego b/bundle/regal/rules/idiomatic/equals_pattern_matching.rego index c605fd34..ee8da3b2 100644 --- a/bundle/regal/rules/idiomatic/equals_pattern_matching.rego +++ b/bundle/regal/rules/idiomatic/equals_pattern_matching.rego @@ -15,8 +15,8 @@ import data.regal.result # f(1) report contains violation if { some fn in ast.functions - ast.generated_body(fn) + not fn.body not fn["else"] arg_var_names := {arg.value | @@ -41,8 +41,8 @@ report contains violation if { # f(1) report contains violation if { some fn in ast.functions - not ast.generated_body(fn) + fn.body not fn["else"] arg_var_names := {arg.value | diff --git a/bundle/regal/rules/idiomatic/no_defined_entrypoint.rego b/bundle/regal/rules/idiomatic/no_defined_entrypoint.rego index 1474e46a..2e0b300d 100644 --- a/bundle/regal/rules/idiomatic/no_defined_entrypoint.rego +++ b/bundle/regal/rules/idiomatic/no_defined_entrypoint.rego @@ -5,12 +5,13 @@ package regal.rules.idiomatic["no-defined-entrypoint"] import rego.v1 import data.regal.result +import data.regal.util aggregate contains entry if { some annotation in input.annotations annotation.entrypoint == true - entry := result.aggregate(rego.metadata.chain(), {"entrypoint": annotation.location}) + entry := result.aggregate(rego.metadata.chain(), {"entrypoint": util.to_location_object(annotation.location)}) } # METADATA diff --git a/bundle/regal/rules/idiomatic/non_raw_regex_pattern.rego b/bundle/regal/rules/idiomatic/non_raw_regex_pattern.rego index 2378b2c2..d3582411 100644 --- a/bundle/regal/rules/idiomatic/non_raw_regex_pattern.rego +++ b/bundle/regal/rules/idiomatic/non_raw_regex_pattern.rego @@ -6,6 +6,7 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util # Mapping of regex.* functions and the position(s) # of their "pattern" attributes @@ -52,7 +53,7 @@ report contains violation if { value[pos].type == "string" - loc := value[pos].location + loc := util.to_location_object(value[pos].location) row := input.regal.file.lines[loc.row - 1] chr := substring(row, loc.col - 1, 1) diff --git a/bundle/regal/rules/idiomatic/prefer_set_or_object_rule.rego b/bundle/regal/rules/idiomatic/prefer_set_or_object_rule.rego index e0d4b55d..bfc7a970 100644 --- a/bundle/regal/rules/idiomatic/prefer_set_or_object_rule.rego +++ b/bundle/regal/rules/idiomatic/prefer_set_or_object_rule.rego @@ -11,7 +11,7 @@ report contains violation if { some rule in ast.rules rule.head.value.type in {"setcomprehension", "objectcomprehension"} - ast.generated_body(rule) + not rule.body # Ignore simple conversions from array to set not is_array_conversion(rule.head.value) diff --git a/bundle/regal/rules/idiomatic/use_contains.rego b/bundle/regal/rules/idiomatic/use_contains.rego index 159725e7..65003bf5 100644 --- a/bundle/regal/rules/idiomatic/use_contains.rego +++ b/bundle/regal/rules/idiomatic/use_contains.rego @@ -7,6 +7,7 @@ import rego.v1 import data.regal.ast import data.regal.capabilities import data.regal.result +import data.regal.util # METADATA # description: Missing capability for keyword `contains` @@ -23,7 +24,7 @@ report contains violation if { rule.head.key not rule.head.value - text := base64.decode(rule.head.location.text) + text := base64.decode(util.to_location_object(rule.head.location).text) not contains(text, " contains ") diff --git a/bundle/regal/rules/idiomatic/use_if.rego b/bundle/regal/rules/idiomatic/use_if.rego index f3f1007b..484445c7 100644 --- a/bundle/regal/rules/idiomatic/use_if.rego +++ b/bundle/regal/rules/idiomatic/use_if.rego @@ -7,6 +7,7 @@ import rego.v1 import data.regal.ast import data.regal.capabilities import data.regal.result +import data.regal.util # METADATA # description: Missing capability for keyword `if` @@ -19,11 +20,10 @@ report contains violation if { not ast.imports_has_path(ast.imports, ["rego", "v1"]) some rule in input.rules + rule.body - not ast.generated_body(rule) - - head_len := count(base64.decode(rule.head.location.text)) - text := trim_space(substring(base64.decode(rule.location.text), head_len, -1)) + head_len := count(base64.decode(util.to_location_object(rule.head.location).text)) + text := trim_space(substring(base64.decode(util.to_location_object(rule.location).text), head_len, -1)) not startswith(text, "if") diff --git a/bundle/regal/rules/imports/circular_import.rego b/bundle/regal/rules/imports/circular_import.rego index a49ce425..2baca45e 100644 --- a/bundle/regal/rules/imports/circular_import.rego +++ b/bundle/regal/rules/imports/circular_import.rego @@ -11,6 +11,7 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util refs contains ref if { some r in ast.all_refs @@ -21,7 +22,7 @@ refs contains ref if { ref := { "package_path": concat(".", [e.value | some e in r.value]), - "location": object.remove(r.location, {"text"}), + "location": object.remove(util.to_location_object(r.location), {"text"}), } } @@ -91,13 +92,13 @@ package_locations[referenced_pkg][referencing_pkg] contains location if { some ref in ag_pkg.aggregate_data.refs referenced_pkg := ref.package_path - referencing_pkg := sprintf("data.%s", [concat(".", ag_pkg.aggregate_source.package_path)]) + ref_loc := util.to_location_object(ref.location) location := { "file": ag_pkg.aggregate_source.file, - "row": ref.location.row, - "col": ref.location.col, + "row": ref_loc.row, + "col": ref_loc.col, } } diff --git a/bundle/regal/rules/imports/import_after_rule.rego b/bundle/regal/rules/imports/import_after_rule.rego index 62caf03d..e8ed2089 100644 --- a/bundle/regal/rules/imports/import_after_rule.rego +++ b/bundle/regal/rules/imports/import_after_rule.rego @@ -5,13 +5,14 @@ package regal.rules.imports["import-after-rule"] import rego.v1 import data.regal.result +import data.regal.util report contains violation if { - first_rule_row := input.rules[0].location.row + first_rule_row := util.to_location_object(input.rules[0].location).row some imp in input.imports - imp.location.row > first_rule_row + util.to_location_object(imp.location).row > first_rule_row violation := result.fail(rego.metadata.chain(), result.location(imp)) } diff --git a/bundle/regal/rules/style/default_over_else.rego b/bundle/regal/rules/style/default_over_else.rego index f2de6148..dc185dff 100644 --- a/bundle/regal/rules/style/default_over_else.rego +++ b/bundle/regal/rules/style/default_over_else.rego @@ -18,14 +18,9 @@ report contains violation if { # the rule if there isn't a single `else` present though! walk(rule["else"], [_, value]) - else_body := value.body else_head := value.head - # we don't know for sure, but if all that's in the body is an empty - # `true`, it's likely an implicit body (i.e. one not printed) - count(else_body) == 1 - else_body[0].terms.type == "boolean" - else_body[0].terms.value == true + not value.body ast.is_constant(else_head.value) diff --git a/bundle/regal/rules/style/default_over_not.rego b/bundle/regal/rules/style/default_over_not.rego index 66006468..1995290d 100644 --- a/bundle/regal/rules/style/default_over_not.rego +++ b/bundle/regal/rules/style/default_over_not.rego @@ -14,7 +14,7 @@ report contains violation if { # example: `rule := input.foo` not rule["default"] - ast.generated_body(rule) + not rule.body name := _static_rule_name(rule) value := rule.head.value diff --git a/bundle/regal/rules/style/detached_metadata.rego b/bundle/regal/rules/style/detached_metadata.rego index e3dfb59a..5440645c 100644 --- a/bundle/regal/rules/style/detached_metadata.rego +++ b/bundle/regal/rules/style/detached_metadata.rego @@ -6,18 +6,19 @@ import rego.v1 import data.regal.ast import data.regal.result +import data.regal.util report contains violation if { some block in ast.comments.blocks - startswith(trim_space(block[0].Text), "METADATA") + startswith(trim_space(block[0].text), "METADATA") - last_row := regal.last(block).Location.row + last_row := util.to_location_object(regal.last(block).location).row # no need to +1 the index here as rows start counting from 1 trim_space(input.regal.file.lines[last_row]) == "" - annotation := annotation_at_row(block[0].Location.row) + annotation := annotation_at_row(util.to_location_object(block[0].location).row) annotation.scope != "document" violation := result.fail(rego.metadata.chain(), result.location(block[0])) @@ -26,5 +27,5 @@ report contains violation if { annotation_at_row(row) := annotation if { some annotation in input.annotations - annotation.location.row == row + util.to_location_object(annotation.location).row == row } diff --git a/bundle/regal/rules/style/no_whitespace_comment.rego b/bundle/regal/rules/style/no_whitespace_comment.rego index 8987241a..fca53f8e 100644 --- a/bundle/regal/rules/style/no_whitespace_comment.rego +++ b/bundle/regal/rules/style/no_whitespace_comment.rego @@ -11,7 +11,7 @@ import data.regal.result report contains violation if { some comment in ast.comments_decoded - not _whitespace_comment(comment.Text) + not _whitespace_comment(comment.text) violation := result.fail(rego.metadata.chain(), result.location(comment)) } diff --git a/bundle/regal/rules/style/pointless_reassignment.rego b/bundle/regal/rules/style/pointless_reassignment.rego index 8f7e112c..033d6a43 100644 --- a/bundle/regal/rules/style/pointless_reassignment.rego +++ b/bundle/regal/rules/style/pointless_reassignment.rego @@ -11,7 +11,7 @@ import data.regal.result report contains violation if { some rule in ast.rules - ast.generated_body(rule) + not rule.body rule.head.value.type == "var" count(rule.head.ref) == 1 diff --git a/bundle/regal/rules/style/prefer_some_in_iteration.rego b/bundle/regal/rules/style/prefer_some_in_iteration.rego index dc8717e0..5d286018 100644 --- a/bundle/regal/rules/style/prefer_some_in_iteration.rego +++ b/bundle/regal/rules/style/prefer_some_in_iteration.rego @@ -14,9 +14,9 @@ cfg := config.for_rule("style", "prefer-some-in-iteration") report contains violation if { some i, rule in input.rules - node := filter_top_level_ref(rule) + not possible_top_level_iteration(rule) - walk(node, [path, value]) + walk(rule, [path, value]) value.type == "ref" @@ -56,9 +56,10 @@ has_sub_attribute(ref) if { # don't walk top level iteration refs: # https://docs.styra.com/regal/rules/bugs/top-level-iteration -filter_top_level_ref(rule) := rule.body if { +possible_top_level_iteration(rule) if { + not rule.body rule.head.value.type == "ref" -} else := rule +} # don't recommend `some .. in` if iteration occurs inside of arrays, objects, or sets invalid_some_context(rule, path) if { diff --git a/bundle/regal/rules/style/prefer_some_in_iteration_test.rego b/bundle/regal/rules/style/prefer_some_in_iteration_test.rego index 20aab201..5f07d303 100644 --- a/bundle/regal/rules/style/prefer_some_in_iteration_test.rego +++ b/bundle/regal/rules/style/prefer_some_in_iteration_test.rego @@ -281,6 +281,18 @@ test_success_iteration_in_args_call_in_comprehension_head if { r == set() } +test_success_top_level_iteration if { + policy := ast.with_rego_v1(`r := input.foo[_]`) + + r := rule.report with config.for_rule as { + "level": "error", + "ignore-nesting-level": 2, + } + with input as policy + with data.internal.combined_config as {"capabilities": capabilities.provided} + r == set() +} + allow_nesting(i) := { "level": "error", "ignore-nesting-level": i, diff --git a/bundle/regal/rules/style/rule_length.rego b/bundle/regal/rules/style/rule_length.rego index ec18eec3..a316da3b 100644 --- a/bundle/regal/rules/style/rule_length.rego +++ b/bundle/regal/rules/style/rule_length.rego @@ -4,15 +4,15 @@ package regal.rules.style["rule-length"] import rego.v1 -import data.regal.ast import data.regal.config import data.regal.result +import data.regal.util cfg := config.for_rule("style", "rule-length") report contains violation if { some rule in input.rules - lines := split(base64.decode(rule.location.text), "\n") + lines := split(base64.decode(util.to_location_object(rule.location).text), "\n") line_count(cfg, rule, lines) > cfg["max-rule-length"] @@ -23,7 +23,7 @@ report contains violation if { generated_body_exception(conf, rule) if { conf["except-empty-body"] == true - ast.generated_body(rule) + not rule.body } line_count(cfg, _, lines) := count(lines) if cfg["count-comments"] == true @@ -32,7 +32,7 @@ line_count(cfg, rule, lines) := n if { not cfg["count-comments"] # Note that this assumes } on its own line - body_start := rule.location.row + 1 + body_start := util.to_location_object(rule.location).row + 1 body_end := (body_start + count(lines)) - 3 body_total := (body_end - body_start) + 1 @@ -41,8 +41,10 @@ line_count(cfg, rule, lines) := n if { body_comments := sum([1 | some comment in input.comments - comment.Location.row >= body_start - comment.Location.row <= body_end + loc := util.to_location_object(comment.location) + + loc.row >= body_start + loc.row <= body_end ]) n := body_total - body_comments diff --git a/bundle/regal/rules/style/todo_comment.rego b/bundle/regal/rules/style/todo_comment.rego index 53bab13a..e0fc6495 100644 --- a/bundle/regal/rules/style/todo_comment.rego +++ b/bundle/regal/rules/style/todo_comment.rego @@ -17,7 +17,7 @@ todo_pattern := sprintf(`^\s*(%s)`, [concat("|", todo_identifiers)]) report contains violation if { some comment in ast.comments_decoded - regex.match(todo_pattern, comment.Text) + regex.match(todo_pattern, comment.text) violation := result.fail(rego.metadata.chain(), result.location(comment)) } diff --git a/bundle/regal/rules/style/use_assignment_operator.rego b/bundle/regal/rules/style/use_assignment_operator.rego index d1b5eae9..af46ff4a 100644 --- a/bundle/regal/rules/style/use_assignment_operator.rego +++ b/bundle/regal/rules/style/use_assignment_operator.rego @@ -48,12 +48,11 @@ report contains violation if { # would be cached on the second invocation of the function walk(rule["else"], [_, value]) + loc := result.location(value.head) + # extract the text from location to see if '=' is used for # assignment - text := base64.decode(value.head.location.text) - regex.match(`^else\s*=`, text) - - loc := result.location(value.head) + regex.match(`else\s*=`, loc.location.text) violation := result.fail(rego.metadata.chain(), object.union(loc, {"location": {"col": eq_col(loc)}})) } diff --git a/bundle/regal/util/util.rego b/bundle/regal/util/util.rego index 0452d3ef..7e767f2a 100644 --- a/bundle/regal/util/util.rego +++ b/bundle/regal/util/util.rego @@ -42,3 +42,10 @@ keys_to_numbers(obj) := {num: v | some k, v in obj num := to_number(k) } + +to_location_object(loc) := {"row": to_number(row), "col": to_number(col), "text": text} if { + is_string(loc) + [row, col, text] := split(loc, ":") +} + +to_location_object(loc) := loc if is_object(loc) diff --git a/cmd/capabilities.go b/cmd/capabilities.go index 519879f2..bb3c7300 100644 --- a/cmd/capabilities.go +++ b/cmd/capabilities.go @@ -1,10 +1,10 @@ package cmd import ( - "encoding/json" "fmt" "os" + "github.com/anderseknert/roast/pkg/encoding" "github.com/spf13/cobra" "github.com/styrainc/regal/internal/compile" @@ -17,7 +17,7 @@ func init() { Short: "Print the capabilities of Regal", Long: "Show capabilities for Regal", RunE: func(*cobra.Command, []string) error { - bs, err := json.MarshalIndent(compile.Capabilities(), "", " ") + bs, err := encoding.JSON().MarshalIndent(compile.Capabilities(), "", " ") if err != nil { return fmt.Errorf("failed marshalling capabilities: %w", err) } diff --git a/cmd/parse.go b/cmd/parse.go index 0940f978..6e1321fb 100644 --- a/cmd/parse.go +++ b/cmd/parse.go @@ -2,11 +2,11 @@ package cmd import ( - "encoding/json" "errors" "log" "os" + "github.com/anderseknert/roast/pkg/encoding" "github.com/spf13/cobra" "github.com/open-policy-agent/opa/ast" @@ -63,7 +63,7 @@ func parse(args []string) error { return err } - bs, err = json.MarshalIndent(enhancedAST, "", " ") + bs, err = encoding.JSON().MarshalIndent(enhancedAST, "", " ") if err != nil { return err } diff --git a/cmd/version.go b/cmd/version.go index 9ef10a2c..3259a735 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,11 +1,11 @@ package cmd import ( - "encoding/json" "fmt" "log" "os" + "github.com/anderseknert/roast/pkg/encoding" "github.com/spf13/cobra" "github.com/styrainc/regal/pkg/version" @@ -38,7 +38,7 @@ func init() { switch params.format { case formatJSON: - e := json.NewEncoder(os.Stdout) + e := encoding.JSON().NewEncoder(os.Stdout) e.SetIndent("", " ") err := e.Encode(vi) if err != nil { diff --git a/go.mod b/go.mod index 4f325d1c..ea11565c 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ module github.com/styrainc/regal -go 1.22 - -toolchain go1.22.0 +go 1.22.5 require ( dario.cat/mergo v1.0.1 + github.com/anderseknert/roast v0.1.0 github.com/fatih/color v1.17.0 github.com/fsnotify/fsnotify v1.7.0 github.com/gobwas/glob v0.2.3 @@ -13,7 +12,7 @@ require ( github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/mitchellh/mapstructure v1.5.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/open-policy-agent/opa v0.67.0 + github.com/open-policy-agent/opa v0.67.1 github.com/owenrumney/go-sarif/v2 v2.3.3 github.com/pdevine/go-asciisprite v0.1.6 github.com/pkg/profile v1.7.0 @@ -28,28 +27,35 @@ require ( github.com/agnivade/levenshtein v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/fgprof v0.9.3 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/tcell v1.1.4 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/lucasb-eyer/go-colorful v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.10 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.20.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect - github.com/rivo/uniseg v0.1.0 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -59,8 +65,12 @@ require ( go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240820151423-278611b39280 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240820151423-278611b39280 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index b97bc381..0122e657 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/anderseknert/roast v0.1.0 h1:PE1KAcrhMEYzsjGmouOqn0qSqdPd+s8N5/e+eHK4y4c= +github.com/anderseknert/roast v0.1.0/go.mod h1:ViJIrrLZLl3+EbjYzsr8G60UfRhaMtN3dwDBlS8OD4o= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= @@ -32,8 +34,8 @@ github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWa github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= @@ -61,8 +63,8 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -78,6 +80,7 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -86,15 +89,17 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report/v2 v2.1.0 h1:X3+hPYlSczH9IMIpSC9CQSZA0L+BipYafciZUWHEmsc= github.com/jstemmer/go-junit-report/v2 v2.1.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -112,16 +117,24 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/open-policy-agent/opa v0.67.0 h1:FOdsO9yNhfmrh+72oVK7ImWmzruG+VSpfbr5IBqEWVs= -github.com/open-policy-agent/opa v0.67.0/go.mod h1:aqKlHc8E2VAAylYE9x09zJYr/fYzGX+JKne89UGqFzk= +github.com/open-policy-agent/opa v0.67.1 h1:rzy26J6g1X+CKknAcx0Vfbt41KqjuSzx4E0A8DAZf3E= +github.com/open-policy-agent/opa v0.67.1/go.mod h1:aqKlHc8E2VAAylYE9x09zJYr/fYzGX+JKne89UGqFzk= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= github.com/owenrumney/go-sarif/v2 v2.3.3 h1:ubWDJcF5i3L/EIOER+ZyQ03IfplbSU1BLOE26uKQIIU= github.com/owenrumney/go-sarif/v2 v2.3.3/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w= @@ -134,18 +147,20 @@ github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDj github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= +github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -159,6 +174,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -194,14 +210,14 @@ go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVf go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -209,21 +225,21 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240820151423-278611b39280 h1:YDFM9oOjiFhaMAVgbDxfxW+66nRrsvzQzJ51wp3OxC0= +google.golang.org/genproto/googleapis/api v0.0.0-20240820151423-278611b39280/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240820151423-278611b39280 h1:XQMA2e105XNlEZ8NRF0HqnUOZzP14sUSsgL09kpdNnU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240820151423-278611b39280/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= diff --git a/internal/embeds/schemas/regal-ast.json b/internal/embeds/schemas/regal-ast.json index 2b323551..0dc624b4 100644 --- a/internal/embeds/schemas/regal-ast.json +++ b/internal/embeds/schemas/regal-ast.json @@ -198,11 +198,11 @@ }, "comment": { "properties": { - "Text": { + "text": { "type": "string", "contentEncoding": "base64" }, - "Location": { + "location": { "$ref": "#/$defs/location" } }, @@ -270,27 +270,7 @@ "type": "object" }, "location": { - "properties": { - "file": { - "type": "string" - }, - "row": { - "type": "integer" - }, - "col": { - "type": "integer" - }, - "text": { - "type": "string" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "file", - "row", - "col" - ] + "type": "string" }, "package": { "properties": { diff --git a/internal/io/io.go b/internal/io/io.go index e7760c07..5da83216 100644 --- a/internal/io/io.go +++ b/internal/io/io.go @@ -1,15 +1,13 @@ package io import ( - "encoding/json" "fmt" - "io" files "io/fs" "log" "os" "strings" - "gopkg.in/yaml.v3" + "github.com/anderseknert/roast/pkg/encoding" "github.com/open-policy-agent/opa/bundle" "github.com/open-policy-agent/opa/loader/filter" @@ -73,6 +71,8 @@ func ToMap(a any) map[string]any { // JSONRoundTrip convert any value to JSON and back again. func JSONRoundTrip(from any, to any) error { + json := encoding.JSON() + bs, err := json.Marshal(from) if err != nil { return fmt.Errorf("failed JSON marshalling %w", err) @@ -88,15 +88,6 @@ func MustJSONRoundTrip(from any, to any) { } } -// MustYAMLToMap creates a map from reader, expecting YAML content, or fail. -func MustYAMLToMap(from io.Reader) (m map[string]any) { - if err := yaml.NewDecoder(from).Decode(&m); err != nil { - log.Fatal(err) - } - - return m -} - // CloseFileIgnore closes file ignoring errors, mainly for deferred cleanup. func CloseFileIgnore(file *os.File) { _ = file.Close() diff --git a/internal/lsp/completions/providers/policy_test.go b/internal/lsp/completions/providers/policy_test.go index dfdc6de3..47a94a0f 100644 --- a/internal/lsp/completions/providers/policy_test.go +++ b/internal/lsp/completions/providers/policy_test.go @@ -7,10 +7,13 @@ import ( "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/storage/inmem" + rio "github.com/styrainc/regal/internal/io" "github.com/styrainc/regal/internal/lsp/cache" "github.com/styrainc/regal/internal/lsp/clients" "github.com/styrainc/regal/internal/lsp/types" "github.com/styrainc/regal/internal/parse" + + _ "github.com/anderseknert/roast/pkg/encoding" ) func TestPolicyProvider_Example1(t *testing.T) { @@ -29,15 +32,19 @@ allow if { module := parse.MustParseModule(policy) c := cache.NewCache() + moduleMap := make(map[string]any) + + rio.MustJSONRoundTrip(module, &moduleMap) + c.SetFileContents(testCaseFileURI, policy) - store := inmem.NewFromObject(map[string]interface{}{ - "workspace": map[string]interface{}{ - "parsed": map[string]interface{}{ - testCaseFileURI: module, + store := inmem.NewFromObjectWithOpts(map[string]any{ + "workspace": map[string]any{ + "parsed": map[string]any{ + testCaseFileURI: moduleMap, }, }, - }) + }, inmem.OptRoundTripOnWrite(false)) locals := NewPolicy(store) diff --git a/internal/lsp/connection.go b/internal/lsp/connection.go index e9642d6d..e24c5d0a 100644 --- a/internal/lsp/connection.go +++ b/internal/lsp/connection.go @@ -23,11 +23,11 @@ package lsp import ( "context" - "encoding/json" "fmt" "io" "sync" + "github.com/anderseknert/roast/pkg/encoding" "github.com/sourcegraph/jsonrpc2" ) @@ -140,6 +140,8 @@ func buildRecvHandler( cfg ConnectionLoggingConfig, ) func(req *jsonrpc2.Request, resp *jsonrpc2.Response) { return func(req *jsonrpc2.Request, resp *jsonrpc2.Response) { + json := encoding.JSON() + switch { case req != nil && resp == nil: setMethod(req.ID, req.Method) @@ -186,6 +188,8 @@ func buildSendHandler( cfg ConnectionLoggingConfig, ) func(req *jsonrpc2.Request, resp *jsonrpc2.Response) { return func(req *jsonrpc2.Request, resp *jsonrpc2.Response) { + json := encoding.JSON() + switch { case req != nil && resp == nil: if !cfg.ShouldLog(req.Method) { diff --git a/internal/lsp/eval.go b/internal/lsp/eval.go index b28205dd..ac06f4dc 100644 --- a/internal/lsp/eval.go +++ b/internal/lsp/eval.go @@ -2,7 +2,6 @@ package lsp import ( "context" - "encoding/json" "errors" "fmt" "io" @@ -11,6 +10,8 @@ import ( "path/filepath" "strings" + "github.com/anderseknert/roast/pkg/encoding" + "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/bundle" "github.com/open-policy-agent/opa/rego" @@ -77,6 +78,8 @@ func (l *LanguageServer) Eval( return nil, fmt.Errorf("failed reading input: %w", err) } + json := encoding.JSON() + err = json.Unmarshal(in, &inputMap) if err != nil { return nil, fmt.Errorf("failed unmarshalling input: %w", err) diff --git a/internal/lsp/examples/examples.go b/internal/lsp/examples/examples.go index d3749b96..60204d66 100644 --- a/internal/lsp/examples/examples.go +++ b/internal/lsp/examples/examples.go @@ -1,9 +1,10 @@ package examples import ( - "encoding/json" "fmt" + "github.com/anderseknert/roast/pkg/encoding" + _ "embed" ) @@ -44,6 +45,8 @@ var index *indexData func init() { index = &indexData{} + json := encoding.JSON() + if err := json.Unmarshal(indexJSON, index); err != nil { panic("failed to unmarshal built-in index: " + err.Error()) } diff --git a/internal/lsp/lint.go b/internal/lsp/lint.go index ab975764..368c133f 100644 --- a/internal/lsp/lint.go +++ b/internal/lsp/lint.go @@ -2,11 +2,12 @@ package lsp import ( "context" - "encoding/json" "errors" "fmt" "strings" + "github.com/anderseknert/roast/pkg/encoding" + "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/storage" @@ -83,6 +84,8 @@ func updateParse(ctx context.Context, cache *cache.Cache, store storage.Store, f Location: parseError.Location, }) } else { + json := encoding.JSON() + jsonErrors, err := json.Marshal(unwrappedError) if err != nil { return false, fmt.Errorf("failed to marshal parse errors: %w", err) diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 0a5f6d5f..b12ef616 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -3,7 +3,6 @@ package lsp import ( "context" - "encoding/json" "errors" "fmt" "io" @@ -14,6 +13,7 @@ import ( "sync" "time" + "github.com/anderseknert/roast/pkg/encoding" "github.com/sourcegraph/jsonrpc2" "gopkg.in/yaml.v3" @@ -564,6 +564,8 @@ func (l *LanguageServer) StartCommandWorker(ctx context.Context) { value = make(map[string]any) } + json := encoding.JSON() + jsonVal, err = json.MarshalIndent(value, "", " ") if err == nil { // staticcheck thinks err here is never used, but I think that's false? @@ -809,6 +811,9 @@ func (l *LanguageServer) handleTextDocumentHover( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentHoverParams + + json := encoding.JSON() + if err := json.Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -926,7 +931,7 @@ func (l *LanguageServer) handleTextDocumentCodeAction( req *jsonrpc2.Request, ) (result any, err error) { var params types.CodeActionParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1007,7 +1012,8 @@ func (l *LanguageServer) handleWorkspaceExecuteCommand( req *jsonrpc2.Request, ) (result any, err error) { var params types.ExecuteCommandParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1027,7 +1033,8 @@ func (l *LanguageServer) handleTextDocumentInlayHint( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentInlayHintParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1066,7 +1073,7 @@ func (l *LanguageServer) handleTextDocumentCodeLens( req *jsonrpc2.Request, ) (result any, err error) { var params types.CodeLensParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1144,7 +1151,7 @@ func (l *LanguageServer) handleTextDocumentCompletion( req *jsonrpc2.Request, ) (any, error) { var params types.CompletionParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1217,7 +1224,7 @@ func (l *LanguageServer) handleWorkspaceSymbol( req *jsonrpc2.Request, ) (result any, err error) { var params types.WorkspaceSymbolParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1248,7 +1255,7 @@ func (l *LanguageServer) handleTextDocumentDefinition( req *jsonrpc2.Request, ) (result any, err error) { var params types.DefinitionParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1304,7 +1311,7 @@ func (l *LanguageServer) handleTextDocumentDidOpen( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentDidOpenParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1338,7 +1345,7 @@ func (l *LanguageServer) handleTextDocumentDidClose( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentDidCloseParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1357,7 +1364,7 @@ func (l *LanguageServer) handleTextDocumentDidChange( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentDidChangeParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1394,7 +1401,7 @@ func (l *LanguageServer) handleTextDocumentDidSave( req *jsonrpc2.Request, ) (result any, err error) { var params types.TextDocumentDidSaveParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1444,7 +1451,7 @@ func (l *LanguageServer) handleTextDocumentDocumentSymbol( req *jsonrpc2.Request, ) (result any, err error) { var params types.DocumentSymbolParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1475,7 +1482,7 @@ func (l *LanguageServer) handleTextDocumentFoldingRange( req *jsonrpc2.Request, ) (result any, err error) { var params types.FoldingRangeParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1498,7 +1505,7 @@ func (l *LanguageServer) handleTextDocumentFormatting( req *jsonrpc2.Request, ) (result any, err error) { var params types.DocumentFormattingParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1603,7 +1610,7 @@ func (l *LanguageServer) handleWorkspaceDidCreateFiles( req *jsonrpc2.Request, ) (result any, err error) { var params types.WorkspaceDidCreateFilesParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1639,7 +1646,7 @@ func (l *LanguageServer) handleWorkspaceDidDeleteFiles( req *jsonrpc2.Request, ) (result any, err error) { var params types.WorkspaceDidDeleteFilesParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1667,7 +1674,7 @@ func (l *LanguageServer) handleWorkspaceDidRenameFiles( req *jsonrpc2.Request, ) (result any, err error) { var params types.WorkspaceDidRenameFilesParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1733,7 +1740,7 @@ func (l *LanguageServer) handleInitialize( req *jsonrpc2.Request, ) (any, error) { var params types.InitializeParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } @@ -1941,7 +1948,7 @@ func (l *LanguageServer) handleWorkspaceDidChangeWatchedFiles( } var params types.WorkspaceDidChangeWatchedFilesParams - if err := json.Unmarshal(*req.Params, ¶ms); err != nil { + if err := encoding.JSON().Unmarshal(*req.Params, ¶ms); err != nil { return nil, fmt.Errorf("failed to unmarshal params: %w", err) } diff --git a/internal/lsp/server_test.go b/internal/lsp/server_test.go index 661a88c1..7be7ee72 100644 --- a/internal/lsp/server_test.go +++ b/internal/lsp/server_test.go @@ -3,7 +3,6 @@ package lsp import ( "bytes" "context" - "encoding/json" "fmt" "io" "net" @@ -15,6 +14,7 @@ import ( "testing" "time" + "github.com/anderseknert/roast/pkg/encoding" "github.com/sourcegraph/jsonrpc2" "github.com/styrainc/regal/internal/lsp/types" @@ -103,7 +103,7 @@ allow = true if req.Method == methodTextDocumentPublishDiagnostics { var requestData types.FileDiagnostics - err = json.Unmarshal(*req.Params, &requestData) + err = encoding.JSON().Unmarshal(*req.Params, &requestData) if err != nil { t.Fatalf("failed to unmarshal diagnostics: %s", err) } @@ -354,7 +354,7 @@ ignore: var requestData types.FileDiagnostics - err = json.Unmarshal(*req.Params, &requestData) + err = encoding.JSON().Unmarshal(*req.Params, &requestData) if err != nil { t.Fatalf("failed to unmarshal diagnostics: %s", err) } @@ -586,7 +586,7 @@ allow := true if req.Method == methodTextDocumentPublishDiagnostics { var requestData types.FileDiagnostics - err = json.Unmarshal(*req.Params, &requestData) + err = encoding.JSON().Unmarshal(*req.Params, &requestData) if err != nil { t.Fatalf("failed to unmarshal diagnostics: %s", err) } @@ -726,10 +726,10 @@ func createConnections( ) cleanup := func() { - netConnServer.Close() - netConnClient.Close() - connServer.Close() - connClient.Close() + _ = netConnServer.Close() + _ = netConnClient.Close() + _ = connServer.Close() + _ = connClient.Close() } return connServer, connClient, cleanup diff --git a/internal/lsp/store.go b/internal/lsp/store.go index a038cd46..d8d13b7d 100644 --- a/internal/lsp/store.go +++ b/internal/lsp/store.go @@ -11,9 +11,9 @@ import ( ) func NewRegalStore() storage.Store { - return inmem.NewFromObject(map[string]interface{}{ - "workspace": map[string]interface{}{ - "parsed": map[string]interface{}{}, + return inmem.NewFromObject(map[string]any{ + "workspace": map[string]any{ + "parsed": map[string]any{}, "defined_refs": map[string][]string{}, }, }) diff --git a/internal/parse/parse.go b/internal/parse/parse.go index 732caefd..58356eff 100644 --- a/internal/parse/parse.go +++ b/internal/parse/parse.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/open-policy-agent/opa/ast" - "github.com/open-policy-agent/opa/ast/json" rio "github.com/styrainc/regal/internal/io" ) @@ -14,26 +13,6 @@ import ( func ParserOptions() ast.ParserOptions { return ast.ParserOptions{ ProcessAnnotation: true, - JSONOptions: &json.Options{ - MarshalOptions: json.MarshalOptions{ - IncludeLocation: json.NodeToggle{ - Term: true, - Package: true, - Comment: true, - Import: true, - Rule: true, - Head: true, - Expr: true, - SomeDecl: true, - Every: true, - With: true, - Annotations: true, - AnnotationsRef: true, - }, - IncludeLocationText: true, - ExcludeLocationFile: true, - }, - }, } } diff --git a/internal/update/update.go b/internal/update/update.go index 602bccc0..630e168a 100644 --- a/internal/update/update.go +++ b/internal/update/update.go @@ -3,7 +3,6 @@ package update import ( "context" - "encoding/json" "fmt" "io" "net/http" @@ -13,6 +12,8 @@ import ( "strings" "time" + "github.com/anderseknert/roast/pkg/encoding" + "github.com/open-policy-agent/opa/rego" _ "embed" @@ -115,6 +116,8 @@ func getLatestVersion(ctx context.Context, opts Options) (string, error) { return "", fmt.Errorf("failed to open file: %w", err) } + json := encoding.JSON() + err = json.NewDecoder(file).Decode(&preExistingState) if err != nil { return "", fmt.Errorf("failed to decode existing version state file: %w", err) @@ -164,6 +167,8 @@ func getLatestVersion(ctx context.Context, opts Options) (string, error) { TagName string `json:"tag_name"` } + json := encoding.JSON() + err = json.NewDecoder(resp.Body).Decode(&responseData) if err != nil { return "", fmt.Errorf("failed to decode response: %w", err) diff --git a/pkg/builtins/builtins.go b/pkg/builtins/builtins.go index 55c24c69..5ad7dcd0 100644 --- a/pkg/builtins/builtins.go +++ b/pkg/builtins/builtins.go @@ -3,9 +3,10 @@ package builtins import ( "bytes" - "encoding/json" "errors" + "github.com/anderseknert/roast/pkg/encoding" + "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/tester" @@ -61,6 +62,8 @@ func RegalParseModule(_ rego.BuiltinContext, filename *ast.Term, policy *ast.Ter return nil, err } + json := encoding.JSON() + var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(&enhancedAST); err != nil { return nil, err diff --git a/pkg/config/config.go b/pkg/config/config.go index 08ec6ffd..92b4fd7e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,13 +1,13 @@ package config import ( - "encoding/json" "errors" "fmt" "os" "path/filepath" "strings" + "github.com/anderseknert/roast/pkg/encoding" "gopkg.in/yaml.v3" "github.com/open-policy-agent/opa/ast" @@ -285,6 +285,7 @@ func (config *Config) UnmarshalYAML(value *yaml.Node) error { } opaCaps := ast.Capabilities{} + json := encoding.JSON() err = json.Unmarshal(bs, &opaCaps) if err != nil { @@ -469,11 +470,16 @@ func (rule Rule) MarshalJSON() ([]byte, error) { return nil, fmt.Errorf("marshalling rule failed %w", err) } + json := encoding.JSON() + return json.Marshal(&result) //nolint:wrapcheck } func (rule *Rule) UnmarshalJSON(data []byte) error { var result map[string]any + + json := encoding.JSON() + if err := json.Unmarshal(data, &result); err != nil { return fmt.Errorf("unmarshalling rule failed %w", err) } diff --git a/pkg/linter/linter.go b/pkg/linter/linter.go index d5048d62..cfb992de 100644 --- a/pkg/linter/linter.go +++ b/pkg/linter/linter.go @@ -208,7 +208,7 @@ func (l Linter) WithProfiling(enabled bool) Linter { } // WithRootDir sets the root directory for the linter. -// A door directory or prefix can be use to resolve relative paths +// A door directory or prefix can be used to resolve relative paths // referenced in the linter configuration with absolute file paths or URIs. func (l Linter) WithRootDir(rootDir string) Linter { l.rootDir = rootDir diff --git a/pkg/linter/linter_test.go b/pkg/linter/linter_test.go index 659d51c2..785c5a5b 100644 --- a/pkg/linter/linter_test.go +++ b/pkg/linter/linter_test.go @@ -80,9 +80,7 @@ func TestLintWithUserConfig(t *testing.T) { import rego.v1 -boo := input.hoo[_] - -or := 1 +r := input.foo[_] `) userConfig := config.Config{ diff --git a/pkg/reporter/reporter.go b/pkg/reporter/reporter.go index c35ee650..36293474 100644 --- a/pkg/reporter/reporter.go +++ b/pkg/reporter/reporter.go @@ -3,13 +3,13 @@ package reporter import ( "context" - "encoding/json" "fmt" "io" "os" "sort" "strings" + "github.com/anderseknert/roast/pkg/encoding" "github.com/fatih/color" "github.com/jstemmer/go-junit-report/v2/junit" "github.com/olekukonko/tablewriter" @@ -262,7 +262,7 @@ func (tr JSONReporter) Publish(_ context.Context, r report.Report) error { r.Violations = []report.Violation{} } - bs, err := json.MarshalIndent(r, "", " ") + bs, err := encoding.JSON().MarshalIndent(r, "", " ") if err != nil { return fmt.Errorf("json marshalling of report failed: %w", err) }