diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db90f758..45066c477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `RedundantJump` analysis rule, which flags redundant jump statements, e.g., `Continue`, `Exit`. - `LoopExecutingAtMostOnce` analysis rule, which flags loop statements that can execute at most once. +- `excludedNames` rule property to the `MixedNames` rule. - **API:** `RepeatStatementNode::getGuardExpression` method. - **API:** `RepeatStatementNode::getStatementList` method. - **API:** `CaseStatementNode::getSelectorExpression` method. diff --git a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/MixedNamesCheck.java b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/MixedNamesCheck.java index 73964d665..89337a653 100644 --- a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/MixedNamesCheck.java +++ b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/MixedNamesCheck.java @@ -22,9 +22,13 @@ */ package au.com.integradev.delphi.checks; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSortedSet; import java.util.List; +import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; import org.sonar.plugins.communitydelphi.api.ast.ArgumentListNode; import org.sonar.plugins.communitydelphi.api.ast.AttributeNode; import org.sonar.plugins.communitydelphi.api.ast.DelphiNode; @@ -48,12 +52,30 @@ public class MixedNamesCheck extends DelphiCheck { private static final String MESSAGE = "Avoid mixing names (found: \"%s\" expected: \"%s\")."; private static final String QUICK_FIX_MESSAGE = "Correct to \"%s\""; + private Set excludedSet; + + @RuleProperty( + key = "excludedNames", + description = "List of names to ignore, separated by a comma.") + public String excludedNames = ""; + + @Override + public void start(DelphiCheckContext context) { + excludedSet = + ImmutableSortedSet.copyOf( + String.CASE_INSENSITIVE_ORDER, Splitter.on(',').trimResults().split(excludedNames)); + } + @Override public DelphiCheckContext visit(NameReferenceNode reference, DelphiCheckContext context) { NameDeclaration declaration = reference.getNameDeclaration(); NameOccurrence occurrence = reference.getNameOccurrence(); if (declaration != null) { + if (excludedSet.contains(occurrence.getImage())) { + return context; + } + if (declaration instanceof UnitImportNameDeclaration) { // Checks the occurrence against the original unit declaration instead of the import // declaration diff --git a/delphi-checks/src/test/java/au/com/integradev/delphi/checks/MixedNamesCheckTest.java b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/MixedNamesCheckTest.java index 276b7b724..bb62550ea 100644 --- a/delphi-checks/src/test/java/au/com/integradev/delphi/checks/MixedNamesCheckTest.java +++ b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/MixedNamesCheckTest.java @@ -23,8 +23,47 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.sonar.plugins.communitydelphi.api.check.DelphiCheck; class MixedNamesCheckTest { + private static DelphiCheck createCheck() { + MixedNamesCheck check = new MixedNamesCheck(); + check.excludedNames = "Foo,Bar"; + return check; + } + + @Test + void testNamesInExcludedListShouldNotAddIssue() { + CheckVerifier.newVerifier() + .withCheck(createCheck()) + .onFile( + new DelphiTestUnitBuilder() + .appendImpl("procedure Test;") + .appendImpl("var") + .appendImpl(" Foo: Boolean;") + .appendImpl(" Bar: Boolean;") + .appendImpl("begin") + .appendImpl(" foo := True;") + .appendImpl(" BAR := True;") + .appendImpl("end;")) + .verifyNoIssues(); + } + + @Test + void testDifferentlyCasedNameFromExcludedListShouldNotAddIssue() { + CheckVerifier.newVerifier() + .withCheck(createCheck()) + .onFile( + new DelphiTestUnitBuilder() + .appendImpl("procedure Test;") + .appendImpl("var") + .appendImpl(" FOO: Boolean;") + .appendImpl("begin") + .appendImpl(" foo := True;") + .appendImpl("end;")) + .verifyNoIssues(); + } + @Test void testMatchingVarNamesShouldNotAddIssue() { CheckVerifier.newVerifier()