From 2e6342db21ddf68a3f77e99e2a336d6c59fa827f Mon Sep 17 00:00:00 2001 From: Sean Ledford Date: Tue, 23 Jun 2026 02:43:54 -0500 Subject: [PATCH 1/3] Update grammar to support every and in keywords Signed-off-by: seanledford --- src/main/grammar/Rego.bnf | 11 +++++++---- src/main/grammar/RegoLexer.flex | 2 ++ .../ideaplugin/lang/psi/RegoTokenType.kt | 4 +++- .../ideaplugin/lang/RegoParsingV1Test.kt | 3 +++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/grammar/Rego.bnf b/src/main/grammar/Rego.bnf index dd78f8e..e892251 100644 --- a/src/main/grammar/Rego.bnf +++ b/src/main/grammar/Rego.bnf @@ -33,6 +33,8 @@ ELSE = 'else' IF = 'if' CONTAINS = 'contains' + EVERY = 'every' + IN = 'in' LBRACE = '{' RBRACE = '}' SEMICOLON = ';' @@ -77,9 +79,10 @@ rule-body ::= else-expr | query-block else-expr ::= else (':=' | '=') expr "if"? query-block? | else (':=' | '=')? "if"? query-block query-block ::= "{" query "}" query ::= ( literal |';' )+ -literal ::= ( some-decl | literal-expr | "not" literal-expr ) with-modifier* +literal ::= ( every-decl | some-decl | literal-expr | "not" literal-expr ) with-modifier* with-modifier ::= "with" term "as" term -some-decl ::= "some" var ( "," var )* +some-decl ::= "some" var ( "," var )* ( "in" expr )? +every-decl ::= "every" var ( "," var )? "in" expr query-block literal-expr ::= expr ((':=' | '=') expr)? expr ::= expr-infix | (expr-call ref-arg*) | term expr-call ::= var ref-arg-dot* "(" ( expr ( "," expr )* ","? )? ")" @@ -90,7 +93,7 @@ array-compr ::= "[" term "|" query "]" set-compr ::= "{" term "|" query "}" object-compr ::= "{" term-pair "|" query "}" term-pair ::= term ":" term -infix-operator ::= bool-operator | arith-operator | bin-operator +infix-operator ::= bool-operator | arith-operator | bin-operator | "in" bool-operator ::= "==" | "!=" | "<" | ">" | ">=" | "<=" arith-operator ::= "+" | "-" | "*" | "/" | "%" bin-operator ::= "&" | "|" @@ -98,7 +101,7 @@ ref ::= ( expr-call | array | object | set | array-compr | obje ref-arg ::= ref-arg-dot | ref-arg-brack ref-arg-brack ::= "[" ( expr | "_" ) "]" ref-arg-dot ::= "." var -var ::= ASCII_LETTER | "contains" +var ::= ASCII_LETTER | "contains" | "in" scalar ::= string | NUMBER | TRUE | FALSE | NULL string ::= STRING_TOKEN| RAW_STRING array ::= '[' expr? ( ',' expr )* ','? ']' diff --git a/src/main/grammar/RegoLexer.flex b/src/main/grammar/RegoLexer.flex index 36d527d..d4dbed9 100644 --- a/src/main/grammar/RegoLexer.flex +++ b/src/main/grammar/RegoLexer.flex @@ -58,6 +58,8 @@ COMMENT=[ \t]*#[^\r\n]* "}" { return RBRACE; } ";" { return SEMICOLON; } "some" { return SOME; } + "every" { return EVERY; } + "in" { return IN; } "contains" { return CONTAINS; } "," { return COMMA; } "." { return DOT; } diff --git a/src/main/kotlin/org/openpolicyagent/ideaplugin/lang/psi/RegoTokenType.kt b/src/main/kotlin/org/openpolicyagent/ideaplugin/lang/psi/RegoTokenType.kt index 7a20ca5..9d2057f 100644 --- a/src/main/kotlin/org/openpolicyagent/ideaplugin/lang/psi/RegoTokenType.kt +++ b/src/main/kotlin/org/openpolicyagent/ideaplugin/lang/psi/RegoTokenType.kt @@ -24,7 +24,9 @@ val REGO_KEYWORDS = tokenSetOf( RegoTypes.NOT, RegoTypes.WITH, RegoTypes.IF, - RegoTypes.CONTAINS + RegoTypes.CONTAINS, + RegoTypes.EVERY, + RegoTypes.IN ) val REGO_OPERATOR = tokenSetOf( diff --git a/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt b/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt index c2dd088..0c6e5c9 100644 --- a/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt +++ b/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt @@ -49,4 +49,7 @@ class RegoParsingV1Test : ParsingTestCase( fun `test contains partial set`() = doTestNoError() fun `test one line bodies`() = doTestNoError() fun `test contains identifier uses`() = doTestNoError() + fun `test every expressions`() = doTestNoError() + fun `test in operator`() = doTestNoError() + fun `test some in`() = doTestNoError() } From e8e3b31691e01dc54e12cf772f987078dca37c41 Mon Sep 17 00:00:00 2001 From: Sean Ledford Date: Tue, 23 Jun 2026 02:59:08 -0500 Subject: [PATCH 2/3] Add fixtures for new grammar support Signed-off-by: seanledford --- .../parser/fixtures/v1/every_expressions.rego | 14 ++++++++++++ .../lang/parser/fixtures/v1/in_operator.rego | 22 +++++++++++++++++++ .../lang/parser/fixtures/v1/some_in.rego | 11 ++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/every_expressions.rego create mode 100644 src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/in_operator.rego create mode 100644 src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/some_in.rego diff --git a/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/every_expressions.rego b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/every_expressions.rego new file mode 100644 index 0000000..b5bfe7e --- /dev/null +++ b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/every_expressions.rego @@ -0,0 +1,14 @@ +package play + +allow if { + every x in input.users { + x.active == true + } +} + +valid_pairs if { + every k, v in input.config { + k != "" + v != null + } +} diff --git a/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/in_operator.rego b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/in_operator.rego new file mode 100644 index 0000000..bce44b7 --- /dev/null +++ b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/in_operator.rego @@ -0,0 +1,22 @@ +package play + +allow if { + "admin" in input.roles +} + +deny if { + not "guest" in input.roles +} + +has_pair if { + ["a", 1] in input.entries +} + +is_admin if { + x := "admin" in input.roles + x +} + +log_membership if { + print("admin" in input.roles) +} diff --git a/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/some_in.rego b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/some_in.rego new file mode 100644 index 0000000..3e797f8 --- /dev/null +++ b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/some_in.rego @@ -0,0 +1,11 @@ +package play + +allow if { + some x in input.users + x.active == true +} + +has_admin if { + some k, v in input.roles + v == "admin" +} From 774c7db89052c12876a9332ab46d2490c0f84734 Mon Sep 17 00:00:00 2001 From: Sean Ledford Date: Mon, 6 Jul 2026 00:47:53 -0500 Subject: [PATCH 3/3] Address PR Feedback Signed-off-by: seanledford --- src/main/grammar/Rego.bnf | 7 ++++--- .../ideaplugin/lang/RegoParsingV1Test.kt | 1 + .../fixtures/v1/keywords_as_identifiers.rego | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/keywords_as_identifiers.rego diff --git a/src/main/grammar/Rego.bnf b/src/main/grammar/Rego.bnf index e892251..ab5fb42 100644 --- a/src/main/grammar/Rego.bnf +++ b/src/main/grammar/Rego.bnf @@ -79,9 +79,10 @@ rule-body ::= else-expr | query-block else-expr ::= else (':=' | '=') expr "if"? query-block? | else (':=' | '=')? "if"? query-block query-block ::= "{" query "}" query ::= ( literal |';' )+ -literal ::= ( every-decl | some-decl | literal-expr | "not" literal-expr ) with-modifier* +literal ::= ( every-decl | some-in-decl | some-decl | literal-expr | "not" literal-expr ) with-modifier* with-modifier ::= "with" term "as" term -some-decl ::= "some" var ( "," var )* ( "in" expr )? +some-in-decl ::= "some" var ( "," var )? "in" expr +some-decl ::= "some" var ( "," var )* every-decl ::= "every" var ( "," var )? "in" expr query-block literal-expr ::= expr ((':=' | '=') expr)? expr ::= expr-infix | (expr-call ref-arg*) | term @@ -101,7 +102,7 @@ ref ::= ( expr-call | array | object | set | array-compr | obje ref-arg ::= ref-arg-dot | ref-arg-brack ref-arg-brack ::= "[" ( expr | "_" ) "]" ref-arg-dot ::= "." var -var ::= ASCII_LETTER | "contains" | "in" +var ::= ASCII_LETTER | "contains" | "in" | "every" | "if" scalar ::= string | NUMBER | TRUE | FALSE | NULL string ::= STRING_TOKEN| RAW_STRING array ::= '[' expr? ( ',' expr )* ','? ']' diff --git a/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt b/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt index 0c6e5c9..a69f35b 100644 --- a/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt +++ b/src/test/kotlin/org/openpolicyagent/ideaplugin/lang/RegoParsingV1Test.kt @@ -52,4 +52,5 @@ class RegoParsingV1Test : ParsingTestCase( fun `test every expressions`() = doTestNoError() fun `test in operator`() = doTestNoError() fun `test some in`() = doTestNoError() + fun `test keywords as identifiers`() = doTestNoError() } diff --git a/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/keywords_as_identifiers.rego b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/keywords_as_identifiers.rego new file mode 100644 index 0000000..613c3f0 --- /dev/null +++ b/src/test/resources/org/openpolicyagent/ideaplugin/lang/parser/fixtures/v1/keywords_as_identifiers.rego @@ -0,0 +1,17 @@ +package play + +if := 1 + +every := 2 + +uses_if if { + input.if == 1 +} + +uses_every if { + input.every.woo != null +} + +check_if(if) := true + +check_every(every, foo) := every + foo