Skip to content

Commit a23533c

Browse files
committed
✨ Remove Unused import codemod
1 parent a9850fc commit a23533c

File tree

9 files changed

+116
-0
lines changed

9 files changed

+116
-0
lines changed

core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public static List<Class<? extends CodeChanger>> asList() {
4141
PreventFileWriterLeakWithFilesCodemod.class,
4242
RandomizeSeedCodemod.class,
4343
RemoveRedundantVariableCreationCodemod.class,
44+
RemoveUnusedImportCodemod.class,
4445
RemoveUnusedLocalVariableCodemod.class,
4546
RemoveUnusedPrivateMethodCodemod.class,
4647
RemoveUselessParenthesesCodemod.class,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package io.codemodder.codemods;
2+
3+
import com.github.javaparser.ast.CompilationUnit;
4+
import com.github.javaparser.ast.ImportDeclaration;
5+
import io.codemodder.Codemod;
6+
import io.codemodder.CodemodExecutionPriority;
7+
import io.codemodder.CodemodInvocationContext;
8+
import io.codemodder.Importance;
9+
import io.codemodder.NodeCollector;
10+
import io.codemodder.RegionNodeMatcher;
11+
import io.codemodder.ReviewGuidance;
12+
import io.codemodder.codetf.DetectorRule;
13+
import io.codemodder.javaparser.ChangesResult;
14+
import io.codemodder.providers.sonar.ProvidedSonarScan;
15+
import io.codemodder.providers.sonar.RuleIssues;
16+
import io.codemodder.providers.sonar.SonarPluginJavaParserChanger;
17+
import io.codemodder.providers.sonar.api.Issue;
18+
import javax.inject.Inject;
19+
20+
@Codemod(
21+
id = "sonar:java/remove-redundant-variable-creation-s1128",
22+
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
23+
importance = Importance.LOW,
24+
executionPriority = CodemodExecutionPriority.HIGH)
25+
public final class RemoveUnusedImportCodemod
26+
extends SonarPluginJavaParserChanger<ImportDeclaration> {
27+
28+
@Inject
29+
public RemoveUnusedImportCodemod(
30+
@ProvidedSonarScan(ruleId = "java:S1128") final RuleIssues issues) {
31+
super(
32+
issues,
33+
ImportDeclaration.class,
34+
/*
35+
* This codemod uses a less strict RegionNodeMatcher because the import declaration technically starts on column
36+
* 1 according to java parser but sonar reports the unused import starting from the import keyword, on column 8,
37+
* which is where the unused name is actually located. Neither are technically incorrect, but we can be less
38+
* strict with matching here given how relatively simple the import declaration is.
39+
*/
40+
RegionNodeMatcher.MATCHES_LINE,
41+
NodeCollector.ALL_FROM_TYPE);
42+
}
43+
44+
@Override
45+
protected DetectorRule getDetectorRule() {
46+
return new DetectorRule(
47+
"java:S1128",
48+
"Unnecessary imports should be removed",
49+
"https://rules.sonarsource.com/java/RSPEC-1128");
50+
}
51+
52+
@Override
53+
public ChangesResult onIssueFound(
54+
CodemodInvocationContext context, CompilationUnit cu, ImportDeclaration node, Issue issue) {
55+
if (issue.getMessage().contains(node.getNameAsString())) {
56+
return cu.remove(node) ? ChangesResult.changesApplied : ChangesResult.noChanges;
57+
} else {
58+
return ChangesResult.noChanges;
59+
}
60+
}
61+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
This change removes unused imports. Unused imports make the code harder to read, which will lead to confusion and bugs. We only remove variables that have no state-changing effects.
2+
3+
Our changes look something like this:
4+
5+
```diff
6+
- import java.util.Predicate;
7+
```
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"summary" : "Removed unused import (Sonar)",
3+
"change" : "Removed unused import variable",
4+
"reviewGuidanceJustification" : "There are no functional changes after this change, but the code will be easier to understand.",
5+
"references" : [
6+
"https://rules.sonarsource.com/java/RSPEC-1128/"
7+
]
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.codemodder.codemods;
2+
3+
import io.codemodder.testutils.CodemodTestMixin;
4+
import io.codemodder.testutils.Metadata;
5+
6+
@Metadata(
7+
codemodType = RemoveUnusedImportCodemod.class,
8+
testResourceDir = "remove-unused-import-s1128",
9+
renameTestFile = "sonar/src/main/java/ai/pixee/triage/sonar/SonarTriageProvider.java",
10+
dependencies = {})
11+
final class RemoveUnusedImportCodemodTest implements CodemodTestMixin {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package ai.pixee.triage.sonar;
2+
3+
import java.io.IOException;
4+
import ai.pixee.triage.TriageProvider;
5+
6+
/** A provider for Sonar. */
7+
public final class SonarTriageProvider implements TriageProvider {
8+
9+
public void triage() throws IOException {
10+
System.out.println("Triage with Sonar");
11+
}
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package ai.pixee.triage.sonar;
2+
3+
import java.io.IOException;
4+
import java.util.function.Predicate;
5+
import ai.pixee.triage.TriageProvider;
6+
7+
/** A provider for Sonar. */
8+
public final class SonarTriageProvider implements TriageProvider {
9+
10+
public void triage() throws IOException {
11+
System.out.println("Triage with Sonar");
12+
}
13+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"total":1,"p":1,"ps":100,"paging":{"pageIndex":1,"pageSize":100,"total":1},"effortTotal":1,"debtTotal":1,"issues":[{"key":"AY6qgnZ1S4TzKH4OoTdU","rule":"java:S1128","severity":"MINOR","component":"pixee_triage:sonar/src/main/java/ai/pixee/triage/sonar/SonarTriageProvider.java","project":"pixee_triage","line":23,"hash":"33f8371bb11c686cc89f1601a8476b8b","textRange":{"startLine":4,"endLine":4,"startOffset":7,"endOffset":35},"flows":[],"status":"OPEN","message":"Remove this unused import 'java.util.function.Predicate'.","effort":"1min","debt":"1min","author":"[email protected]","tags":["unused"],"creationDate":"2024-04-04T21:06:25+0200","updateDate":"2024-04-04T21:07:21+0200","type":"CODE_SMELL","organization":"pixee","pullRequest":"13","cleanCodeAttribute":"CLEAR","cleanCodeAttributeCategory":"INTENTIONAL","impacts":[{"softwareQuality":"MAINTAINABILITY","severity":"LOW"}]}],"components":[{"organization":"pixee","key":"pixee_triage","uuid":"AY6qghtlrWyjshUAn-MS","enabled":true,"qualifier":"TRK","name":"triage","longName":"triage","pullRequest":"13"},{"organization":"pixee","key":"pixee_triage:sonar/src/main/java/ai/pixee/triage/sonar/SonarTriageProvider.java","uuid":"AY6qgnRLS4TzKH4OoTZ_","enabled":true,"qualifier":"FIL","name":"SonarTriageProvider.java","longName":"sonar/src/main/java/ai/pixee/triage/sonar/SonarTriageProvider.java","path":"sonar/src/main/java/ai/pixee/triage/sonar/SonarTriageProvider.java","pullRequest":"13"}],"organizations":[{"key":"pixee","name":"Pixee"}],"facets":[]}

framework/codemodder-base/src/main/java/io/codemodder/RegionNodeMatcher.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ public interface RegionNodeMatcher {
3232
(region, range) ->
3333
region.start().line() == range.begin.line
3434
&& region.start().column() == range.begin.column;
35+
36+
RegionNodeMatcher MATCHES_LINE = (region, range) -> region.start().line() == range.begin.line;
3537
}

0 commit comments

Comments
 (0)