-
-
Notifications
You must be signed in to change notification settings - Fork 376
Closed
Labels
Description
Describe the bug
After updating Spoon from 11.2.0 to 11.3.0, I've noticed Spoon does not rename occurrences of a variable arounnd if statements. As far as I know, this was actually working in 11.2.0.
Please note, I've encountered two different cases (although I'm not sure if they have the same root cause), so I've provided them as two different classes in source code sample.
Source code you are trying to analyze/transform
class RaindropConverter {
String convert(int number) {
StringBuffer buffer = new StringBuffer();
if(number % 3 == 0)
buffer.append("Pling");
if(number % 5 == 0)
buffer.append("Plang");
if(number % 7 == 0)
buffer.append("Plong");
if(buffer.length() == 0)
buffer.append(number);
return buffer.toString();
}
}
class AffineCipher {
private static final int ALPHABET_SIZE = 26;
private static final int ALPHABET_START_UNICODE = 97;
private static int modInverse(int keyA) {
return keyA + 1;
}
private static String translate(String text, int keyA, int keyB, Mode mode) {
int inv = modInverse(keyA);
if (inv == 1) {
throw new IllegalArgumentException("Error: keyA and alphabet size must be coprime.");
}
StringBuilder stringBuilder = new StringBuilder();
text.chars()
.filter(Character::isLetterOrDigit)
.map(Character::toLowerCase)
.forEach(c -> {
int orig = c - ALPHABET_START_UNICODE;
if (orig < 0) {
stringBuilder.appendCodePoint(c);
} else {
if (mode == Mode.ENCODE) {
stringBuilder.appendCodePoint(
ALPHABET_START_UNICODE + Math.floorMod(keyA * orig + keyB, ALPHABET_SIZE)
);
} else if (mode == Mode.DECODE) {
stringBuilder.appendCodePoint(
ALPHABET_START_UNICODE + Math.floorMod(inv * (orig - keyB), ALPHABET_SIZE)
);
}
}
});
return stringBuilder.toString();
}
}Source code for your Spoon processing
import spoon.Launcher;
import spoon.refactoring.CtRenameGenericVariableRefactoring;
import spoon.reflect.CtModel;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtVariable;
import spoon.support.compiler.VirtualFile;
import java.util.Collection;
public class Main {
private static final String SAMPLE1 = """
class RaindropConverter {
String convert(int number) {
StringBuffer buffer = new StringBuffer();
if(number % 3 == 0)
buffer.append("Pling");
if(number % 5 == 0)
buffer.append("Plang");
if(number % 7 == 0)
buffer.append("Plong");
if(buffer.length() == 0)
buffer.append(number);
return buffer.toString();
}
}
class AffineCipher {
private static final int ALPHABET_SIZE = 26;
private static final int ALPHABET_START_UNICODE = 97;
private static int modInverse(int keyA) {
return keyA + 1;
}
private static String translate(String text, int keyA, int keyB, Mode mode) {
int inv = modInverse(keyA);
if (inv == 1) {
throw new IllegalArgumentException("Error: keyA and alphabet size must be coprime.");
}
StringBuilder stringBuilder = new StringBuilder();
text.chars()
.filter(Character::isLetterOrDigit)
.map(Character::toLowerCase)
.forEach(c -> {
int orig = c - ALPHABET_START_UNICODE;
if (orig < 0) {
stringBuilder.appendCodePoint(c);
} else {
if (mode == Mode.ENCODE) {
stringBuilder.appendCodePoint(
ALPHABET_START_UNICODE + Math.floorMod(keyA * orig + keyB, ALPHABET_SIZE)
);
} else if (mode == Mode.DECODE) {
stringBuilder.appendCodePoint(
ALPHABET_START_UNICODE + Math.floorMod(inv * (orig - keyB), ALPHABET_SIZE)
);
}
}
});
return stringBuilder.toString();
}
}
""";
public static void main(String[] args) {
Launcher launcher = new Launcher();
launcher.addInputResource(new VirtualFile(SAMPLE1));
launcher.getEnvironment().setComplianceLevel(21);
launcher.getEnvironment().setNoClasspath(true);
launcher.getEnvironment().setAutoImports(true);
Collection<CtType<?>> allTypes = launcher.buildModel().getAllTypes();
for (CtType<?> ctType : allTypes) {
if (ctType instanceof CtClass<?> ctClass) {
ctType.getElements(CtVariable.class::isInstance)
.forEach(ctElem -> {
if (ctElem instanceof CtVariable<?> variable) {
new CtRenameGenericVariableRefactoring().setTarget(variable).setNewName(variable.getSimpleName().toUpperCase() + "_1").refactor();
}
});
}
}
launcher.process();
System.out.println(getRepresentationString(launcher.getModel()));
}
private static String getRepresentationString(CtModel model) {
var normalized = new StringBuilder();
for (CtType<?> type : model.getAllTypes()) {
normalized.append(type.toString());
normalized.append("\n");
}
return normalized.toString();
}
}Actual output
class RaindropConverter {
String convert(int NUMBER_1) {
StringBuffer BUFFER_1 = new StringBuffer();
if ((NUMBER_1 % 3) == 0) {
buffer.append("Pling");
}
if ((NUMBER_1 % 5) == 0) {
buffer.append("Plang");
}
if ((NUMBER_1 % 7) == 0) {
buffer.append("Plong");
}
if (buffer.length() == 0) {
buffer.append(NUMBER_1);
}
return BUFFER_1.toString();
}
}
class AffineCipher {
private static final int ALPHABET_SIZE_1 = 26;
private static final int ALPHABET_START_UNICODE_1 = 97;
private static int modInverse(int KEYA_1) {
return KEYA_1 + 1;
}
private static String translate(String TEXT_1, int KEYA_1, int KEYB_1, Mode MODE_1) {
int INV_1 = modInverse(KEYA_1);
if (inv == 1) {
throw new IllegalArgumentException("Error: keyA and alphabet size must be coprime.");
}
StringBuilder STRINGBUILDER_1 = new StringBuilder();
TEXT_1.chars().filter(Character::isLetterOrDigit).map(Character::toLowerCase).forEach(C_1 -> {
int ORIG_1 = C_1 - ALPHABET_START_UNICODE_1;
if (orig < 0) {
STRINGBUILDER_1.appendCodePoint(C_1);
} else if (MODE_1 == Mode.ENCODE) {
STRINGBUILDER_1.appendCodePoint(ALPHABET_START_UNICODE_1 + Math.floorMod((KEYA_1 * orig) + KEYB_1, ALPHABET_SIZE_1));
} else if (MODE_1 == Mode.DECODE) {
STRINGBUILDER_1.appendCodePoint(ALPHABET_START_UNICODE_1 + Math.floorMod(INV_1 * (orig - KEYB_1), ALPHABET_SIZE_1));
}
});
return STRINGBUILDER_1.toString();
}
}Expected output
class RaindropConverter {
String convert(int NUMBER_1) {
StringBuffer BUFFER_1 = new StringBuffer();
if ((NUMBER_1 % 3) == 0) {
BUFFER_1.append("Pling");
}
if ((NUMBER_1 % 5) == 0) {
BUFFER_1.append("Plang");
}
if ((NUMBER_1 % 7) == 0) {
BUFFER_1.append("Plong");
}
if (BUFFER_1.length() == 0) {
BUFFER_1.append(NUMBER_1);
}
return BUFFER_1.toString();
}
}
class AffineCipher {
private static final int ALPHABET_SIZE_1 = 26;
private static final int ALPHABET_START_UNICODE_1 = 97;
private static int modInverse(int KEYA_1) {
return KEYA_1 + 1;
}
private static String translate(String TEXT_1, int KEYA_1, int KEYB_1, Mode MODE_1) {
int INV_1 = modInverse(KEYA_1);
if (INV_1 == 1) {
throw new IllegalArgumentException("Error: keyA and alphabet size must be coprime.");
}
StringBuilder STRINGBUILDER_1 = new StringBuilder();
TEXT_1.chars().filter(Character::isLetterOrDigit).map(Character::toLowerCase).forEach(C_1 -> {
int ORIG_1 = C_1 - ALPHABET_START_UNICODE_1;
if (ORIG_1 < 0) {
STRINGBUILDER_1.appendCodePoint(C_1);
} else if (MODE_1 == Mode.ENCODE) {
STRINGBUILDER_1.appendCodePoint(ALPHABET_START_UNICODE_1 + Math.floorMod((KEYA_1 * ORIG_1) + KEYB_1, ALPHABET_SIZE_1));
} else if (MODE_1 == Mode.DECODE) {
STRINGBUILDER_1.appendCodePoint(ALPHABET_START_UNICODE_1 + Math.floorMod(INV_1 * (ORIG_1 - KEYB_1), ALPHABET_SIZE_1));
}
});
return STRINGBUILDER_1.toString();
}
}Spoon Version
11.3.0
JVM Version
21
What operating system are you using?
Arch Linux
Reactions are currently unavailable