diff options
author | Eric Bruneton <ebruneton@free.fr> | 2023-09-17 14:11:12 +0200 |
---|---|---|
committer | Eric Bruneton <ebruneton@free.fr> | 2023-09-23 19:05:53 +0200 |
commit | 5d00fe4ea47b17f3d2e981a18ee447d9b1d32de1 (patch) | |
tree | 3b23315074a8c24eefb101e247c5c336f70d0b88 | |
parent | c890eac5963700541703445d06c62c18e044d671 (diff) | |
download | ow2-asm-5d00fe4ea47b17f3d2e981a18ee447d9b1d32de1.tar.gz |
Add a getArgumentCount() method in Type.
5 files changed, 76 insertions, 23 deletions
diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java index 2776fb30..ac3600c7 100644 --- a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java @@ -672,7 +672,7 @@ public class Frame<V extends Value> { final AbstractInsnNode insn, final String methodDescriptor, final Interpreter<V> interpreter) throws AnalyzerException { ArrayList<V> valueList = new ArrayList<>(); - for (int i = Type.getArgumentTypes(methodDescriptor).length; i > 0; --i) { + for (int i = Type.getArgumentCount(methodDescriptor); i > 0; --i) { valueList.add(0, pop()); } if (insn.getOpcode() != Opcodes.INVOKESTATIC && insn.getOpcode() != Opcodes.INVOKEDYNAMIC) { diff --git a/asm-tree/src/main/java/org/objectweb/asm/tree/MethodNode.java b/asm-tree/src/main/java/org/objectweb/asm/tree/MethodNode.java index 23e3e4c5..8b529a52 100644 --- a/asm-tree/src/main/java/org/objectweb/asm/tree/MethodNode.java +++ b/asm-tree/src/main/java/org/objectweb/asm/tree/MethodNode.java @@ -294,14 +294,14 @@ public class MethodNode extends MethodVisitor { AnnotationNode annotation = new AnnotationNode(descriptor); if (visible) { if (visibleParameterAnnotations == null) { - int params = Type.getArgumentTypes(desc).length; + int params = Type.getArgumentCount(desc); visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; } visibleParameterAnnotations[parameter] = Util.add(visibleParameterAnnotations[parameter], annotation); } else { if (invisibleParameterAnnotations == null) { - int params = Type.getArgumentTypes(desc).length; + int params = Type.getArgumentCount(desc); invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; } invisibleParameterAnnotations[parameter] = diff --git a/asm/src/main/java/org/objectweb/asm/MethodWriter.java b/asm/src/main/java/org/objectweb/asm/MethodWriter.java index a1e075b6..8cdeec47 100644 --- a/asm/src/main/java/org/objectweb/asm/MethodWriter.java +++ b/asm/src/main/java/org/objectweb/asm/MethodWriter.java @@ -694,7 +694,7 @@ final class MethodWriter extends MethodVisitor { if (visible) { if (lastRuntimeVisibleParameterAnnotations == null) { lastRuntimeVisibleParameterAnnotations = - new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + new AnnotationWriter[Type.getArgumentCount(descriptor)]; } return lastRuntimeVisibleParameterAnnotations[parameter] = AnnotationWriter.create( @@ -702,7 +702,7 @@ final class MethodWriter extends MethodVisitor { } else { if (lastRuntimeInvisibleParameterAnnotations == null) { lastRuntimeInvisibleParameterAnnotations = - new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + new AnnotationWriter[Type.getArgumentCount(descriptor)]; } return lastRuntimeInvisibleParameterAnnotations[parameter] = AnnotationWriter.create( diff --git a/asm/src/main/java/org/objectweb/asm/Type.java b/asm/src/main/java/org/objectweb/asm/Type.java index 85aab7ea..c60a4233 100644 --- a/asm/src/main/java/org/objectweb/asm/Type.java +++ b/asm/src/main/java/org/objectweb/asm/Type.java @@ -295,26 +295,12 @@ public final class Type { */ public static Type[] getArgumentTypes(final String methodDescriptor) { // First step: compute the number of argument types in methodDescriptor. - int numArgumentTypes = 0; - // Skip the first character, which is always a '('. - int currentOffset = 1; - // Parse the argument types, one at a each loop iteration. - while (methodDescriptor.charAt(currentOffset) != ')') { - while (methodDescriptor.charAt(currentOffset) == '[') { - currentOffset++; - } - if (methodDescriptor.charAt(currentOffset++) == 'L') { - // Skip the argument descriptor content. - int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset); - currentOffset = Math.max(currentOffset, semiColumnOffset + 1); - } - ++numArgumentTypes; - } + int numArgumentTypes = getArgumentCount(methodDescriptor); // Second step: create a Type instance for each argument type. Type[] argumentTypes = new Type[numArgumentTypes]; // Skip the first character, which is always a '('. - currentOffset = 1; + int currentOffset = 1; // Parse and create the argument types, one at each loop iteration. int currentArgumentTypeIndex = 0; while (methodDescriptor.charAt(currentOffset) != ')') { @@ -703,13 +689,51 @@ public final class Type { } /** + * Returns the number of arguments of this method type. This method should only be used for method + * types. + * + * @return the number of arguments of this method type. Each argument counts for 1, even long and + * double ones. The implicit @literal{this} argument is not counted. + */ + public int getArgumentCount() { + return getArgumentCount(getDescriptor()); + } + + /** + * Returns the number of arguments in the given method descriptor. + * + * @param methodDescriptor a method descriptor. + * @return the number of arguments in the given method descriptor. Each argument counts for 1, + * even long and double ones. The implicit @literal{this} argument is not counted. + */ + public static int getArgumentCount(final String methodDescriptor) { + int argumentCount = 0; + // Skip the first character, which is always a '('. + int currentOffset = 1; + // Parse the argument types, one at a each loop iteration. + while (methodDescriptor.charAt(currentOffset) != ')') { + while (methodDescriptor.charAt(currentOffset) == '[') { + currentOffset++; + } + if (methodDescriptor.charAt(currentOffset++) == 'L') { + // Skip the argument descriptor content. + int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset); + currentOffset = Math.max(currentOffset, semiColumnOffset + 1); + } + ++argumentCount; + } + return argumentCount; + } + + /** * Returns the size of the arguments and of the return value of methods of this type. This method * should only be used for method types. * * @return the size of the arguments of the method (plus one for the implicit this argument), * argumentsSize, and the size of its return value, returnSize, packed into a single int i = * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code - * i >> 2}, and returnSize to {@code i & 0x03}). + * i >> 2}, and returnSize to {@code i & 0x03}). Long and double values have size 2, + * the others have size 1. */ public int getArgumentsAndReturnSizes() { return getArgumentsAndReturnSizes(getDescriptor()); @@ -722,7 +746,8 @@ public final class Type { * @return the size of the arguments of the method (plus one for the implicit this argument), * argumentsSize, and the size of its return value, returnSize, packed into a single int i = * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code - * i >> 2}, and returnSize to {@code i & 0x03}). + * i >> 2}, and returnSize to {@code i & 0x03}). Long and double values have size 2, + * the others have size 1. */ public static int getArgumentsAndReturnSizes(final String methodDescriptor) { int argumentsSize = 1; diff --git a/asm/src/test/java/org/objectweb/asm/TypeTest.java b/asm/src/test/java/org/objectweb/asm/TypeTest.java index bf52bcd2..ccefc808 100644 --- a/asm/src/test/java/org/objectweb/asm/TypeTest.java +++ b/asm/src/test/java/org/objectweb/asm/TypeTest.java @@ -249,6 +249,34 @@ class TypeTest implements Opcodes { } @Test + void testGetArgumentCountFromType() { + assertEquals( + 14, + Type.getMethodType("(IZBCSDFJLI;LV;Ljava/lang/Object;[I[LI;[[Ljava/lang/Object;)V") + .getArgumentCount()); + } + + @Test + void testGetArgumentCountFromDescriptor() { + assertEquals( + 14, Type.getArgumentCount("(IZBCSDFJLI;LV;Ljava/lang/Object;[I[LI;[[Ljava/lang/Object;)V")); + assertEquals(0, Type.getArgumentCount("()I")); + } + + @Test + void testGetArgumentsAndReturnSizeFromType() { + assertEquals( + 17 << 2, + Type.getMethodType("(IZBCSDFJLI;LV;Ljava/lang/Object;[I[LI;[[Ljava/lang/Object;)V") + .getArgumentsAndReturnSizes()); + assertEquals(1 << 2 | 1, Type.getMethodType("()I").getArgumentsAndReturnSizes()); + assertEquals(1 << 2 | 1, Type.getMethodType("()F").getArgumentsAndReturnSizes()); + assertEquals(1 << 2 | 2, Type.getMethodType("()J").getArgumentsAndReturnSizes()); + assertEquals(1 << 2 | 2, Type.getMethodType("()D").getArgumentsAndReturnSizes()); + assertEquals(1 << 2 | 1, Type.getMethodType("()LD;").getArgumentsAndReturnSizes()); + } + + @Test void testGetArgumentsAndReturnSizeFromDescriptor() { assertEquals( 17 << 2, |