diff --git a/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable.rego b/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable.rego index d50b3f14..5d6cdb35 100644 --- a/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable.rego +++ b/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable.rego @@ -30,6 +30,7 @@ report contains violation if { not ast.var_in_head(input.rules[to_number(rule_index)].head, var.value) not ast.var_in_call(ast.function_calls, rule_index, var.value) not _ref_base_vars[rule_index][var.value] + not _comprehension_term_vars[rule_index][var.value] # this is by far the most expensive condition to check, so only do # so when all other conditions apply @@ -52,3 +53,12 @@ _ref_base_vars[rule_index][term.value] contains term if { not ast.is_wildcard(term) } + +_comprehension_term_vars[rule_index] contains var.value if { + some rule_index, comprehensions in ast.found.comprehensions + some comprehension in comprehensions + + only_head := object.remove(comprehension.value, ["body"]) + + some var in ast.find_term_vars(only_head) +} diff --git a/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable_test.rego b/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable_test.rego index 6997f5ff..069d00c4 100644 --- a/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable_test.rego +++ b/bundle/regal/rules/bugs/unused-output-variable/unused_output_variable_test.rego @@ -176,3 +176,24 @@ test_success_not_output_variable_argument if { r := rule.report with input as module r == set() } + +test_success_not_unused_comprehension_term if { + module := ast.with_rego_v1(`success if {x | input[x]}`) + + r := rule.report with input as module + r == set() +} + +test_success_not_unused_comprehension_term_complex if { + module := ast.with_rego_v1(`success if {[x, y] | input[x][y]}`) + + r := rule.report with input as module + r == set() +} + +test_success_not_unused_comprehension_term_key_value if { + module := ast.with_rego_v1(`success if {x: y | input[x][y]}`) + + r := rule.report with input as module + r == set() +}