diff --git a/rules/005_microflows/005_0005_nested_if_statements.rego b/rules/005_microflows/005_0005_nested_if_statements.rego new file mode 100644 index 0000000..1aaa034 --- /dev/null +++ b/rules/005_microflows/005_0005_nested_if_statements.rego @@ -0,0 +1,41 @@ +# METADATA +# scope: package +# title: Nested if-statements +# description: Microflow actions with nested if-statements hide complexity and are harder to maintain. +# authors: +# - Bart Zantingh +# custom: +# category: Complexity +# rulename: NestedIfStatements +# severity: MEDIUM +# rulenumber: "005_0005" +# remediation: Simplify the expression or use exclusive splits. +# input: "**/*$Microflow.yaml" +package app.mendix.microflows.nested_if_statements + +import rego.v1 + +annotation := rego.metadata.chain()[1].annotations + +default allow := false + +allow if count(errors) == 0 + +regex_to_match := `^[\S\s]*(then|else)[\S\s]*(if)[\S\s]*$` + +errors contains error if { + some ex_split in input.ObjectCollection.Objects + ex_split["$Type"] == "Microflows$ExclusiveSplit" + + regex.match(regex_to_match, ex_split.SplitCondition.Expression) + + error := sprintf( + "[%v, %v, %v] Exclusive split with caption '%v' has nested if-statements in its expression", + [ + annotation.custom.severity, + annotation.custom.category, + annotation.custom.rulenumber, + ex_split.Caption, + ], + ) +} diff --git a/rules/005_microflows/005_0005_nested_if_statements_test.rego b/rules/005_microflows/005_0005_nested_if_statements_test.rego new file mode 100644 index 0000000..00362f0 --- /dev/null +++ b/rules/005_microflows/005_0005_nested_if_statements_test.rego @@ -0,0 +1,76 @@ +package app.mendix.microflows.nested_if_statements_test + +import data.app.mendix.microflows.nested_if_statements +import rego.v1 + +# Test data +one_exclusive_split_with_no_nested_ifs := {"ObjectCollection": { + "$Type": "Microflows$MicroflowObjectCollection", + "Objects": [{ + "$Type": "Microflows$ExpressionSplitCondition", + "Caption": "no nested ifs", + "SplitCondition": {"Expression": "if $Variable then a else b"}, + }], +}} + +multiple_exclusive_splits_with_no_nested_ifs := {"ObjectCollection": { + "$Type": "Microflows$MicroflowObjectCollection", + "Objects": [ + { + "$Type": "Microflows$ExpressionSplitCondition", + "Caption": "ex spit 1 with no nested ifs", + "SplitCondition": {"Expression": "if $Variable then a else b"}, + }, + { + "$Type": "Microflows$ExpressionSplitCondition", + "Caption": "ex split 2 with no nested ifs", + "SplitCondition": {"Expression": "if $Variable then c else d"}, + }, + ], +}} + +one_exclusive_split_with_else_if := {"ObjectCollection": { + "$Type": "Microflows$MicroflowObjectCollection", + "Objects": [{ + "$Type": "Microflows$ExclusiveSplit", + "Caption": "ex split with else-if", + "SplitCondition": {"Expression": "if true then\n\tfalse\nelse if false then\n\ttrue\nelse false"}, + }], +}} + +one_exclusive_split_with_then_if := {"ObjectCollection": { + "$Type": "Microflows$MicroflowObjectCollection", + "Objects": [{ + "$Type": "Microflows$ExclusiveSplit", + "Caption": "ex split with then-if", + "SplitCondition": {"Expression": "if a then if b then c else d else e"}, + }], +}} + +multiple_exclusive_splits_with_one_nested_if := {"ObjectCollection": { + "$Type": "Microflows$MicroflowObjectCollection", + "Objects": [ + { + "$Type": "Microflows$ExclusiveSplit", + "Caption": "no nested ifs", + "SplitCondition": {"Expression": "if $Variable then a else b"}, + }, + { + "$Type": "Microflows$ExclusiveSplit", + "Caption": "ex split with then-if", + "SplitCondition": {"Expression": "if a then b else if c then d else e"}, + }, + ], +}} + +# Test cases +test_should_allow_when_no_exclusive_splits_with_nested_ifs if { + nested_if_statements.allow with input as one_exclusive_split_with_no_nested_ifs + nested_if_statements.allow with input as multiple_exclusive_splits_with_no_nested_ifs +} + +test_should_deny_when_exclusive_splits_with_nested_ifs if { + not nested_if_statements.allow with input as one_exclusive_split_with_else_if + not nested_if_statements.allow with input as one_exclusive_split_with_then_if + not nested_if_statements.allow with input as multiple_exclusive_splits_with_one_nested_if +}