Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spoon): Improve snippet generation for spoon-analyzer #848

Merged
merged 1 commit into from
Jul 15, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
} catch (Throwable e) {
return Optional.empty();
}
}
}