Skip to content

Commit

Permalink
feat(spoon): Improve snippet generation for spoon-analyzer (#848)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinWitt committed Jul 15, 2023
1 parent c65ac44 commit 3fa3323
Showing 1 changed file with 44 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
import io.github.martinwitt.spoon_analyzer.badsmells.size_replaceable_by_is_empty.SizeReplaceableByIsEmpty;
import io.github.martinwitt.spoon_analyzer.badsmells.unnecessary_implements.UnnecessaryImplements;
import io.github.martinwitt.spoon_analyzer.badsmells.unnecessary_tostring.UnnecessaryTostring;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
import spoon.reflect.code.CtBinaryOperator;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtType;

class AnalyzerResultVisitor implements BadSmellVisitor<AnalyzerResult> {
Expand All @@ -37,10 +41,10 @@ public AnalyzerResult visit(IndexOfReplaceableByContains badSmell) {
return toSpoonAnalyzerResult(
badSmell,
badSmell.getIndexOfCall().getPosition(),
badSmell.getIndexOfCall()
.getParent(CtBinaryOperator.class)
.getOriginalSourceFragment()
.toString());
trygetOriginalSourceCode(badSmell.getIndexOfCall())
.orElse(badSmell.getIndexOfCall()
.getParent(CtBinaryOperator.class)
.toString()));
}

private String getAbsolutePath(BadSmell badSmell) {
Expand Down Expand Up @@ -71,27 +75,28 @@ public AnalyzerResult toSpoonAnalyzerResult(BadSmell badSmell, SourcePosition po

@Override
public AnalyzerResult visit(AccessStaticViaInstance badSmell) {
String snippet =
badSmell.getAffectedCtInvocation().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getAffectedCtInvocation())
.orElse(badSmell.getAffectedCtInvocation().toString());
return toSpoonAnalyzerResult(
badSmell, badSmell.getAffectedCtInvocation().getPosition(), snippet);
}

@Override
public AnalyzerResult visit(ArrayCanBeReplacedWithEnumValues badSmell) {
String snippet =
badSmell.getAffectedElement().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getAffectedElement())
.orElse(badSmell.getAffectedElement().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getAffectedElement().getPosition(), snippet);
}

@Override
public AnalyzerResult visit(CharsetObjectCanBeUsed badSmell) {
if (badSmell.getInvocation() != null) {
String snippet =
badSmell.getInvocation().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getInvocation())
.orElse(badSmell.getInvocation().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getInvocation().getPosition(), snippet);
} else {
String snippet = badSmell.getCtorCall().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getCtorCall())
.orElse(badSmell.getCtorCall().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getCtorCall().getPosition(), snippet);
}
}
Expand All @@ -106,21 +111,22 @@ public AnalyzerResult visit(InnerClassMayBeStatic badSmell) {

@Override
public AnalyzerResult visit(NonProtectedConstructorInAbstractClass badSmell) {
String snippet = badSmell.getCtConstructor().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getCtConstructor())
.orElse(badSmell.getCtConstructor().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getCtConstructor().getPosition(), snippet);
}

@Override
public AnalyzerResult visit(PrivateFinalMethod badSmell) {
String snippet =
badSmell.getAffectedMethod().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getAffectedMethod())
.orElse(badSmell.getAffectedMethod().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getAffectedMethod().getPosition(), snippet);
}

@Override
public AnalyzerResult visit(SizeReplaceableByIsEmpty badSmell) {
String snippet =
badSmell.getSizeInvocation().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getSizeInvocation())
.orElse(badSmell.getSizeInvocation().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getSizeInvocation().getPosition(), snippet);
}

Expand All @@ -135,8 +141,8 @@ public AnalyzerResult visit(UnnecessaryImplements badSmell) {

@Override
public AnalyzerResult visit(UnnecessaryTostring badSmell) {
String snippet =
badSmell.getNotNeededTostring().getOriginalSourceFragment().toString();
String snippet = trygetOriginalSourceCode(badSmell.getNotNeededTostring())
.orElse(badSmell.getNotNeededTostring().toString());
return toSpoonAnalyzerResult(badSmell, badSmell.getNotNeededTostring().getPosition(), snippet);
}

Expand All @@ -145,4 +151,24 @@ public AnalyzerResult visit(FinalStaticMethod badSmell) {
String snippet = badSmell.getMethod().getSignature();
return toSpoonAnalyzerResult(badSmell, badSmell.getMethod().getPosition(), snippet);
}

private Optional<String> trygetOriginalSourceCode(CtElement element) {
try {
File file = element.getPosition().getCompilationUnit().getFile();
String sourceCode = Files.readString(file.toPath());
int lineNumber = element.getPosition().getLine();

// Split the source code into lines
String[] lines = sourceCode.split("\\r?\\n");

// Extract the two lines before and after the given line number
int startIndex = Math.max(0, lineNumber - 3);
int endIndex = Math.min(lines.length - 1, lineNumber + 2);
String context = String.join("\n", Arrays.copyOfRange(lines, startIndex, endIndex + 1));

return Optional.ofNullable(context);

Check warning on line 169 in code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/AnalyzerResultVisitor.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Nullability and data flow problems

Passing a non-null argument to `Optional`
} catch (Throwable e) {
return Optional.empty();
}
}
}

0 comments on commit 3fa3323

Please sign in to comment.