Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .regal/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ rules:
prefer-value-in-head:
level: error
only-scalars: true
include-interpolated: true
style:
line-length:
level: error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ report contains violation if {
terms[1].type == "var"
terms[1].value == var

not _scalar_fail(terms[2].type, ast.scalar_types)
not _scalar_fail(terms[2].type, _scalar_types)
not _excepted_var_name(var)

violation := result.fail(rego.metadata.chain(), result.location(terms[2]))
Expand All @@ -36,3 +36,6 @@ _scalar_fail(term_type, scalar_types) if {
}

_excepted_var_name(name) if name in config.rules.custom["prefer-value-in-head"]["except-var-names"]

_scalar_types contains type if some type in ast.scalar_types
_scalar_types contains "templatestring" if config.rules.custom["prefer-value-in-head"]["include-interpolated"] == true
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,51 @@ test_fail_value_could_be_in_head_but_not_a_scalar if {
r == set()
}

test_fail_value_could_be_in_head_templatestring if {
r := rule.report with input as ast.policy(`value := x if {
input.x
x := $"{input.y}"
}`)

r == expected_with_location({
"col": 8,
"row": 5,
"end": {
"col": 20,
"row": 5,
},
"text": "\t\tx := $\"{input.y}\"",
})
}

test_success_only_scalar_no_include_interpolated if {
r := rule.report with input as ast.policy(`value := x if {
input.x
x := $"{input.y}"
}`)
with config.rules as {"custom": {"prefer-value-in-head": {"only-scalars": true}}}

r == set()
}

test_fail_value_could_be_in_head_only_scalars_with_include_interpolated if {
r := rule.report with input as ast.policy(`value := x if {
input.x
x := $"{input.y}"
}`)
with config.rules as {"custom": {"prefer-value-in-head": {"only-scalars": true, "include-interpolated": true}}}

r == expected_with_location({
"col": 8,
"row": 5,
"end": {
"col": 20,
"row": 5,
},
"text": "\t\tx := $\"{input.y}\"",
})
}

test_fail_value_could_be_in_head_and_is_a_scalar if {
module := ast.policy(`value := x if {
input.x
Expand Down
12 changes: 10 additions & 2 deletions docs/rules/custom/prefer-value-in-head.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**Category**: Custom

**Avoid**

```rego
package policy

Expand All @@ -20,6 +21,7 @@ deny contains message if {
```

**Prefer**

```rego
package policy

Expand Down Expand Up @@ -58,6 +60,9 @@ deny contains message if {
}
```

The `include-interpolated` configuration option may be used to count interpolated strings as a scalar (string) values,
which will have Regal recommend moving them to the head even when `only-scalars` is set to `true`.

## Configuration Options

This linter rule provides the following configuration options:
Expand All @@ -74,10 +79,13 @@ rules:
# whether to only suggest moving scalar values (strings, numbers, booleans, null)
# to the head, and not expressions or functions
only-scalars: false
# when set to true, counts interpolated strings as a scalar value, and will suggest
# moving them to the head even when `only-scalars` is true
include-interpolated: false
# variable names to exempt from the rule (by default, none)
except-var-names:
- report
- violation
- report
- violation
```

## Related Resources
Expand Down
Loading