Skip to content

Commit cb465da

Browse files
committed
Fix FPs around enums that are never referenced by name in UnusedType
Enums are considered used as long as any of their elements are used.
1 parent 890d92f commit cb465da

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414

1515
### Fixed
1616

17+
- False positives on enums that are never referenced by name (but have used values) in `UnusedType`.
1718
- Incorrect file position calculation for multiline string tokens.
1819

1920
## [1.15.0] - 2025-04-03

delphi-checks/src/main/java/au/com/integradev/delphi/checks/UnusedTypeCheck.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@
1818
*/
1919
package au.com.integradev.delphi.checks;
2020

21+
import java.util.List;
22+
import java.util.function.Predicate;
2123
import org.sonar.check.Rule;
2224
import org.sonar.check.RuleProperty;
25+
import org.sonar.plugins.communitydelphi.api.ast.EnumElementNode;
26+
import org.sonar.plugins.communitydelphi.api.ast.EnumTypeNode;
2327
import org.sonar.plugins.communitydelphi.api.ast.InterfaceSectionNode;
28+
import org.sonar.plugins.communitydelphi.api.ast.NameDeclarationNode;
2429
import org.sonar.plugins.communitydelphi.api.ast.TypeDeclarationNode;
2530
import org.sonar.plugins.communitydelphi.api.check.DelphiCheck;
2631
import org.sonar.plugins.communitydelphi.api.check.DelphiCheckContext;
@@ -63,6 +68,10 @@ private boolean isViolation(TypeDeclarationNode node) {
6368
return false;
6469
}
6570

71+
if (node.isEnum() && hasElementsWithUsages((EnumTypeNode) node.getTypeNode())) {
72+
return false;
73+
}
74+
6675
if (excludeApi
6776
&& (node.isPublic() || node.isPublished())
6877
&& node.getFirstParentOfType(InterfaceSectionNode.class) != null) {
@@ -77,6 +86,13 @@ private boolean isViolation(TypeDeclarationNode node) {
7786
.allMatch(occurrence -> isWithinType(occurrence, type));
7887
}
7988

89+
private static boolean hasElementsWithUsages(EnumTypeNode node) {
90+
return node.getElements().stream()
91+
.map(EnumElementNode::getNameDeclarationNode)
92+
.map(NameDeclarationNode::getUsages)
93+
.anyMatch(Predicate.not(List::isEmpty));
94+
}
95+
8096
private static boolean isWithinType(NameOccurrence occurrence, Type type) {
8197
DelphiScope scope = occurrence.getLocation().getScope();
8298
while (scope != null) {

delphi-checks/src/test/java/au/com/integradev/delphi/checks/UnusedTypeCheckTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,34 @@ void testUnusedTypeWithAttributeShouldNotAddIssue() {
212212
.appendDecl(" end;"))
213213
.verifyNoIssues();
214214
}
215+
216+
@Test
217+
void testUnusedEnumWithUsedElementsShouldNotAddIssue() {
218+
CheckVerifier.newVerifier()
219+
.withCheck(new UnusedTypeCheck())
220+
.onFile(
221+
new DelphiTestUnitBuilder()
222+
.appendImpl("function Foo: Integer;")
223+
.appendImpl("type")
224+
.appendImpl(" TBar = (Baz, Flarp);")
225+
.appendImpl("begin")
226+
.appendImpl(" Result := Ord(Baz) + 123;")
227+
.appendImpl("end;"))
228+
.verifyNoIssues();
229+
}
230+
231+
@Test
232+
void testUnusedEnumWithUnusedElementsShouldAddIssue() {
233+
CheckVerifier.newVerifier()
234+
.withCheck(new UnusedTypeCheck())
235+
.onFile(
236+
new DelphiTestUnitBuilder()
237+
.appendImpl("function Foo: Integer;")
238+
.appendImpl("type")
239+
.appendImpl(" TBar = (Baz, Flarp); // Noncompliant")
240+
.appendImpl("begin")
241+
.appendImpl(" Result := 123;")
242+
.appendImpl("end;"))
243+
.verifyIssues();
244+
}
215245
}

0 commit comments

Comments
 (0)