Skip to content

Commit

Permalink
fix: fix sniper-mode after type rename (#3418)
Browse files Browse the repository at this point in the history
  • Loading branch information
monperrus committed Jun 15, 2020
1 parent f916140 commit a9c4a11
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ public CompilationUnit getOrCreate(CtPackage ctPackage) {
*/
public void removeType(CtType type) {
cachedCompilationUnits.remove(type.getPosition().getCompilationUnit().getFile().getAbsolutePath());
type.setPosition(NoSourcePosition.NOPOSITION);
}

/**
Expand All @@ -113,7 +112,8 @@ public CompilationUnit addType(CtType type) {
String path = file.getCanonicalPath();
CompilationUnit result = this._create(path);
result.addDeclaredType(type);
type.setPosition(this.factory.createPartialSourcePosition(result));
// for sniper, we need to keep the link to original source code
// type.setPosition(this.factory.createPartialSourcePosition(result));
return result;
} catch (IOException e) {
throw new SpoonException("Cannot get path for file: " + file.getAbsolutePath(), e);
Expand All @@ -134,7 +134,9 @@ public CompilationUnit getOrCreate(CtType type) {
if (!(type.getPosition().getCompilationUnit() instanceof NoSourcePosition.NullCompilationUnit)) {
return type.getPosition().getCompilationUnit();
}
return addType(type);
CompilationUnit compilationUnit = addType(type);
type.setPosition(this.factory.createPartialSourcePosition(compilationUnit));
return compilationUnit;
}

public CompilationUnit getOrCreate(CtModule module) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ private TokenWriter createTokenWriterListener(TokenWriter tokenWriter) {

@Override
public void calculate(CtCompilationUnit compilationUnit, List<CtType<?>> types) {
sourceCompilationUnit = compilationUnit;

//use line separator of origin source file
setLineSeparator(detectLineSeparator(compilationUnit.getOriginalSourceCode()));
runInContext(new SourceFragmentContextList(mutableTokenWriter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ protected int findIFragmentIndexCorrespondingToEvent(PrinterEvent event) {
}
return findIndexOfNextChildTokenByValue(tpe.getToken());
} else {
throw new SpoonException("Unexpected PrintEvent: " + event.getClass());
return -1;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ private ElementSourceFragment addChild(CtRole roleInParent, SourcePositionHolder
SourcePosition otherSourcePosition = otherElement.getPosition();
if (otherSourcePosition instanceof SourcePositionImpl && !(otherSourcePosition.getCompilationUnit() instanceof NoSourcePosition.NullCompilationUnit)) {
ElementSourceFragment otherFragment = new ElementSourceFragment(otherElement, this.getRoleHandler(roleInParent, otherElement));
if (this.getElement() instanceof CtCompilationUnit) {
addChild(otherFragment);
return otherFragment;
}

CMP cmp = this.compare(otherFragment);
if (cmp == CMP.OTHER_IS_CHILD) {
// core contract:
Expand Down Expand Up @@ -691,6 +696,9 @@ private void forEachConstantFragment(int start, int end, Consumer<SourceFragment
throw new SpoonException("Inconsistent start/end. Start=" + start + " is greater then End=" + end);
}
String sourceCode = getOriginalSourceCode();
if (sourceCode.length() == 0) {
return;
}
StringBuilder buff = new StringBuilder();
CharType lastType = null;
int off = start;
Expand Down
60 changes: 58 additions & 2 deletions src/test/java/spoon/test/prettyprinter/TestSniperPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import spoon.Launcher;
import spoon.SpoonException;
import spoon.processing.Processor;
import spoon.refactoring.Refactoring;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.code.CtCodeSnippetExpression;
Expand All @@ -28,6 +29,7 @@
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtThrow;
import spoon.reflect.cu.CompilationUnit;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtField;
Expand Down Expand Up @@ -62,6 +64,8 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.regex.Matcher;
Expand All @@ -73,6 +77,54 @@

public class TestSniperPrinter {

@Test
public void testClassRename1() throws Exception {
// contract: one can sniper out of the box after Refactoring.changeTypeName
testClassRename(type -> {
Refactoring.changeTypeName(type, "Bar");
});
}

@Test
public void testClassRename2() throws Exception {
// contract: one can sniper after setSimpleName
// with the necessary tweaks
testClassRename(type -> {
type.setSimpleName("Bar");
type.getFactory().CompilationUnit().addType(type);
});

}

public void testClassRename(Consumer<CtType> renameTransfo) throws Exception {
// contract: sniper supports class rename

// clean the output dir
Runtime.getRuntime().exec(new String[]{"bash","-c", "rm -rf spooned"});
String testClass = ToBeChanged.class.getName();
Launcher launcher = new Launcher();
launcher.addInputResource(getResourcePath(testClass));
launcher.getEnvironment().setPrettyPrinterCreator(() -> {
SniperJavaPrettyPrinter printer = new SniperJavaPrettyPrinter(launcher.getEnvironment());
return printer;
});
launcher.buildModel();
Factory f = launcher.getFactory();

final CtClass<?> type = f.Class().get(testClass);

// performing the type rename
renameTransfo.accept(type);
//print the changed model
launcher.prettyprint();


String contentOfPrettyPrintedClassFromDisk = getContentOfPrettyPrintedClassFromDisk(type);
assertTrue(contentOfPrettyPrintedClassFromDisk, contentOfPrettyPrintedClassFromDisk.contains("EOLs*/ Bar<T, K>"));

}


@Test
public void testPrintInsertedThrow() {
testSniper(Throw.class.getName(), type -> {
Expand Down Expand Up @@ -328,8 +380,7 @@ private void testSniper(String testClass, Consumer<CtType<?>> transformation, Bi

private String getContentOfPrettyPrintedClassFromDisk(CtType<?> type) {
Factory f = type.getFactory();
File outputDir = f.getEnvironment().getSourceOutputDirectory();
File outputFile = new File(outputDir, type.getQualifiedName().replace('.', '/') + ".java");
File outputFile = getFileForType(type);

byte[] content = new byte[(int) outputFile.length()];
try (InputStream is = new FileInputStream(outputFile)) {
Expand All @@ -344,6 +395,11 @@ private String getContentOfPrettyPrintedClassFromDisk(CtType<?> type) {
}
}

private File getFileForType(CtType<?> type) {
File outputDir = type.getFactory().getEnvironment().getSourceOutputDirectory();
return new File(outputDir, type.getQualifiedName().replace('.', '/') + ".java");
}

private static String getResourcePath(String className) {
String r = "./src/test/java/" + className.replaceAll("\\.", "/") + ".java";
if (new File(r).exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@

import spoon.processing.AbstractProcessor;
import spoon.refactoring.Refactoring;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtClass;

public class ThisTransformationProcessor extends AbstractProcessor<CtClass<?>> {
@Override
public void process(CtClass<?> element) {
Refactoring.changeTypeName(element, element.getSimpleName() + "X");
element.setPosition(SourcePosition.NOPOSITION);
}
}

0 comments on commit a9c4a11

Please sign in to comment.