[Git][java-team/asm][upstream] 2 commits: New upstream version 9.10
Emmanuel Bourg (@ebourg)
gitlab at salsa.debian.org
Fri Sep 18 14:21:29 BST 2026
Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / asm
Commits:
f04a1bf7 by Emmanuel Bourg at 2026-09-18T14:56:14+02:00
New upstream version 9.10
- - - - -
edbc7f58 by Emmanuel Bourg at 2026-09-18T15:03:12+02:00
New upstream version 9.10.1
- - - - -
25 changed files:
- asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java
- asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java
- asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Value.java
- asm-commons/src/test/java/org/objectweb/asm/commons/LambdaRemapTest.java
- asm-commons/src/test/java/org/objectweb/asm/commons/MethodNodeBuilder.java
- asm-test/src/main/java/org/objectweb/asm/test/ClassFile.java
- asm-test/src/main/java/org/objectweb/asm/test/Util.java
- asm-test/src/test/java/org/objectweb/asm/test/ClassFileTest.java
- asm-tree/src/main/java/org/objectweb/asm/tree/InsnList.java
- asm-util/src/main/java/org/objectweb/asm/util/ASMifier.java
- asm-util/src/main/java/org/objectweb/asm/util/ASMifierSupport.java
- asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java
- asm-util/src/main/java/org/objectweb/asm/util/Textifier.java
- asm-util/src/main/java/org/objectweb/asm/util/TextifierSupport.java
- asm-util/src/main/java/org/objectweb/asm/util/TraceSignatureVisitor.java
- asm-util/src/test/java/org/objectweb/asm/util/TraceSignatureVisitorTest.java
- asm/src/main/java/org/objectweb/asm/ClassReader.java
- asm/src/main/java/org/objectweb/asm/Frame.java
- asm/src/main/java/org/objectweb/asm/Opcodes.java
- asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java
- asm/src/test/java/org/objectweb/asm/ConstantsTest.java
- benchmarks/src/jmh/java/org/objectweb/asm/benchmarks/AbstractBenchmark.java
- build.gradle
- tools/pmd.xml
- tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java
Changes:
=====================================
asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java
=====================================
@@ -119,15 +119,14 @@ public class Analyzer<V extends Value> implements Opcodes {
// For each exception handler, and each instruction within its range, record in 'handlers' the
// fact that execution can flow from this instruction to the exception handler.
- for (int i = 0; i < method.tryCatchBlocks.size(); ++i) {
- TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i);
+ for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
int startIndex = insnList.indexOf(tryCatchBlock.start);
int endIndex = insnList.indexOf(tryCatchBlock.end);
- for (int j = startIndex; j < endIndex; ++j) {
- List<TryCatchBlockNode> insnHandlers = handlers[j];
+ for (int i = startIndex; i < endIndex; ++i) {
+ List<TryCatchBlockNode> insnHandlers = handlers[i];
if (insnHandlers == null) {
insnHandlers = new ArrayList<>();
- handlers[j] = insnHandlers;
+ handlers[i] = insnHandlers;
}
insnHandlers.add(tryCatchBlock);
}
@@ -197,8 +196,7 @@ public class Analyzer<V extends Value> implements Opcodes {
currentFrame.initJumpTarget(insnOpcode, lookupSwitchInsn.dflt);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
- for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
- LabelNode label = lookupSwitchInsn.labels.get(i);
+ for (LabelNode label : lookupSwitchInsn.labels) {
targetInsnIndex = insnList.indexOf(label);
currentFrame.initJumpTarget(insnOpcode, label);
merge(targetInsnIndex, currentFrame, subroutine);
@@ -210,8 +208,7 @@ public class Analyzer<V extends Value> implements Opcodes {
currentFrame.initJumpTarget(insnOpcode, tableSwitchInsn.dflt);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
- for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
- LabelNode label = tableSwitchInsn.labels.get(i);
+ for (LabelNode label : tableSwitchInsn.labels) {
currentFrame.initJumpTarget(insnOpcode, label);
targetInsnIndex = insnList.indexOf(label);
merge(targetInsnIndex, currentFrame, subroutine);
@@ -221,8 +218,7 @@ public class Analyzer<V extends Value> implements Opcodes {
if (subroutine == null) {
throw new AnalyzerException(insnNode, "RET instruction outside of a subroutine");
}
- for (int i = 0; i < subroutine.callers.size(); ++i) {
- JumpInsnNode caller = subroutine.callers.get(i);
+ for (JumpInsnNode caller : subroutine.callers) {
int jsrInsnIndex = insnList.indexOf(caller);
if (frames[jsrInsnIndex] != null) {
merge(
=====================================
asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java
=====================================
@@ -93,8 +93,7 @@ final class Subroutine {
}
}
if (subroutine.start == start) {
- for (int i = 0; i < subroutine.callers.size(); ++i) {
- JumpInsnNode caller = subroutine.callers.get(i);
+ for (JumpInsnNode caller : subroutine.callers) {
if (!callers.contains(caller)) {
callers.add(caller);
changed = true;
=====================================
asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Value.java
=====================================
@@ -32,6 +32,7 @@ package org.objectweb.asm.tree.analysis;
*
* @author Eric Bruneton
*/
+ at FunctionalInterface
public interface Value {
/**
=====================================
asm-commons/src/test/java/org/objectweb/asm/commons/LambdaRemapTest.java
=====================================
@@ -63,11 +63,9 @@ class LambdaRemapTest extends AsmTest implements Opcodes {
"metafactory",
LAMBDA_FACTORY_METAFACTORY,
false),
- new Object[] {
- Type.getType("()V"),
- new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
- Type.getType("()V")
- });
+ Type.getType("()V"),
+ new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
+ Type.getType("()V"));
}
void func_serializableLambda(final MethodVisitor methodVisitor) {
@@ -80,13 +78,11 @@ class LambdaRemapTest extends AsmTest implements Opcodes {
"altMetafactory",
LAMBDA_FACTORY_ALTMETAFACTORY,
false),
- new Object[] {
- Type.getType("()V"),
- new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
- Type.getType("()V"),
- Integer.valueOf(5),
- Integer.valueOf(0)
- });
+ Type.getType("()V"),
+ new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
+ Type.getType("()V"),
+ Integer.valueOf(5),
+ Integer.valueOf(0));
}
void func_advancedLambda(final MethodVisitor methodVisitor) {
@@ -99,15 +95,13 @@ class LambdaRemapTest extends AsmTest implements Opcodes {
"altMetafactory",
LAMBDA_FACTORY_ALTMETAFACTORY,
false),
- new Object[] {
- Type.getType("()V"),
- new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
- Type.getType("()V"),
- Integer.valueOf(7),
- Integer.valueOf(1),
- Type.getType("Lpkg/LambdaTest$TestInterface;"),
- Integer.valueOf(0)
- });
+ Type.getType("()V"),
+ new Handle(Opcodes.H_INVOKESTATIC, "java/lang/Thread", "dumpStack", "()V", false),
+ Type.getType("()V"),
+ Integer.valueOf(7),
+ Integer.valueOf(1),
+ Type.getType("Lpkg/LambdaTest$TestInterface;"),
+ Integer.valueOf(0));
}
public static Stream<Remapper> remappersLatest() {
=====================================
asm-commons/src/test/java/org/objectweb/asm/commons/MethodNodeBuilder.java
=====================================
@@ -191,7 +191,7 @@ final class MethodNodeBuilder {
MethodNodeBuilder switchto(
final Label defaultLabel, final int key, final Label target, final boolean useTableSwitch) {
if (useTableSwitch) {
- methodNode.visitTableSwitchInsn(key, key, defaultLabel, new Label[] {target});
+ methodNode.visitTableSwitchInsn(key, key, defaultLabel, target);
} else {
methodNode.visitLookupSwitchInsn(defaultLabel, new int[] {key}, new Label[] {target});
}
@@ -200,7 +200,7 @@ final class MethodNodeBuilder {
MethodNodeBuilder switchto(final Label label0, final Label label1, final boolean useTableSwitch) {
if (useTableSwitch) {
- methodNode.visitTableSwitchInsn(0, 1, label0, new Label[] {label0, label1});
+ methodNode.visitTableSwitchInsn(0, 1, label0, label0, label1);
} else {
methodNode.visitLookupSwitchInsn(label0, new int[] {1}, new Label[] {label1});
}
=====================================
asm-test/src/main/java/org/objectweb/asm/test/ClassFile.java
=====================================
@@ -2356,11 +2356,13 @@ public class ClassFile {
}
/** A context to lookup constant pool items from their index. */
+ @FunctionalInterface
private interface ClassContext {
<C extends CpInfo> C getCpInfo(int cpIndex, Class<C> cpInfoType);
}
/** A context to lookup instruction indices from their bytecode offset. */
+ @FunctionalInterface
private interface MethodContext {
int getInsnIndex(int bytecodeOffset);
}
@@ -2526,6 +2528,7 @@ public class ClassFile {
* @param opcode a bytecode instruction opcode.
* @param arguments the bytecode instruction arguments.
*/
+ @SuppressWarnings("PMD.UseArraysAsList") // false positive
void addInsn(final int insnIndex, final int opcode, final Object... arguments) {
children.add(insnIndex);
children.add(": ");
=====================================
asm-test/src/main/java/org/objectweb/asm/test/Util.java
=====================================
@@ -26,6 +26,7 @@ final class Util {
return Integer.parseInt(javaMajorVersionText);
}
+ @SuppressWarnings("PMD.PreserveStackTrace")
static boolean previewFeatureEnabled() {
try {
Class<?> managementFactoryClass = Class.forName("java.lang.management.ManagementFactory");
=====================================
asm-test/src/test/java/org/objectweb/asm/test/ClassFileTest.java
=====================================
@@ -62,6 +62,7 @@ class ClassFileTest extends AsmTest {
*/
@ParameterizedTest
@EnumSource(InvalidClass.class)
+ @SuppressWarnings("PMD.ExhaustiveSwitchHasDefault") // Checkstyle complains if default is missing!
void testStaticNewInstance_invalidClass(final InvalidClass invalidClass) {
String className = invalidClass.toString();
byte[] classContent = invalidClass.getBytes();
=====================================
asm-tree/src/main/java/org/objectweb/asm/tree/InsnList.java
=====================================
@@ -226,7 +226,6 @@ public class InsnList implements Iterable<AbstractInsnNode> {
++size;
if (lastInsn == null) {
firstInsn = insnNode;
- lastInsn = insnNode;
} else {
lastInsn.nextInsn = insnNode;
insnNode.previousInsn = lastInsn;
@@ -268,7 +267,6 @@ public class InsnList implements Iterable<AbstractInsnNode> {
public void insert(final AbstractInsnNode insnNode) {
++size;
if (firstInsn == null) {
- firstInsn = insnNode;
lastInsn = insnNode;
} else {
firstInsn.previousInsn = insnNode;
=====================================
asm-util/src/main/java/org/objectweb/asm/util/ASMifier.java
=====================================
@@ -116,6 +116,7 @@ public class ASMifier extends Printer {
classVersions.put(Opcodes.V24, "V24");
classVersions.put(Opcodes.V25, "V25");
classVersions.put(Opcodes.V26, "V26");
+ classVersions.put(Opcodes.V27, "V27");
CLASS_VERSIONS = Collections.unmodifiableMap(classVersions);
}
@@ -273,8 +274,7 @@ public class ASMifier extends Printer {
@Override
public Printer visitModule(final String name, final int flags, final String version) {
stringBuilder.setLength(0);
- stringBuilder.append("{\n");
- stringBuilder.append("ModuleVisitor moduleVisitor = classWriter.visitModule(");
+ stringBuilder.append("{\nModuleVisitor moduleVisitor = classWriter.visitModule(");
appendConstant(name);
stringBuilder.append(", ");
appendAccessFlags(flags | ACCESS_MODULE);
@@ -364,8 +364,7 @@ public class ASMifier extends Printer {
public ASMifier visitRecordComponent(
final String name, final String descriptor, final String signature) {
stringBuilder.setLength(0);
- stringBuilder.append("{\n");
- stringBuilder.append("recordComponentVisitor = classWriter.visitRecordComponent(");
+ stringBuilder.append("{\nrecordComponentVisitor = classWriter.visitRecordComponent(");
appendConstant(name);
stringBuilder.append(", ");
appendConstant(descriptor);
@@ -387,8 +386,7 @@ public class ASMifier extends Printer {
final String signature,
final Object value) {
stringBuilder.setLength(0);
- stringBuilder.append("{\n");
- stringBuilder.append("fieldVisitor = classWriter.visitField(");
+ stringBuilder.append("{\nfieldVisitor = classWriter.visitField(");
appendAccessFlags(access | ACCESS_FIELD);
stringBuilder.append(", ");
appendConstant(name);
@@ -414,8 +412,7 @@ public class ASMifier extends Printer {
final String signature,
final String[] exceptions) {
stringBuilder.setLength(0);
- stringBuilder.append("{\n");
- stringBuilder.append("methodVisitor = classWriter.visitMethod(");
+ stringBuilder.append("{\nmethodVisitor = classWriter.visitMethod(");
appendAccessFlags(access);
stringBuilder.append(", ");
appendConstant(name);
@@ -575,11 +572,11 @@ public class ASMifier extends Printer {
public ASMifier visitAnnotation(final String name, final String descriptor) {
stringBuilder.setLength(0);
stringBuilder
- .append("{\n")
- .append("AnnotationVisitor annotationVisitor")
+ .append("{\nAnnotationVisitor annotationVisitor")
.append(id + 1)
- .append(" = annotationVisitor");
- stringBuilder.append(id).append(".visitAnnotation(");
+ .append(" = annotationVisitor")
+ .append(id)
+ .append(".visitAnnotation(");
appendConstant(name);
stringBuilder.append(", ");
appendConstant(descriptor);
@@ -594,12 +591,12 @@ public class ASMifier extends Printer {
@Override
public ASMifier visitArray(final String name) {
stringBuilder.setLength(0);
- stringBuilder.append("{\n");
stringBuilder
- .append("AnnotationVisitor annotationVisitor")
+ .append("{\nAnnotationVisitor annotationVisitor")
.append(id + 1)
- .append(" = annotationVisitor");
- stringBuilder.append(id).append(".visitArray(");
+ .append(" = annotationVisitor")
+ .append(id)
+ .append(".visitArray(");
appendConstant(name);
stringBuilder.append(");\n");
text.add(stringBuilder.toString());
@@ -887,9 +884,7 @@ public class ASMifier extends Printer {
appendConstant(name);
stringBuilder.append(", ");
appendConstant(descriptor);
- stringBuilder.append(", ");
- stringBuilder.append(isInterface ? "true" : "false");
- stringBuilder.append(");\n");
+ stringBuilder.append(", ").append(isInterface ? "true" : "false").append(");\n");
text.add(stringBuilder.toString());
}
@@ -1244,8 +1239,7 @@ public class ASMifier extends Printer {
}
stringBuilder.append("{\n");
((ASMifierSupport) attribute).asmify(stringBuilder, "attribute", labelNames);
- stringBuilder.append(name).append(".visitAttribute(attribute);\n");
- stringBuilder.append("}\n");
+ stringBuilder.append(name).append(".visitAttribute(attribute);\n}\n");
}
text.add(stringBuilder.toString());
}
@@ -1449,22 +1443,30 @@ public class ASMifier extends Printer {
} else if (value instanceof String) {
appendString(stringBuilder, (String) value);
} else if (value instanceof Type) {
- stringBuilder.append("Type.getType(\"");
- stringBuilder.append(((Type) value).getDescriptor());
- stringBuilder.append("\")");
+ stringBuilder.append("Type.getType(\"").append(((Type) value).getDescriptor()).append("\")");
} else if (value instanceof Handle) {
stringBuilder.append("new Handle(");
Handle handle = (Handle) value;
- stringBuilder.append("Opcodes.").append(HANDLE_TAG[handle.getTag()]).append(", \"");
- stringBuilder.append(handle.getOwner()).append(COMMA);
- stringBuilder.append(handle.getName()).append(COMMA);
- stringBuilder.append(handle.getDesc()).append("\", ");
- stringBuilder.append(handle.isInterface()).append(')');
+ stringBuilder
+ .append("Opcodes.")
+ .append(HANDLE_TAG[handle.getTag()])
+ .append(", \"")
+ .append(handle.getOwner())
+ .append(COMMA)
+ .append(handle.getName())
+ .append(COMMA)
+ .append(handle.getDesc())
+ .append("\", ")
+ .append(handle.isInterface())
+ .append(')');
} else if (value instanceof ConstantDynamic) {
stringBuilder.append("new ConstantDynamic(\"");
ConstantDynamic constantDynamic = (ConstantDynamic) value;
- stringBuilder.append(constantDynamic.getName()).append(COMMA);
- stringBuilder.append(constantDynamic.getDescriptor()).append("\", ");
+ stringBuilder
+ .append(constantDynamic.getName())
+ .append(COMMA)
+ .append(constantDynamic.getDescriptor())
+ .append("\", ");
appendConstant(constantDynamic.getBootstrapMethod());
stringBuilder.append(NEW_OBJECT_ARRAY);
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
=====================================
asm-util/src/main/java/org/objectweb/asm/util/ASMifierSupport.java
=====================================
@@ -30,6 +30,7 @@ import org.objectweb.asm.Label;
*
* @author Eugene Kuleshov
*/
+ at FunctionalInterface
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public interface ASMifierSupport {
=====================================
asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java
=====================================
@@ -158,8 +158,7 @@ class CheckFrameAnalyzer<V extends Value> extends Analyzer<V> {
LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame= */ true);
- for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
- LabelNode label = lookupSwitchInsn.labels.get(i);
+ for (LabelNode label : lookupSwitchInsn.labels) {
targetInsnIndex = insnList.indexOf(label);
currentFrame.initJumpTarget(insnOpcode, label);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame= */ true);
@@ -171,8 +170,7 @@ class CheckFrameAnalyzer<V extends Value> extends Analyzer<V> {
currentFrame.initJumpTarget(insnOpcode, tableSwitchInsn.dflt);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame= */ true);
newControlFlowEdge(insnIndex, targetInsnIndex);
- for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
- LabelNode label = tableSwitchInsn.labels.get(i);
+ for (LabelNode label : tableSwitchInsn.labels) {
currentFrame.initJumpTarget(insnOpcode, label);
targetInsnIndex = insnList.indexOf(label);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame= */ true);
=====================================
asm-util/src/main/java/org/objectweb/asm/util/Textifier.java
=====================================
@@ -350,9 +350,7 @@ public class Textifier extends Printer {
stringBuilder.append(tab);
appendDescriptor(FIELD_DESCRIPTOR, descriptor);
- stringBuilder.append(' ').append(name);
-
- stringBuilder.append('\n');
+ stringBuilder.append(' ').append(name).append('\n');
text.add(stringBuilder.toString());
return addNewTextifier(null);
}
@@ -500,8 +498,7 @@ public class Textifier extends Printer {
private void visitExportOrOpen(
final String method, final String packaze, final int access, final String... modules) {
stringBuilder.setLength(0);
- stringBuilder.append(tab).append(method);
- stringBuilder.append(packaze);
+ stringBuilder.append(tab).append(method).append(packaze);
if (modules != null && modules.length > 0) {
stringBuilder.append(" to");
} else {
@@ -510,8 +507,10 @@ public class Textifier extends Printer {
appendRawAccess(access);
if (modules != null && modules.length > 0) {
for (int i = 0; i < modules.length; ++i) {
- stringBuilder.append(tab2).append(modules[i]);
- stringBuilder.append(i != modules.length - 1 ? ",\n" : ";\n");
+ stringBuilder
+ .append(tab2)
+ .append(modules[i])
+ .append(i != modules.length - 1 ? ",\n" : ";\n");
}
}
text.add(stringBuilder.toString());
@@ -791,9 +790,11 @@ public class Textifier extends Printer {
@Override
public Textifier visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
stringBuilder.setLength(0);
- stringBuilder.append(tab2).append("// annotable parameter count: ");
- stringBuilder.append(parameterCount);
- stringBuilder.append(visible ? " (visible)\n" : " (invisible)\n");
+ stringBuilder
+ .append(tab2)
+ .append("// annotable parameter count: ")
+ .append(parameterCount)
+ .append(visible ? " (visible)\n" : " (invisible)\n");
text.add(stringBuilder.toString());
return this;
}
@@ -833,8 +834,7 @@ public class Textifier extends Printer {
final int numStack,
final Object[] stack) {
stringBuilder.setLength(0);
- stringBuilder.append(ltab);
- stringBuilder.append("FRAME ");
+ stringBuilder.append(ltab).append("FRAME ");
switch (type) {
case Opcodes.F_NEW:
case Opcodes.F_FULL:
@@ -939,17 +939,13 @@ public class Textifier extends Printer {
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
stringBuilder.setLength(0);
- stringBuilder.append(tab2).append("INVOKEDYNAMIC").append(' ');
- stringBuilder.append(name);
+ stringBuilder.append(tab2).append("INVOKEDYNAMIC").append(' ').append(name);
appendDescriptor(METHOD_DESCRIPTOR, descriptor);
- stringBuilder.append(" [");
- stringBuilder.append('\n');
- stringBuilder.append(tab3);
+ stringBuilder.append(" [").append('\n').append(tab3);
appendHandle(bootstrapMethodHandle, tab3);
stringBuilder.append('\n').append(tab3);
appendBoostrapMethodArgs(bootstrapMethodArguments, tab3);
- stringBuilder.append('\n');
- stringBuilder.append(tab2).append("]\n");
+ stringBuilder.append('\n').append(tab2).append("]\n");
text.add(stringBuilder.toString());
}
@@ -1075,8 +1071,7 @@ public class Textifier extends Printer {
stringBuilder.setLength(0);
stringBuilder.append(") : ");
appendTypeReference(typeRef);
- stringBuilder.append(", ").append(typePath);
- stringBuilder.append(visible ? "\n" : INVISIBLE);
+ stringBuilder.append(", ").append(typePath).append(visible ? "\n" : INVISIBLE);
return addNewTextifier(stringBuilder.toString());
}
@@ -1204,8 +1199,7 @@ public class Textifier extends Printer {
stringBuilder.setLength(0);
stringBuilder.append(") : ");
appendTypeReference(typeRef);
- stringBuilder.append(", ").append(typePath);
- stringBuilder.append(visible ? "\n" : INVISIBLE);
+ stringBuilder.append(", ").append(typePath).append(visible ? "\n" : INVISIBLE);
return addNewTextifier(stringBuilder.toString());
}
@@ -1324,8 +1318,9 @@ public class Textifier extends Printer {
.append(condy.getName())
.append(" : ")
.append(condy.getDescriptor())
- .append(" [\n");
- stringBuilder.append(condyIndent).append(tab);
+ .append(" [\n")
+ .append(condyIndent)
+ .append(tab);
appendHandle(condy.getBootstrapMethod(), condyIndent + tab);
stringBuilder.append('\n').append(condyIndent).append(tab);
Object[] bsmArgs = new Object[condy.getBootstrapMethodArgumentCount()];
@@ -1414,11 +1409,9 @@ public class Textifier extends Printer {
new SignatureReader(signature).accept(traceSignatureVisitor);
stringBuilder.append("// declaration: ");
if (traceSignatureVisitor.getReturnType() != null) {
- stringBuilder.append(traceSignatureVisitor.getReturnType());
- stringBuilder.append(' ');
+ stringBuilder.append(traceSignatureVisitor.getReturnType()).append(' ');
}
- stringBuilder.append(name);
- stringBuilder.append(traceSignatureVisitor.getDeclaration());
+ stringBuilder.append(name).append(traceSignatureVisitor.getDeclaration());
if (traceSignatureVisitor.getExceptions() != null) {
stringBuilder.append(" throws ").append(traceSignatureVisitor.getExceptions());
}
@@ -1500,11 +1493,9 @@ public class Textifier extends Printer {
default:
throw new IllegalArgumentException();
}
- stringBuilder.append('\n');
- stringBuilder.append(afterComment);
+ stringBuilder.append('\n').append(afterComment);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
- stringBuilder.append('.');
- stringBuilder.append(handle.getName());
+ stringBuilder.append('.').append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
=====================================
asm-util/src/main/java/org/objectweb/asm/util/TextifierSupport.java
=====================================
@@ -29,6 +29,7 @@ import org.objectweb.asm.Label;
*
* @author Eugene Kuleshov
*/
+ at FunctionalInterface
public interface TextifierSupport {
/**
=====================================
asm-util/src/main/java/org/objectweb/asm/util/TraceSignatureVisitor.java
=====================================
@@ -27,6 +27,7 @@
// THE POSSIBILITY OF SUCH DAMAGE.
package org.objectweb.asm.util;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -86,19 +87,17 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
/** Whether {@link #visitInterface} has been called. */
private boolean interfaceVisited;
- /**
- * The stack used to keep track of class types that have arguments. Each element of this stack is
- * a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false
- * = *2, pushing true = *2+1, popping = /2.
- */
- private int argumentStack;
+ /** A delayed task to perform when a type or a list of type arguments has been visited. */
+ static enum Task {
+ END_ARRAY_TYPE,
+ END_EMPTY_TYPE_ARGUMENTS,
+ END_NON_EMPTY_TYPE_ARGUMENTS,
+ }
/**
- * The stack used to keep track of array class types. Each element of this stack is a boolean
- * encoded in one bit. The top of the stack is the lowest order bit. Pushing false = *2, pushing
- * true = *2+1, popping = /2.
+ * A stack of pending tasks to perform when a type or a list of type arguments has been visited.
*/
- private int arrayStack;
+ private ArrayList<Task> pendingTasks = new ArrayList<>();
/** The separator to append before the next visited class or inner class type. */
private String separator = "";
@@ -130,7 +129,6 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
@Override
public SignatureVisitor visitClassBound() {
separator = EXTENDS_SEPARATOR;
- startType();
return this;
}
@@ -138,7 +136,6 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
public SignatureVisitor visitInterfaceBound() {
separator = interfaceBoundVisited ? COMMA_SEPARATOR : EXTENDS_SEPARATOR;
interfaceBoundVisited = true;
- startType();
return this;
}
@@ -146,7 +143,6 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
public SignatureVisitor visitSuperclass() {
endFormals();
separator = EXTENDS_SEPARATOR;
- startType();
return this;
}
@@ -158,7 +154,6 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
separator = isInterface ? EXTENDS_SEPARATOR : IMPLEMENTS_SEPARATOR;
interfaceVisited = true;
}
- startType();
return this;
}
@@ -171,7 +166,6 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
declaration.append('(');
parameterTypeVisited = true;
}
- startType();
return this;
}
@@ -217,8 +211,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
@Override
public SignatureVisitor visitArrayType() {
- startType();
- arrayStack |= 1;
+ pendingTasks.add(Task.END_ARRAY_TYPE);
return this;
}
@@ -227,7 +220,10 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
if ("java/lang/Object".equals(name)) {
// 'Map<java.lang.Object,java.util.List>' or 'abstract public V get(Object key);' should have
// Object 'but java.lang.String extends java.lang.Object' is unnecessary.
- boolean needObjectClass = argumentStack % 2 != 0 || parameterTypeVisited;
+ boolean needObjectClass =
+ (!pendingTasks.isEmpty()
+ && pendingTasks.get(pendingTasks.size() - 1) == Task.END_NON_EMPTY_TYPE_ARGUMENTS)
+ || parameterTypeVisited;
if (needObjectClass) {
declaration.append(separator).append(name.replace('/', '.'));
}
@@ -235,25 +231,22 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
declaration.append(separator).append(name.replace('/', '.'));
}
separator = "";
- argumentStack *= 2;
+ pendingTasks.add(Task.END_EMPTY_TYPE_ARGUMENTS);
}
@Override
public void visitInnerClassType(final String name) {
- if (argumentStack % 2 != 0) {
- declaration.append('>');
- }
- argumentStack /= 2;
- declaration.append('.');
- declaration.append(separator).append(name.replace('/', '.'));
+ endTypeArguments();
+ declaration.append('.').append(separator).append(name.replace('/', '.'));
+ pendingTasks.add(Task.END_EMPTY_TYPE_ARGUMENTS);
separator = "";
- argumentStack *= 2;
}
@Override
public void visitTypeArgument() {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
+ int lastTaskIndex = pendingTasks.size() - 1;
+ if (pendingTasks.get(lastTaskIndex) == Task.END_EMPTY_TYPE_ARGUMENTS) {
+ pendingTasks.set(lastTaskIndex, Task.END_NON_EMPTY_TYPE_ARGUMENTS);
declaration.append('<');
} else {
declaration.append(COMMA_SEPARATOR);
@@ -263,29 +256,24 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
@Override
public SignatureVisitor visitTypeArgument(final char tag) {
- if (argumentStack % 2 == 0) {
- ++argumentStack;
+ int lastTaskIndex = pendingTasks.size() - 1;
+ if (pendingTasks.get(lastTaskIndex) == Task.END_EMPTY_TYPE_ARGUMENTS) {
+ pendingTasks.set(lastTaskIndex, Task.END_NON_EMPTY_TYPE_ARGUMENTS);
declaration.append('<');
} else {
declaration.append(COMMA_SEPARATOR);
}
-
if (tag == EXTENDS) {
declaration.append("? extends ");
} else if (tag == SUPER) {
declaration.append("? super ");
}
-
- startType();
return this;
}
@Override
public void visitEnd() {
- if (argumentStack % 2 != 0) {
- declaration.append('>');
- }
- argumentStack /= 2;
+ endTypeArguments();
endType();
}
@@ -327,18 +315,17 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
}
}
- private void startType() {
- arrayStack *= 2;
+ private void endTypeArguments() {
+ if (pendingTasks.remove(pendingTasks.size() - 1) == Task.END_NON_EMPTY_TYPE_ARGUMENTS) {
+ declaration.append('>');
+ }
}
private void endType() {
- if (arrayStack % 2 == 0) {
- arrayStack /= 2;
- } else {
- while (arrayStack % 2 != 0) {
- arrayStack /= 2;
- declaration.append("[]");
- }
+ int numTasks = pendingTasks.size();
+ while (numTasks > 0 && pendingTasks.get(--numTasks) == Task.END_ARRAY_TYPE) {
+ declaration.append("[]");
+ pendingTasks.remove(numTasks);
}
}
}
=====================================
asm-util/src/test/java/org/objectweb/asm/util/TraceSignatureVisitorTest.java
=====================================
@@ -88,7 +88,8 @@ class TraceSignatureVisitorTest {
{
"java.util.Hashtable<java.lang.Object, java.lang.String>",
"Ljava/util/Hashtable<Ljava/lang/Object;Ljava/lang/String;>;"
- }
+ },
+ {"java.util.List<java.lang.Boolean[]>[][][]", "[[[Ljava/util/List<[Ljava/lang/Boolean;>;"}
};
private static final String[][] METHOD_SIGNATURES = {
@@ -119,6 +120,10 @@ class TraceSignatureVisitorTest {
{
"java.util.Map<java.lang.Object, java.lang.String><E, T extends java.lang.Comparable<E>>(java.lang.Object, java.util.Map<java.lang.Object, java.lang.String>, T)",
"<E:Ljava/lang/Object;T::Ljava/lang/Comparable<TE;>;>(Ljava/lang/Object;Ljava/util/Map<Ljava/lang/Object;Ljava/lang/String;>;TT;)Ljava/util/Map<Ljava/lang/Object;Ljava/lang/String;>;"
+ },
+ {
+ "(java.util.Map<java.util.Map<java.lang.String, ? extends java.util.List<? super java.lang.Runnable>>, java.util.List<java.lang.Boolean[]>[]>)",
+ "(Ljava/util/Map<Ljava/util/Map<Ljava/lang/String;+Ljava/util/List<-Ljava/lang/Runnable;>;>;[Ljava/util/List<[Ljava/lang/Boolean;>;>;)Ljava/lang/Object;"
}
};
=====================================
asm/src/main/java/org/objectweb/asm/ClassReader.java
=====================================
@@ -195,7 +195,7 @@ public class ClassReader {
this.b = classFileBuffer;
// Check the class' major_version. This field is after the magic and minor_version fields, which
// use 4 and 2 bytes respectively.
- if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V26) {
+ if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V27) {
throw new IllegalArgumentException(
"Unsupported class file major version " + readShort(classFileOffset + 6));
}
=====================================
asm/src/main/java/org/objectweb/asm/Frame.java
=====================================
@@ -577,7 +577,8 @@ class Frame {
return outputStack[--outputStackTop];
} else {
// If the output frame stack is empty, pop from the input stack.
- return STACK_KIND | -(--outputStackStart);
+ --outputStackStart;
+ return STACK_KIND | -outputStackStart;
}
}
=====================================
asm/src/main/java/org/objectweb/asm/Opcodes.java
=====================================
@@ -293,6 +293,7 @@ public interface Opcodes {
int V24 = 0 << 16 | 68;
int V25 = 0 << 16 | 69;
int V26 = 0 << 16 | 70;
+ int V27 = 0 << 16 | 71;
/**
* Version flag indicating that the class is using 'preview' features.
=====================================
asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java
=====================================
@@ -89,8 +89,7 @@ public class SignatureWriter extends SignatureVisitor {
hasFormals = true;
stringBuilder.append('<');
}
- stringBuilder.append(name);
- stringBuilder.append(':');
+ stringBuilder.append(name).append(':');
}
@Override
@@ -148,9 +147,7 @@ public class SignatureWriter extends SignatureVisitor {
@Override
public void visitTypeVariable(final String name) {
- stringBuilder.append('T');
- stringBuilder.append(name);
- stringBuilder.append(';');
+ stringBuilder.append('T').append(name).append(';');
}
@Override
@@ -161,8 +158,7 @@ public class SignatureWriter extends SignatureVisitor {
@Override
public void visitClassType(final String name) {
- stringBuilder.append('L');
- stringBuilder.append(name);
+ stringBuilder.append('L').append(name);
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
// we can tell at this point).
argumentStack <<= 1;
@@ -171,8 +167,7 @@ public class SignatureWriter extends SignatureVisitor {
@Override
public void visitInnerClassType(final String name) {
endArguments();
- stringBuilder.append('.');
- stringBuilder.append(name);
+ stringBuilder.append('.').append(name);
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
// we can tell at this point).
argumentStack <<= 1;
=====================================
asm/src/test/java/org/objectweb/asm/ConstantsTest.java
=====================================
@@ -259,6 +259,7 @@ class ConstantsTest {
case "V24":
case "V25":
case "V26":
+ case "V27":
return ConstantType.CLASS_VERSION;
case "ACC_PUBLIC":
case "ACC_PRIVATE":
=====================================
benchmarks/src/jmh/java/org/objectweb/asm/benchmarks/AbstractBenchmark.java
=====================================
@@ -81,6 +81,7 @@ public abstract class AbstractBenchmark {
ArrayList<byte[]> java8classFiles;
/** The ASM versions that can be benchmarked. */
+ @SuppressWarnings("PMD.ExhaustiveSwitchHasDefault") // Checkstyle complains if default is missing!
public enum AsmVersion {
V4_0,
V5_0,
=====================================
build.gradle
=====================================
@@ -47,8 +47,8 @@ dependencies {
allprojects {
group = 'org.ow2.asm'
- version = '9.9.1' + (rootProject.hasProperty('release') ? '' : '-SNAPSHOT')
- ext.osgi_version_upper_bound = '9.10'
+ version = '9.10.1' + (rootProject.hasProperty('release') ? '' : '-SNAPSHOT')
+ ext.osgi_version_upper_bound = '9.11'
}
subprojects {
@@ -223,8 +223,8 @@ subprojects {
tasks.withType(AbstractArchiveTask).configureEach {
preserveFileTimestamps = false
reproducibleFileOrder = true
- dirMode = 0775
- fileMode = 0664
+ dirPermissions { unix("0755") }
+ filePermissions { unix("0664") }
}
}
@@ -233,7 +233,7 @@ subprojects {
// and packaged with generated module-info classes.
configure(subprojects.findAll{it.provides}) {
// Code coverage configuration.
- jacoco.toolVersion = '0.8.12'
+ jacoco.toolVersion = '0.8.14'
jacocoTestReport {
reports { xml.required = true }
classDirectories.setFrom(sourceSets.main.output.classesDirs)
@@ -253,9 +253,9 @@ configure(subprojects.findAll{it.provides}) {
// Retrofit the code in-place to Java 1.5 and generate a module-info class
// from the code content, in compileJava.doLast.
if (name != 'asm-test') {
+ def path = project(':tools:retrofitter').sourceSets.main.runtimeClasspath
compileJava.dependsOn ':tools:retrofitter:classes'
compileJava.doLast {
- def path = project(':tools:retrofitter').sourceSets.main.runtimeClasspath
def loader = new URLClassLoader(path.collect {f -> f.toURL()} as URL[])
def retrofitter =
loader.loadClass('org.objectweb.asm.tools.Retrofitter').newInstance()
@@ -269,6 +269,7 @@ configure(subprojects.findAll{it.provides}) {
// Create one backward compatibility checking task for each 'sigtest-*' file
// in test/resources, and make the 'check' task depend on all these tasks.
if (file('src/test/resources/').exists()) {
+ def jdk8ApiJarPath = project(':tools').file('jdk8-api.jar').path
file('src/test/resources/').eachFileMatch(~/sigtest-.*/) { f ->
task "${f.name}"(dependsOn: 'classes') {
inputs.files(f, sourceSets.main.java)
@@ -277,7 +278,7 @@ configure(subprojects.findAll{it.provides}) {
def sigtest = new com.sun.tdk.signaturetest.SignatureTest()
def args = ['-ApiVersion', version, '-Backward', '-Static',
'-Mode', 'bin', '-FileName', f, '-Classpath',
- project(':tools').file('jdk8-api.jar').path + File.pathSeparator +
+ jdk8ApiJarPath + File.pathSeparator +
sourceSets.main.output.classesDirs.asPath, '-Package'] + provides
outputs.getFiles()[0].withPrintWriter { printWriter ->
sigtest.run(args as String[], printWriter, null)
@@ -294,7 +295,7 @@ configure(subprojects.findAll{it.provides}) {
doLast {
def setup = new com.sun.tdk.signaturetest.Setup()
def args = ['-ApiVersion', version, '-FileName', outputs.getFiles()[0],
- '-Classpath', project(':tools').file('jdk8-api.jar').path +
+ '-Classpath', jdk8ApiJarPath +
File.pathSeparator + sourceSets.main.output.classesDirs.asPath +
File.pathSeparator + sourceSets.main.compileClasspath.asPath,
'-Package'] + provides
@@ -381,15 +382,15 @@ configure([rootProject] + subprojects.findAll { it.provides }) {
name = 'nexus'
url = rootProject.hasProperty('release') ? releasesUrl : snapshotsUrl
credentials {
- username System.env.NEXUS_USER_NAME
- password System.env.NEXUS_PASSWORD
+ username = System.env.NEXUS_USER_NAME
+ password = System.env.NEXUS_PASSWORD
}
}
}
publications {
maven(MavenPublication) {
def isRoot = project == rootProject
- artifactId (isRoot ? 'asm-bom' : project.name)
+ artifactId = (isRoot ? 'asm-bom' : project.name)
from (isRoot ? components.javaPlatform : components.java)
pom.withXml {
def parent = asNode().appendNode('parent')
@@ -460,7 +461,7 @@ configure([rootProject] + subprojects.findAll { it.provides }) {
}
}
signing {
- required rootProject.hasProperty('release')
+ required = rootProject.hasProperty('release')
sign publishing.publications.maven
}
tasks.withType(GenerateModuleMetadata) { enabled = false }
=====================================
tools/pmd.xml
=====================================
@@ -20,17 +20,11 @@
<exclude name="CheckResultSet" />
<!-- Already covered with Checkstyle 'InterfaceIsType' rule. -->
<exclude name="ConstantsInInterface" />
- <!-- Already covered with Checkstyle 'DefaultComesLast' rule. -->
- <exclude name="DefaultLabelNotLastInSwitchStmt" />
- <!-- Not relevant for ASM (no logging and using JUnit 5). -->
+ <!-- Not relevant for ASM (no logging). -->
<exclude name="GuardLogStatement" />
- <exclude name="JUnit4SuitesShouldUseSuiteAnnotation" />
- <exclude name="JUnit4TestShouldUseAfterAnnotation" />
- <exclude name="JUnit4TestShouldUseBeforeAnnotation" />
- <exclude name="JUnit4TestShouldUseTestAnnotation" />
<!-- Would give too verbose code. -->
- <exclude name="JUnitAssertionsShouldIncludeMessage" />
- <exclude name="JUnitTestContainsTooManyAsserts" />
+ <exclude name="UnitTestAssertionsShouldIncludeMessage" />
+ <exclude name="UnitTestContainsTooManyAsserts" />
<!-- Not relevant for ASM (using JUnit 5). -->
<exclude name="JUnitUseExpected" />
<!-- Already covered with Checkstyle 'IllegalType' rule. -->
@@ -40,24 +34,20 @@
<!-- Actually not a best practice. -->
<exclude name="LiteralsFirstInComparisons" />
<!-- Already covered with Checkstyle 'MissingSwitchDefault' rule. -->
- <exclude name="SwitchStmtsShouldHaveDefault" />
<!-- Already covered with google-java-format. -->
- <exclude name="UnusedImports" />
<!-- Too many false positives. -->
<exclude name="UseVarargs" />
</rule>
<rule ref="category/java/bestpractices.xml/ArrayIsStoredDirectly">
<properties>
<property name="violationSuppressXPath"
- value="//MethodDeclaration[@Private='true' or
- @PackagePrivate='true']" />
+ value="//MethodDeclaration[@Visibility!='public']" />
</properties>
</rule>
<rule ref="category/java/bestpractices.xml/MethodReturnsInternalArray">
<properties>
<property name="violationSuppressXPath"
- value="//MethodDeclaration[@Private='true' or
- @PackagePrivate='true']" />
+ value="//MethodDeclaration[@Visibility!='public']" />
</properties>
</rule>
<rule ref="category/java/bestpractices.xml/ForLoopVariableCount">
@@ -77,8 +67,6 @@
<exclude name="AvoidLiteralsInIfCondition" />
<!-- Too many false positives. -->
<exclude name="CompareObjectsWithEquals" />
- <!-- Does not work, too many false positives. -->
- <exclude name="DataflowAnomalyAnalysis" />
<!-- Not relevant for ASM. -->
<exclude name="DoNotHardCodeSDCard" />
<exclude name="DontImportSun" />
@@ -87,11 +75,6 @@
<exclude name="FinalizeOnlyCallsSuperFinalize" />
<exclude name="FinalizeOverloaded" />
<exclude name="FinalizeShouldBeProtected" />
- <!-- Not relevant for ASM (no logging and using JUnit 5). -->
- <exclude name="JUnitSpelling" />
- <exclude name="JUnitStaticSuite" />
- <exclude name="LoggerIsNotStaticFinal" />
- <exclude name="MoreThanOneLogger" />
<!-- Needed to implement custom data structures such as linked lists. -->
<exclude name="NullAssignment" />
<!-- Not relevant for ASM (no logging, no dates, no EJB). -->
@@ -103,15 +86,13 @@
<rule ref="category/java/errorprone.xml/ReturnEmptyCollectionRatherThanNull">
<properties>
<property name="violationSuppressXPath"
- value="//MethodDeclaration[@Private='true']"/>
+ value="//MethodDeclaration[@Visibility!='public']"/>
</properties>
</rule>
<rule ref="category/java/performance.xml">
<!-- Too many false positives. -->
<exclude name="AvoidInstantiatingObjectsInLoops" />
- <!-- Shorts can be decrease memory use, without decreasing performance. -->
- <exclude name="AvoidUsingShortType" />
<!-- Not relevant for ASM (no BigInteger). -->
<exclude name="BigIntegerInstantiation" />
<!-- Does not work, too many false positives. -->
=====================================
tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java
=====================================
@@ -58,6 +58,7 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
+import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
@@ -345,7 +346,7 @@ public final class Retrofitter {
}
}
if (moduleNames.size() != 1) {
- throw new IllegalArgumentException("Module name can't be infered from classes");
+ throw new IllegalArgumentException("Module name can't be inferred from classes");
}
ModuleVisitor moduleVisitor =
classWriter.visitModule(moduleNames.get(0).replace('/', '.'), Opcodes.ACC_OPEN, version);
@@ -443,6 +444,14 @@ public final class Retrofitter {
super.visit(Opcodes.V1_5, access, name, signature, superName, interfaces);
}
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ if (descriptor.equals("Ljava/lang/FunctionalInterface;")) {
+ return null;
+ }
+ return super.visitAnnotation(descriptor, visible);
+ }
+
@Override
public void visitNestHost(final String nestHost) {
// Remove the NestHost attribute.
@@ -453,6 +462,20 @@ public final class Retrofitter {
// Remove the NestMembers attribute.
}
+ private AnnotationVisitor removeDeprecatedForRemoval(final AnnotationVisitor av) {
+ // We use @Deprecated(forRemoval = false) instead of a plain @Deprecated
+ // but forRemoval was introduced in Java 9, so we need to remove it
+ return new AnnotationVisitor(api, av) {
+ @Override
+ public void visit(final String name, final Object value) {
+ if (name.equals("forRemoval")) {
+ return;
+ }
+ super.visit(name, value);
+ }
+ };
+ }
+
@Override
public FieldVisitor visitField(
final int access,
@@ -461,7 +484,17 @@ public final class Retrofitter {
final String signature,
final Object value) {
addPackageReferences(Type.getType(descriptor), /* export= */ false);
- return super.visitField(access, name, descriptor, signature, value);
+ FieldVisitor fv = super.visitField(access, name, descriptor, signature, value);
+ return new FieldVisitor(api, fv) {
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(descriptor, visible);
+ if (descriptor.equals("Ljava/lang/Deprecated;")) {
+ return removeDeprecatedForRemoval(av);
+ }
+ return av;
+ }
+ };
}
@Override
@@ -475,6 +508,15 @@ public final class Retrofitter {
return new MethodVisitor(
api, super.visitMethod(access, name, descriptor, signature, exceptions)) {
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(descriptor, visible);
+ if (descriptor.equals("Ljava/lang/Deprecated;")) {
+ return removeDeprecatedForRemoval(av);
+ }
+ return av;
+ }
+
@Override
public void visitParameter(final String name, final int access) {
// Javac 21 generates a Parameter attribute for the synthetic/mandated parameters.
@@ -648,9 +690,6 @@ public final class Retrofitter {
/** The internal name of the visited class. */
String className;
- /** The name and descriptor of the currently visited method. */
- String currentMethodName;
-
public ClassVerifier() {
// Make sure use we don't use Java 9 or higher classfile features.
// We also want to make sure we don't use Java 6, 7 or 8 classfile
@@ -673,6 +712,49 @@ public final class Retrofitter {
className = name;
}
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ var av = super.visitAnnotation(descriptor, visible);
+ if (descriptor.equals("Ljava/lang/FunctionalInterface;")) {
+ throw new IllegalArgumentException(
+ format("ERROR: @FunctionalInterface in %s is not available in JDK 1.5", className));
+ }
+ return av;
+ }
+
+ private AnnotationVisitor deprecatedAnnotationVisitor(
+ final String descriptor, final AnnotationVisitor av, final String member) {
+ if (descriptor.equals("Ljava/lang/Deprecated;")) {
+ return new AnnotationVisitor(Opcodes.ASM4, av) {
+ @Override
+ public void visit(final String name, final Object value) {
+ throw new IllegalArgumentException(
+ format(
+ "ERROR: @Deprecated name %s on %s %s is not available in JDK 1.5",
+ name, member, className));
+ }
+ };
+ }
+ return av;
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ var fv = super.visitField(access, name, descriptor, signature, value);
+ return new FieldVisitor(Opcodes.ASM4, fv) {
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ var av = super.visitAnnotation(descriptor, visible);
+ return deprecatedAnnotationVisitor(descriptor, av, name);
+ }
+ };
+ }
+
@Override
public MethodVisitor visitMethod(
final int access,
@@ -680,14 +762,28 @@ public final class Retrofitter {
final String descriptor,
final String signature,
final String[] exceptions) {
- currentMethodName = name + descriptor;
+ String methodName = name + descriptor;
MethodVisitor methodVisitor =
super.visitMethod(access, name, descriptor, signature, exceptions);
return new MethodVisitor(Opcodes.ASM4, methodVisitor) {
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ var av = super.visitAnnotation(descriptor, visible);
+ return deprecatedAnnotationVisitor(descriptor, av, methodName);
+ }
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ throw new IllegalArgumentException(
+ format(
+ "ERROR: parameter %s in %s %s is not available in JDK 1.5",
+ name, className, methodName));
+ }
+
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String descriptor) {
- check(owner, name);
+ check(owner, name, methodName);
}
@Override
@@ -697,7 +793,7 @@ public final class Retrofitter {
final String name,
final String descriptor,
final boolean isInterface) {
- check(owner, name + descriptor);
+ check(owner, name + descriptor, methodName);
}
@Override
@@ -708,13 +804,13 @@ public final class Retrofitter {
throw new IllegalArgumentException(
format(
"ERROR: ldc with a MethodType called in %s %s is not available in JDK 1.5",
- className, currentMethodName));
+ className, methodName));
}
} else if (value instanceof Handle) {
throw new IllegalArgumentException(
format(
"ERROR: ldc with a MethodHandle called in %s %s is not available in JDK 1.5",
- className, currentMethodName));
+ className, methodName));
}
}
@@ -727,7 +823,7 @@ public final class Retrofitter {
throw new IllegalArgumentException(
format(
"ERROR: invokedynamic called in %s %s is not available in JDK 1.5",
- className, currentMethodName));
+ className, methodName));
}
};
}
@@ -737,8 +833,9 @@ public final class Retrofitter {
*
* @param owner A class name.
* @param member A field name or a method name and descriptor.
+ * @param methodName The name and descriptor of the currently visited method.
*/
- private void check(final String owner, final String member) {
+ private void check(final String owner, final String member, final String methodName) {
if (owner.startsWith("java/")) {
String currentOwner = owner;
while (currentOwner != null) {
@@ -750,7 +847,7 @@ public final class Retrofitter {
throw new IllegalArgumentException(
format(
"ERROR: %s %s called in %s %s is not defined in the JDK 1.5 API",
- owner, member, className, currentMethodName));
+ owner, member, className, methodName));
}
}
}
View it on GitLab: https://salsa.debian.org/java-team/asm/-/compare/c8bd3e4e3e504a5c090ae93065b950992128b551...edbc7f58f5c873aa8961b74c6c16afb9c112573a
--
View it on GitLab: https://salsa.debian.org/java-team/asm/-/compare/c8bd3e4e3e504a5c090ae93065b950992128b551...edbc7f58f5c873aa8961b74c6c16afb9c112573a
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20260918/e9989a2b/attachment.htm>
More information about the pkg-java-commits
mailing list