-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add inner_class_may_be_static rule (#239)
- Loading branch information
1 parent
6dc849e
commit 7fa964f
Showing
8 changed files
with
775 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/InnerClassMayBeStatic.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package xyz.keksdose.spoon.code_solver.analyzer.qodana.rules; | ||
|
||
import java.nio.file.Path; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import spoon.reflect.declaration.CtElement; | ||
import spoon.reflect.declaration.CtType; | ||
import spoon.reflect.declaration.ModifierKind; | ||
import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; | ||
import xyz.keksdose.spoon.code_solver.api.analyzer.AnalyzerResult; | ||
import xyz.keksdose.spoon.code_solver.history.Change; | ||
import xyz.keksdose.spoon.code_solver.history.ChangeListener; | ||
import xyz.keksdose.spoon.code_solver.history.MarkdownString; | ||
import xyz.keksdose.spoon.code_solver.transformations.BadSmell; | ||
|
||
public class InnerClassMayBeStatic extends AbstractRefactoring { | ||
|
||
private static final BadSmell badSmell = new BadSmell() { | ||
@Override | ||
public MarkdownString getName() { | ||
return MarkdownString.fromMarkdown("InnerClassMayBeStatic"); | ||
} | ||
|
||
@Override | ||
public MarkdownString getDescription() { | ||
return MarkdownString.fromMarkdown( | ||
""" | ||
Inner classes that do not reference their enclosing instances can be made static. | ||
This prevents a common cause of memory leaks and uses less memory per instance of the class. | ||
"""); | ||
} | ||
}; | ||
|
||
public InnerClassMayBeStatic(AnalyzerResult result) { | ||
super(result); | ||
} | ||
|
||
@Override | ||
public void refactor(ChangeListener listener, CtType<?> type) { | ||
if (!isSameType(type, Path.of(result.filePath()))) { | ||
return; | ||
} | ||
for (CtType<?> ctType : filterMatches(PositionScanner.findLineOnly(type, result.position()))) { | ||
var modifiers = new HashSet<>(ctType.getModifiers()); | ||
modifiers.add(ModifierKind.STATIC); | ||
ctType.setModifiers(modifiers); | ||
String format = "Add to inner class %s modifier static"; | ||
String markdown = String.format(format, "`" + ctType.getSimpleName() + "`"); | ||
String text = String.format(format, ctType.getQualifiedName()); | ||
MarkdownString markdownString = MarkdownString.fromMarkdown(text, markdown); | ||
Change change = new Change(badSmell, markdownString, getMostOuterType(type), result); | ||
listener.setChanged(getMostOuterType(type), change); | ||
} | ||
} | ||
|
||
private Iterable<? extends CtType<?>> filterMatches(List<CtElement> findLineOnly) { | ||
return findLineOnly.stream() | ||
.filter(v -> v instanceof CtType<?>) | ||
.map(v -> (CtType<?>) v) | ||
.filter(v -> !v.isTopLevel()) | ||
.filter(v -> !v.getModifiers().contains(ModifierKind.STATIC)) | ||
.toList(); | ||
} | ||
|
||
@Override | ||
public List<BadSmell> getHandledBadSmells() { | ||
return List.of(badSmell); | ||
} | ||
|
||
private CtType<?> getMostOuterType(CtType<?> inner) { | ||
if (inner.getDeclaringType() == null) { | ||
return inner; | ||
} else { | ||
return getMostOuterType(inner.getDeclaringType()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
...java/xyz/keksdose/spoon/code_solver/transformations/qodana/InnerClassMayBeStaticTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package xyz.keksdose.spoon.code_solver.transformations.qodana; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.InnerClassMayBeStatic; | ||
import xyz.keksdose.spoon.code_solver.api.analyzer.AnalyzerResult; | ||
import xyz.keksdose.spoon.code_solver.api.analyzer.Position; | ||
import xyz.keksdose.spoon.code_solver.transformations.TestAnalyzerResult; | ||
import xyz.keksdose.spoon.code_solver.transformations.TransformationTestUtils; | ||
|
||
public class InnerClassMayBeStaticTest { | ||
|
||
@Test | ||
void landLordInnerClassMabyBeStatic(@TempDir File dir) throws IOException { | ||
Position position = new Position(296, 0, 0, 0, 0, 80); | ||
AnalyzerResult result = new TestAnalyzerResult("Landlordbase.java", position); | ||
String resourcePath = "projects/refactorings/InnerClassMayBeStatic/Landlordbase.java"; | ||
var copy = TransformationTestUtils.transform(new InnerClassMayBeStatic(result), resourcePath, dir); | ||
TransformationTestUtils.compareContent(copy, resourcePath); | ||
} | ||
} |
Oops, something went wrong.