35 Commits

Author SHA1 Message Date
Johan Fylling b6c3ac1860 ast: Enable future.keywords.not in default capabilities (#8609)
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2026-05-06 14:32:33 +02:00
Johan Fylling 9b330379f7 ast,format,planner: Add not block syntax (#8562)
Expanding the Rego syntax to support not-bodies (not blocks?): `not {...}`

For a not block to successfully evaluate, its body must not successfully evaluate. If evaluation causes iteration, all evaluation paths must fail.

Fixes: #8402

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2026-04-24 16:35:39 +00:00
Johan Fylling 7ecc1fd121 format: Preserve location of trailing comments inside every body (#8559)
Use location text of outer expression to calculate closing location of `every` body (the term itself doesn't capture the full text).

Fixes: #8558

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2026-04-23 18:00:19 +00:00
Anders Eknert 5668e0c707 fmt: don't indent until first with on new line (#8555)
This worked before but got lost in my `with` indentation change.
Now it works again!

Signed-off-by: Anders Eknert <anders.eknert@apple.com>
2026-04-23 11:16:54 +00:00
Sebastian Spaink f60893275c Fix dropping comments after handling unexpectedCommentError (#8553)
Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
2026-04-23 09:47:05 +00:00
Sebastian Spaink 22f8e8d0cd fmt: restore indention level when handling unexpected comments (#8534)
* fmt: restore indention level when handling unexpected comments

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>

* add another test

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>

* support "rego-check-pr" in merge group

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>

---------

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
2026-04-20 14:57:40 +00:00
Sebastian Spaink a7bd374b00 Prevent fmt from formatting single attribute objects with comments (#8519)
Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
2026-04-16 10:09:50 +02:00
Anders Eknert 4b47732f77 fmt: Allow indenting all withs in expression (#8508)
```rego
test_something if {
    something
        with input.foo as 1
        with input.bar as 2
}
```
Would previously be formatted as:
```rego
test_something if {
    something with input.foo as 1
        with input.bar as 2
}
```
Now the formatter allows also the first `with` to be indented
as the rest if the first `with` is found below the line where
the expression begins.

Existing Rego files that have been formatted before should remain
the same when reformatted, and none of the existing formatter tests
have required changes. Only users who actively place the first `with`
in a group on a line below will now see that the formatter respects
their wish, and will indent it the same way as the following `with`s.

Signed-off-by: Anders Eknert <anders.eknert@apple.com>
2026-04-09 18:05:37 +00:00
Sebastian Spaink 918b8cc969 fmt: add new line between METADATA blocks (#8483)
Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
2026-04-03 06:53:36 -05:00
Anders Eknert 4d1dfc4f7c perf: replace regex implementation in IsVarCompatibleString
The allowed pattern is simple enough to check byte-for-byte, and doing
so is much faster, as the benchmarks clearly demonstrate. While
it isnt't a bottleneck by any means, this function is called often
enough (once for every term in any ref serialized) that optimizing
its implementation is warranted, IMO.

Signed-off-by: Anders Eknert <anders.eknert@apple.com>
2026-01-05 10:19:34 +01:00
Anders Eknert b06737bb0b Fix template string not serialized with escaped { (#8161)
Escaping `{` only at the time of serializtion, which should help
avoid special case treatment of these string values. But if there
is a better approach I haven't thought of, let me know.

Fixes #8156

Signed-off-by: Anders Eknert <anders.eknert@apple.com>
2025-12-31 00:04:25 +01:00
Anders Eknert 5a0dc476be Template string performance improvements and more (#8143)
A mixed bag of improvements I have had around for a while, and would
like to see included in v1.12.0 if possible. I have about twice the
amount of changes **not** included here as they could use some more
testing. These changes should be low risk, I believe.. but obviously
do let me know if you see any potential risks that I don't!

- Add template string benchmarks
- Faster template strings / print eval by not passing bctx in recursion
- Allow passing nil value to `Query.WithQueryTracer` (no-op)
- Reduce allocations in rego v1 compiler stages
- Intern a few more common var name `Value`s
- Remove redundant switch on `scope` in annotations code
- Add a few more benchmarks in the `ast` package
- Performance improvements in type checker, most notably removing
  a function literal for checking expression, which only ever had
  one implementation. We can extend this later if needed.
- Prefer `NewGenericTransformer` over `&GenericTransformer` for
  easier tracking in pprof

Signed-off-by: Anders Eknert <anders.eknert@apple.com>
2025-12-18 11:04:18 +00:00
Johan Fylling 8e410b830a String interpolation (#8109)
Adding string interpolation support to the Rego language.

An interpolated string is composed of a template-string that can contain zero or more template-expressions that interpolates values into the string generated at eval-time.

Requires the `template_strings` capability feature and `internal.template_string` built-in function.

Implements: #4733
2025-12-16 11:47:04 +01:00
Anders Eknert c122df1868 Performance improvements in formatter (#7967)
- Use new `util.SlicePool` to avoid cost of temporary slices in `formatTerm`
- Add `SkipDefensiveCopying` option and enable it for all `Source`* functions

```
676179 ns/op    995204 B/op    8850 allocs/op // regression in 0fb7526
513570 ns/op    378787 B/op    8775 allocs/op // addressed regression with sync.Pool
481681 ns/op    352130 B/op    7954 allocs/op // new util.NewSlicePool using only pointers
365116 ns/op    160528 B/op    2098 allocs/op // new SkipDefensiveCopying option
```

Signed-off-by: Anders Eknert <anders@eknert.com>
2025-10-08 14:16:40 +02:00
Ville Vesilehto f77322b3fb build: bump Go version requirement to 1.24 (#7839)
Go 1.23 is no longer supported as per Go release policy.

Changes:

- Use Go v1.24.6 as the project SDK requirement
- Apply lint fixes for Go 1.24
- Fix "non-constant format string in call" issues as seen in CI.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-08-24 09:02:09 +02:00
Johan Fylling 0121d68404 format: Not bracketing keywords in imports (#7744)
Fixing a bug where the formatter would wrap keywords in brackets inside import paths.

Fixes: #7742

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2025-07-02 14:06:25 +02:00
Johan Fylling 817b6635a8 ast,format: Allowing keywords in Rego references (#7709)
Updating the parser and formatter to allow keywords in refs.

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2025-06-25 15:19:21 +02:00
Anders Eknert 78a5ca2ab4 Simplify interning (#7714)
Use a single generic entrypoint for obtaining interned
terms regardless of type.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-06-23 11:40:00 +02:00
Anders Eknert 20fe70e321 perf: more interning (#7636)
This PR adds interning of strings representing common integer values,
which greatly speeds up "to string" operations on numbers, and updates
some built-ins commonly used for this to make use of interned values
where possible.

This is "light" version of a previous PR that did this more aggressively,
but also came with more caveats. Importantly, interning of new strings is
now never done at "runtime", but only allowed at init time. The API for
interning is marked experimental and should not relied upon by anyone
who expects a stable API.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-05-28 23:19:31 +02:00
Anders Eknert 8ba08ac80c Apply modernize linter fixes (#7599)
Following up on #7566, and now applying the more exciting
modernizations. fmt.Appendf was new to me! But especially
the contains checks are so much better IMHO. I have reviewed
all changes myself and did a few manual changes where it
became obvious that things could be improved a little further.

(the modernize analyzer still has some issues running against
OPA, and I have manually worked around those for the time being)

Signed-off-by: Anders Eknert <anders@styra.com>
2025-05-20 23:12:13 +02:00
Anders Eknert e43ef0a979 Use any in place of interface{} (#7566)
Earlier this evening I tried to run the Go
[modernize](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize)
analyzer on OPA. That didn't go as planned:

- https://github.com/golang/go/issues/73661
- https://github.com/golang/go/issues/73663

While we wait for that to be fixed, I figured an old-fashioned
search-and-replace across the repo may work for at least the
`interface{}` to `any` conversion. That should help make it easier
to see the other fixes as applied by the modernize tool once it has
had those issues resolved.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-05-12 13:57:48 +02:00
Sebastian Spaink 24ff9cfb3a fix: return the raw strings when formatting (#7525)
prevent `\u0000` from being changed to `\x00` 

Signed-off-by: sspaink <sspaink@styra.com>
2025-04-25 12:04:16 -05:00
Sebastian Spaink 0fb752607b fix: don't panic on format due to unexpected comments (#7458)
fix: don't panic on format due to unexpected comments

comments next to object elements is valid rego, instead of panicking
catch the error and write the rule as-is.

Signed-off-by: sspaink <sspaink@styra.com>
2025-04-15 08:55:47 -05:00
Anders Eknert b3b87ffd83 fmt: allow one liner rule grouping (#7453)
While the double newline added by the formatter after each rule makes sense
for most rules, short one-liner rules should be groupable. This PR changes
the behavior of the formatter, so that if the user does:

```rego
x := 1
y := 2
```

That is no longer formatted into:

```rego
x := 1

y := 2
```

If the user **wants** double newlines between one-liner rules, the formatter
respects those when present.

Note that the `default` rules are excepted even when a one-liner, as presenting
these separately helps understanding the policy.

Fixes #6760

Do note that the issued mentioned doing this only for incremental rules, i.e.
to group only rules of the same name. I changed my mind on that though, as grouping
"constants" should be possible too.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-03-19 14:35:58 +01:00
Anders Eknert bd5ceb5142 Enable unused-receiver linter (revive) (#7448)
Signed-off-by: Anders Eknert <anders@styra.com>
2025-03-14 11:41:25 +01:00
Johan Fylling e6f040c28a compile: Require multi-term entrypoint paths for optimized bundle building (#7413)
Single term entrypoints has never been supported by OPA, this formalizes that behaviour through error reporting.

Fixes: #7321

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2025-03-05 17:28:57 +01:00
Anders Eknert afb30d3f9d Add gocritic linter, fix a bunch of stuff (#7377)
Brace yourselves! For there are many touched files here. No changes
in semantics however.

Spent a long time trying out the various optional rules gocritic
provides, and settled for a few of them. There are more I really
like, but that would take many hours to address across the codebase.

Perhaps others find gocritic too pedantic? If so, we can merge the
fixes without enabling the rule.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-02-24 16:28:41 +01:00
Anders Eknert 61d3b7b64d perf: cost of indexing greatly reduced (#7370)
And many smaller performance improvements. The indexer recycling results
is one of the most impactful performance improvements as of yet, and alone
saves more than 2 million allocations in the Regal lint benchmark. The indexer
is also more efficient, as `values` are no longer stored on the struct. Thanks
@tsandall for that code!

Also included a bunch of small improvements from my perf branches.

**Before**
```
1209043041 ns/op	3255157224 B/op	64026192 allocs/op
```

**After**
```
1197131792 ns/op	3194124864 B/op	61876276 allocs/op
```

Signed-off-by: Anders Eknert <anders@styra.com>
2025-02-19 11:09:27 +01:00
Anders Eknert cc4783a0cc perf: opa fmt 3x faster formatting (#7341)
We have a Regal rule checking that a file is formatted, making the
performance of the formatter more important than it normally might be.

Since I did some work on this in Regal recently, I was curious to see
if this could be improved. Turned out to be a few bottlenecks that we
could remove with great results. The Regal policies are possibly not
representative for all kinds of Rego, and one thing that stands out is
thay they have a *lot* of metadata annotations. Turned out that comment
processing was the main bottleneck, so improving this meant a huge
boost for formatting a typical Regal policy. The improvements here
should make formatting of any file faster though.

**BenchmarkFormatLargePolicy-10 main**
```
382	   3064960 ns/op	 4573131 B/op	   26266 allocs/op
```

**BenchmarkFormatLargePolicy-10 opa-fmt-perf**
```
1396	    812859 ns/op	  362651 B/op	    8811 allocs/op
```

Signed-off-by: Anders Eknert <anders@styra.com>
2025-02-06 10:37:52 +01:00
Anders Eknert 55e87e79ae Add perfsprint linter (#7334)
And update code to conform to the rule.

- Replace unnecessary fmt.Sprintf with string concatenation
- Replace fmt.Sprint with more efficient strconv.Itoa
- Replace static fmt.Errorf calls with more efficient errors.New

Thanks @srenatus for pushing me down this rabbit hole!

Signed-off-by: Anders Eknert <anders@styra.com>
2025-01-31 20:24:05 +01:00
Anders Eknert b942136a4a Use Go 1.22+ int ranges (#7328)
With "some" help from `golangci-lint run --fix ./...`

Signed-off-by: Anders Eknert <anders@styra.com>
2025-01-30 09:57:27 +01:00
Anders Eknert 75962f58b9 Perf: improvements to terms and built-in functions (#7284)
Having worked on performance improvements in OPA on the side for almost
a month now, there's a lot of code piling up 😅 So much that a single PR
would be way too much to review. Instead, I'm splitting the work into
chunks, and will submit the next PR as soon as this one is merged. Using
the same benchmark as before — Regal linting itself, these new changes
in total reduce the number of allocations by ~13 million, and quite a
substantial amount of evaluation time saved as well.

This first PR is isolated to improvements to terms, values and
built-ins, and saves ~3M allocations. The details can be found below for
each change, and of course in the code :)

**BenchmarkRegalLintingItself-10 Before**
```
1885978209 ns/op    3497157312 B/op    69064779 allocs/op
```
**BenchmarkRegalLintingItself-10 After**
```
1796255084 ns/op    3452379408 B/op    66126623 allocs/op
```

**Terms**
- Use pointer receivers consistently for object and set types. This allows
  changing the sortGuard once lock from a pointer to a non-pointer type, which
  is really the biggest win performance-wise in this PR.
- Comparisons happen all the time, so make sure these take the shortest path
  possible whenever, possible, such as when one type is compared to another
  value of the same type.

Built-in functions:

**Arrays**
- Both `array.concat` and `array.slice` will now return the operand on operations
  where the result isn't different from the input operand (like when concatenating
  an empty array) instead of allocating a new term/value.

**Strings**
- Return operand on unchanged result rather than allocating new term/value.
- Where applicable, have functions take a cheaper path when string is ASCII
  and we can avoid the cost of rune conversion.

**Crypto**
- Hashing functions now optimized, spending less than half the time compared to
  previously.

**Objects**
- Avoid heap allocating result boolean escaping its scope, and instead use the
  return value of the `Until` function.

**HTTP**
- Use interned terms for keys in configuration object, avoding allocating these
  each time `http.send` is invoked.

**Globs**
- Use read/write lock to avoid contention. Use package level vars for "constant"
  values, avoiding them to escape to the heap each invocation.

**Not directly/only related to built-in functions**
- Add `ValueName` function replacing the previous `TypeName` functions for
  getting the name of Value's without paying for `any` interface allocations.
- Add a few more interned terms.

Signed-off-by: Anders Eknert <anders@styra.com>
2025-01-20 17:41:39 +01:00
Johan Fylling f88306274f Updating formatter to not drop rego.v1 and future.keywords imports (#7224)
to maximize compatibility surface across OPA versions.

Adding `--drop-v0-imports` flag to `opa fmt` for opting in to dropping redundant v0 imports.

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2024-12-17 17:12:05 +01:00
Johan Fylling a179a24c48 v1 API
All packages, except for `cmd` and `internal`, have been moved into a new `v1` root package.

Old packages are kept for backwards-compatibility reasons. All contained code is replaced with simple type aliases and proxy functions to `v1` implementations.

Old packages default to the Rego v0 syntax, new `v1` packages default to the Rego v1 syntax.

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2024-12-12 15:27:34 +01:00
Johan Fylling 7bb6dbe36b Preparing for v1 API
Moving (most) source to v1 root package to prepare for v0/v1 API separation.

Signed-off-by: Johan Fylling <johan.dev@fylling.se>
2024-12-12 15:09:03 +01:00