You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2018/11/29 00:34:00 UTC
[13/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7
for Java 9+ support
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
old mode 100644
new mode 100755
index b71c186..8ddee8d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
@@ -1,41 +1,38 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
package org.apache.tapestry5.internal.plastic.asm.util;
-import java.io.FileInputStream;
-import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-
import org.apache.tapestry5.internal.plastic.asm.Attribute;
-import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
@@ -44,1397 +41,1534 @@ import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link Printer} that prints the ASM code to generate the classes if visits.
- *
+ *
* @author Eric Bruneton
*/
+// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public class ASMifier extends Printer {
- /**
- * The name of the visitor variable in the produced code.
- */
- protected final String name;
-
- /**
- * Identifier of the annotation visitor variable in the produced code.
- */
- protected final int id;
-
- /**
- * The label names. This map associates String values to Label keys. It is
- * used only in ASMifierMethodVisitor.
- */
- protected Map<Label, String> labelNames;
-
- /**
- * Pseudo access flag used to distinguish class access flags.
- */
- private static final int ACCESS_CLASS = 262144;
-
- /**
- * Pseudo access flag used to distinguish field access flags.
- */
- private static final int ACCESS_FIELD = 524288;
-
- /**
- * Pseudo access flag used to distinguish inner class flags.
- */
- private static final int ACCESS_INNER = 1048576;
-
- /**
- * Pseudo access flag used to distinguish module requires/exports flags.
- */
- private static final int ACCESS_MODULE = 2097152;
-
- /**
- * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #ASMifier(int, String, int)} version.
- *
- * @throws IllegalStateException
- * If a subclass calls this constructor.
- */
- public ASMifier() {
- this(Opcodes.ASM6, "cw", 0);
- if (getClass() != ASMifier.class) {
- throw new IllegalStateException();
- }
- }
-
- /**
- * Constructs a new {@link ASMifier}.
- *
- * @param api
- * the ASM API version implemented by this class. Must be one of
- * {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param name
- * the name of the visitor variable in the produced code.
- * @param id
- * identifier of the annotation visitor variable in the produced
- * code.
- */
- protected ASMifier(final int api, final String name, final int id) {
- super(api);
- this.name = name;
- this.id = id;
- }
-
- /**
- * Prints the ASM source code to generate the given class to the standard
- * output.
- * <p>
- * Usage: ASMifier [-debug] <binary class name or class file name>
- *
- * @param args
- * the command line arguments.
- *
- * @throws Exception
- * if the class cannot be found, or if an IO exception occurs.
- */
- public static void main(final String[] args) throws Exception {
- int i = 0;
- int flags = ClassReader.SKIP_DEBUG;
-
- boolean ok = true;
- if (args.length < 1 || args.length > 2) {
- ok = false;
- }
- if (ok && "-debug".equals(args[0])) {
- i = 1;
- flags = 0;
- if (args.length != 2) {
- ok = false;
- }
- }
- if (!ok) {
- System.err
- .println("Prints the ASM code to generate the given class.");
- System.err.println("Usage: ASMifier [-debug] "
- + "<fully qualified class name or class file name>");
- return;
- }
- ClassReader cr;
- if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
- || args[i].indexOf('/') > -1) {
- cr = new ClassReader(new FileInputStream(args[i]));
+ /** A pseudo access flag used to distinguish class access flags. */
+ private static final int ACCESS_CLASS = 0x40000;
+
+ /** A pseudo access flag used to distinguish field access flags. */
+ private static final int ACCESS_FIELD = 0x80000;
+
+ /** A pseudo access flag used to distinguish inner class flags. */
+ private static final int ACCESS_INNER = 0x100000;
+
+ /** A pseudo access flag used to distinguish module requires / exports flags. */
+ private static final int ACCESS_MODULE = 0x200000;
+
+ private static final String ANNOTATION_VISITOR = "annotationVisitor";
+ private static final String ANNOTATION_VISITOR0 = "annotationVisitor0 = ";
+ private static final String NEW_OBJECT_ARRAY = ", new Object[] {";
+ private static final String END_ARRAY = " });\n";
+ private static final String END_PARAMETERS = ");\n\n";
+ private static final String VISIT_END = ".visitEnd();\n";
+
+ private static final Map<Integer, String> CLASS_VERSIONS;
+
+ static {
+ HashMap<Integer, String> classVersions = new HashMap<Integer, String>();
+ classVersions.put(Opcodes.V1_1, "V1_1");
+ classVersions.put(Opcodes.V1_2, "V1_2");
+ classVersions.put(Opcodes.V1_3, "V1_3");
+ classVersions.put(Opcodes.V1_4, "V1_4");
+ classVersions.put(Opcodes.V1_5, "V1_5");
+ classVersions.put(Opcodes.V1_6, "V1_6");
+ classVersions.put(Opcodes.V1_7, "V1_7");
+ classVersions.put(Opcodes.V1_8, "V1_8");
+ classVersions.put(Opcodes.V9, "V9");
+ classVersions.put(Opcodes.V10, "V10");
+ classVersions.put(Opcodes.V11, "V11");
+ classVersions.put(Opcodes.V12, "V12");
+ CLASS_VERSIONS = Collections.unmodifiableMap(classVersions);
+ }
+
+ /** The name of the visitor variable in the produced code. */
+ protected final String name;
+
+ /** The identifier of the annotation visitor variable in the produced code. */
+ protected final int id;
+
+ /** The name of the Label variables in the produced code. */
+ protected Map<Label, String> labelNames;
+
+ /**
+ * Constructs a new {@link ASMifier}. <i>Subclasses must not use this constructor</i>. Instead,
+ * they must use the {@link #ASMifier(int, String, int)} version.
+ *
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public ASMifier() {
+ this(Opcodes.ASM7, "classWriter", 0);
+ if (getClass() != ASMifier.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link ASMifier}.
+ *
+ * @param api the ASM API version implemented by this class. Must be one of {@link Opcodes#ASM4},
+ * {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param visitorVariableName the name of the visitor variable in the produced code.
+ * @param annotationVisitorId identifier of the annotation visitor variable in the produced code.
+ */
+ protected ASMifier(
+ final int api, final String visitorVariableName, final int annotationVisitorId) {
+ super(api);
+ this.name = visitorVariableName;
+ this.id = annotationVisitorId;
+ }
+
+ /**
+ * Prints the ASM source code to generate the given class to the standard output.
+ *
+ * <p>Usage: ASMifier [-debug] <binary class name or class file name>
+ *
+ * @param args the command line arguments.
+ * @throws IOException if the class cannot be found, or if an IOException occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ String usage =
+ "Prints the ASM code to generate the given class.\n"
+ + "Usage: ASMifier [-debug] <fully qualified class name or class file name>";
+ main(usage, new ASMifier(), args);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Classes
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ String simpleName;
+ if (name == null) {
+ simpleName = "module-info";
+ } else {
+ int lastSlashIndex = name.lastIndexOf('/');
+ if (lastSlashIndex == -1) {
+ simpleName = name;
+ } else {
+ text.add("package asm." + name.substring(0, lastSlashIndex).replace('/', '.') + ";\n");
+ simpleName = name.substring(lastSlashIndex + 1).replace('-', '_');
+ }
+ }
+ text.add("import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Attribute;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ClassReader;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ClassWriter;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Handle;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Label;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Opcodes;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.Type;\n");
+ text.add("import org.apache.tapestry5.internal.plastic.asm.TypePath;\n");
+ text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+ text.add("public static byte[] dump () throws Exception {\n\n");
+ text.add("ClassWriter classWriter = new ClassWriter(0);\n");
+ text.add("FieldVisitor fieldVisitor;\n");
+ text.add("MethodVisitor methodVisitor;\n");
+ text.add("AnnotationVisitor annotationVisitor0;\n\n");
+
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visit(");
+ String versionString = CLASS_VERSIONS.get(version);
+ if (versionString != null) {
+ stringBuilder.append(versionString);
+ } else {
+ stringBuilder.append(version);
+ }
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_CLASS);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendConstant(superName);
+ stringBuilder.append(", ");
+ if (interfaces != null && interfaces.length > 0) {
+ stringBuilder.append("new String[] {");
+ for (int i = 0; i < interfaces.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(interfaces[i]);
+ }
+ stringBuilder.append(" }");
+ } else {
+ stringBuilder.append("null");
+ }
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitSource(");
+ appendConstant(file);
+ stringBuilder.append(", ");
+ appendConstant(debug);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitModule(final String name, final int flags, final String version) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("ModuleVisitor moduleVisitor = classWriter.visitModule(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendAccessFlags(flags | ACCESS_MODULE);
+ stringBuilder.append(", ");
+ appendConstant(version);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("moduleVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitNestHost(final String nestHost) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitNestHost(");
+ appendConstant(nestHost);
+ stringBuilder.append(");\n\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitOuterClass(");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitClassAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitClassTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitNestMember(final String nestMember) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitNestMember(");
+ appendConstant(nestMember);
+ stringBuilder.append(");\n\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name, final String outerName, final String innerName, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("classWriter.visitInnerClass(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(outerName);
+ stringBuilder.append(", ");
+ appendConstant(innerName);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_INNER);
+ stringBuilder.append(END_PARAMETERS);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitField(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder.append("fieldVisitor = classWriter.visitField(");
+ appendAccessFlags(access | ACCESS_FIELD);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("fieldVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder.append("methodVisitor = classWriter.visitMethod(");
+ appendAccessFlags(access);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ if (exceptions != null && exceptions.length > 0) {
+ stringBuilder.append("new String[] {");
+ for (int i = 0; i < exceptions.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(exceptions[i]);
+ }
+ stringBuilder.append(" }");
+ } else {
+ stringBuilder.append("null");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier("methodVisitor", 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("classWriter.visitEnd();\n\n");
+ text.add("return classWriter.toByteArray();\n");
+ text.add("}\n");
+ text.add("}\n");
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Modules
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitMainClass(");
+ appendConstant(mainClass);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitPackage(");
+ appendConstant(packaze);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitRequire(");
+ appendConstant(module);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ stringBuilder.append(", ");
+ appendConstant(version);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitExport(");
+ appendConstant(packaze);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(modules[i]);
+ }
+ stringBuilder.append(" }");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitOpen(");
+ appendConstant(packaze);
+ stringBuilder.append(", ");
+ appendAccessFlags(access | ACCESS_MODULE);
+ if (modules != null && modules.length > 0) {
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < modules.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(modules[i]);
+ }
+ stringBuilder.append(" }");
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitUse(");
+ appendConstant(service);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("moduleVisitor.visitProvide(");
+ appendConstant(service);
+ stringBuilder.append(", new String[] {");
+ for (int i = 0; i < providers.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendConstant(providers[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitModuleEnd() {
+ text.add("moduleVisitor.visitEnd();\n");
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Annotations
+ // -----------------------------------------------------------------------------------------------
+
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ @Override
+ public void visit(final String name, final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(".visit(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitEnum(final String name, final String descriptor, final String value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(".visitEnum(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotation(final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append("AnnotationVisitor annotationVisitor")
+ .append(id + 1)
+ .append(" = annotationVisitor");
+ stringBuilder.append(id).append(".visitAnnotation(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, id + 1);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitArray(final String name) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("{\n");
+ stringBuilder
+ .append("AnnotationVisitor annotationVisitor")
+ .append(id + 1)
+ .append(" = annotationVisitor");
+ stringBuilder.append(id).append(".visitArray(");
+ appendConstant(name);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, id + 1);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(ANNOTATION_VISITOR).append(id).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Fields
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitFieldAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitFieldTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Methods
+ // -----------------------------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(final String parameterName, final int access) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitParameter(");
+ appendString(stringBuilder, parameterName);
+ stringBuilder.append(", ");
+ appendAccessFlags(access);
+ text.add(stringBuilder.append(");\n").toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotationDefault() {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitAnnotationDefault();\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public ASMifier visitMethodAnnotation(final String descriptor, final boolean visible) {
+ return visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitMethodTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public ASMifier visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitAnnotableParameterCount(")
+ .append(parameterCount)
+ .append(", ")
+ .append(visible)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ return this;
+ }
+
+ @Override
+ public ASMifier visitParameterAnnotation(
+ final int parameter, final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitParameterAnnotation(")
+ .append(parameter)
+ .append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attribute) {
+ visitAttribute(attribute);
+ }
+
+ @Override
+ public void visitCode() {
+ text.add(name + ".visitCode();\n");
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int numLocal,
+ final Object[] local,
+ final int numStack,
+ final Object[] stack) {
+ stringBuilder.setLength(0);
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ declareFrameTypes(numLocal, local);
+ declareFrameTypes(numStack, stack);
+ if (type == Opcodes.F_NEW) {
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_NEW, ");
} else {
- cr = new ClassReader(args[i]);
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_FULL, ");
}
- cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
- System.out)), flags);
- }
-
- // ------------------------------------------------------------------------
- // Classes
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName,
- final String[] interfaces) {
- String simpleName;
- if (name == null) {
- simpleName = "module-info";
+ stringBuilder.append(numLocal).append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append("}, ").append(numStack).append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numStack, stack);
+ stringBuilder.append('}');
+ break;
+ case Opcodes.F_APPEND:
+ declareFrameTypes(numLocal, local);
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_APPEND,")
+ .append(numLocal)
+ .append(NEW_OBJECT_ARRAY);
+ appendFrameTypes(numLocal, local);
+ stringBuilder.append("}, 0, null");
+ break;
+ case Opcodes.F_CHOP:
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_CHOP,")
+ .append(numLocal)
+ .append(", null, 0, null");
+ break;
+ case Opcodes.F_SAME:
+ stringBuilder.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ break;
+ case Opcodes.F_SAME1:
+ declareFrameTypes(1, stack);
+ stringBuilder
+ .append(name)
+ .append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+ appendFrameTypes(1, stack);
+ stringBuilder.append('}');
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitInsn(").append(OPCODES[opcode]).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitIntInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer.toString(operand))
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitVarInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(var)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(type);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitFieldInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ /**
+ * Deprecated.
+ *
+ * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+ */
+ @Deprecated
+ @Override
+ public void visitMethodInsn(
+ final int opcode, final String owner, final String name, final String descriptor) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+
+ private void doVisitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(this.name)
+ .append(".visitMethodInsn(")
+ .append(OPCODES[opcode])
+ .append(", ");
+ appendConstant(owner);
+ stringBuilder.append(", ");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ stringBuilder.append(isInterface ? "true" : "false");
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitInvokeDynamicInsn(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(bootstrapMethodHandle);
+ stringBuilder.append(", new Object[]{");
+ for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
+ appendConstant(bootstrapMethodArguments[i]);
+ if (i != bootstrapMethodArguments.length - 1) {
+ stringBuilder.append(", ");
+ }
+ }
+ stringBuilder.append("});\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ stringBuilder.setLength(0);
+ declareLabel(label);
+ stringBuilder.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]).append(", ");
+ appendLabel(label);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ stringBuilder.setLength(0);
+ declareLabel(label);
+ stringBuilder.append(name).append(".visitLabel(");
+ appendLabel(label);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitLdcInsn(");
+ appendConstant(value);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitIincInsn(")
+ .append(var)
+ .append(", ")
+ .append(increment)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min, final int max, final Label dflt, final Label... labels) {
+ stringBuilder.setLength(0);
+ for (Label label : labels) {
+ declareLabel(label);
+ }
+ declareLabel(dflt);
+
+ stringBuilder
+ .append(name)
+ .append(".visitTableSwitchInsn(")
+ .append(min)
+ .append(", ")
+ .append(max)
+ .append(", ");
+ appendLabel(dflt);
+ stringBuilder.append(", new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ stringBuilder.setLength(0);
+ for (Label label : labels) {
+ declareLabel(label);
+ }
+ declareLabel(dflt);
+
+ stringBuilder.append(name).append(".visitLookupSwitchInsn(");
+ appendLabel(dflt);
+ stringBuilder.append(", new int[] {");
+ for (int i = 0; i < keys.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ").append(keys[i]);
+ }
+ stringBuilder.append(" }, new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ stringBuilder.append(END_ARRAY);
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitMultiANewArrayInsn(");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(numDimensions).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitInsnAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start, final Label end, final Label handler, final String type) {
+ stringBuilder.setLength(0);
+ declareLabel(start);
+ declareLabel(end);
+ declareLabel(handler);
+ stringBuilder.append(name).append(".visitTryCatchBlock(");
+ appendLabel(start);
+ stringBuilder.append(", ");
+ appendLabel(end);
+ stringBuilder.append(", ");
+ appendLabel(handler);
+ stringBuilder.append(", ");
+ appendConstant(type);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public ASMifier visitTryCatchAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitTryCatchAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String descriptor,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(this.name).append(".visitLocalVariable(");
+ appendConstant(name);
+ stringBuilder.append(", ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ");
+ appendConstant(signature);
+ stringBuilder.append(", ");
+ appendLabel(start);
+ stringBuilder.append(", ");
+ appendLabel(end);
+ stringBuilder.append(", ").append(index).append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public Printer visitLocalVariableAnnotation(
+ final int typeRef,
+ final TypePath typePath,
+ final Label[] start,
+ final Label[] end,
+ final int[] index,
+ final String descriptor,
+ final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitLocalVariableAnnotation(")
+ .append(typeRef);
+ if (typePath == null) {
+ stringBuilder.append(", null, ");
+ } else {
+ stringBuilder.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+ }
+ stringBuilder.append("new Label[] {");
+ for (int i = 0; i < start.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(start[i]);
+ }
+ stringBuilder.append(" }, new Label[] {");
+ for (int i = 0; i < end.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ");
+ appendLabel(end[i]);
+ }
+ stringBuilder.append(" }, new int[] {");
+ for (int i = 0; i < index.length; ++i) {
+ stringBuilder.append(i == 0 ? " " : ", ").append(index[i]);
+ }
+ stringBuilder.append(" }, ");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(".visitLineNumber(").append(line).append(", ");
+ appendLabel(start);
+ stringBuilder.append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append(name)
+ .append(".visitMaxs(")
+ .append(maxStack)
+ .append(", ")
+ .append(maxLocals)
+ .append(");\n");
+ text.add(stringBuilder.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ stringBuilder.setLength(0);
+ stringBuilder.append(name).append(VISIT_END);
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Common methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Visits a class, field or method annotation.
+ *
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ // DontCheck(OverloadMethodsDeclarationOrder): overloads are semantically different.
+ public ASMifier visitAnnotation(final String descriptor, final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".visitAnnotation(");
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ /**
+ * Visits a class, field or method type annotation.
+ *
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#FIELD}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ public ASMifier visitTypeAnnotation(
+ final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath, descriptor, visible);
+ }
+
+ /**
+ * Visits a class, field, method, instruction or try catch block type annotation.
+ *
+ * @param method the name of the visit method for this type of annotation.
+ * @param typeRef a reference to the annotated type. The sort of this type reference must be
+ * {@link org.apache.tapestry5.internal.plastic.asm.TypeReference#FIELD}. See {@link org.apache.tapestry5.internal.plastic.asm.TypeReference}.
+ * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
+ * static inner type within 'typeRef'. May be {@literal null} if the annotation targets
+ * 'typeRef' as a whole.
+ * @param descriptor the class descriptor of the annotation class.
+ * @param visible {@literal true} if the annotation is visible at runtime.
+ * @return a new {@link ASMifier} to visit the annotation values.
+ */
+ public ASMifier visitTypeAnnotation(
+ final String method,
+ final int typeRef,
+ final TypePath typePath,
+ final String descriptor,
+ final boolean visible) {
+ stringBuilder.setLength(0);
+ stringBuilder
+ .append("{\n")
+ .append(ANNOTATION_VISITOR0)
+ .append(name)
+ .append(".")
+ .append(method)
+ .append("(")
+ .append(typeRef);
+ if (typePath == null) {
+ stringBuilder.append(", null, ");
+ } else {
+ stringBuilder.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+ }
+ appendConstant(descriptor);
+ stringBuilder.append(", ").append(visible).append(");\n");
+ text.add(stringBuilder.toString());
+ ASMifier asmifier = createASMifier(ANNOTATION_VISITOR, 0);
+ text.add(asmifier.getText());
+ text.add("}\n");
+ return asmifier;
+ }
+
+ /**
+ * Visit a class, field or method attribute.
+ *
+ * @param attribute an attribute.
+ */
+ public void visitAttribute(final Attribute attribute) {
+ stringBuilder.setLength(0);
+ stringBuilder.append("// ATTRIBUTE ").append(attribute.type).append('\n');
+ if (attribute instanceof ASMifiable) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ stringBuilder.append("{\n");
+ StringBuffer stringBuffer = new StringBuffer();
+ ((ASMifiable) attribute).asmify(stringBuffer, "attribute", labelNames);
+ stringBuilder.append(stringBuffer.toString());
+ stringBuilder.append(name).append(".visitAttribute(attribute);\n");
+ stringBuilder.append("}\n");
+ }
+ text.add(stringBuilder.toString());
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // Utility methods
+ // -----------------------------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ASMifier}.
+ *
+ * @param visitorVariableName the name of the visitor variable in the produced code.
+ * @param annotationVisitorId identifier of the annotation visitor variable in the produced code.
+ * @return a new {@link ASMifier}.
+ */
+ // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
+ protected ASMifier createASMifier(
+ final String visitorVariableName, final int annotationVisitorId) {
+ return new ASMifier(Opcodes.ASM7, visitorVariableName, annotationVisitorId);
+ }
+
+ /**
+ * Appends a string representation of the given access flags to {@link #stringBuilder}.
+ *
+ * @param accessFlags some access flags.
+ */
+ private void appendAccessFlags(final int accessFlags) {
+ boolean isEmpty = true;
+ if ((accessFlags & Opcodes.ACC_PUBLIC) != 0) {
+ stringBuilder.append("ACC_PUBLIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_PRIVATE) != 0) {
+ stringBuilder.append("ACC_PRIVATE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_PROTECTED) != 0) {
+ stringBuilder.append("ACC_PROTECTED");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_FINAL) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_FINAL");
+ } else {
+ stringBuilder.append("ACC_TRANSITIVE");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_STATIC) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_STATIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_SUPER | Opcodes.ACC_TRANSITIVE))
+ != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_CLASS) == 0) {
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_SYNCHRONIZED");
} else {
- int n = name.lastIndexOf('/');
- if (n == -1) {
- simpleName = name;
- } else {
- text.add("package asm." + name.substring(0, n).replace('/', '.')
- + ";\n");
- simpleName = name.substring(n + 1).replace('-', '_');
- }
+ stringBuilder.append("ACC_TRANSITIVE");
}
- text.add("import java.util.*;\n");
- text.add("import org.apache.tapestry5.internal.plastic.asm.*;\n");
- text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
- text.add("public static byte[] dump () throws Exception {\n\n");
- text.add("ClassWriter cw = new ClassWriter(0);\n");
- text.add("FieldVisitor fv;\n");
- text.add("MethodVisitor mv;\n");
- text.add("AnnotationVisitor av0;\n\n");
-
- buf.setLength(0);
- buf.append("cw.visit(");
- switch (version) {
- case Opcodes.V1_1:
- buf.append("V1_1");
- break;
- case Opcodes.V1_2:
- buf.append("V1_2");
- break;
- case Opcodes.V1_3:
- buf.append("V1_3");
- break;
- case Opcodes.V1_4:
- buf.append("V1_4");
- break;
- case Opcodes.V1_5:
- buf.append("V1_5");
- break;
- case Opcodes.V1_6:
- buf.append("V1_6");
- break;
- case Opcodes.V1_7:
- buf.append("V1_7");
- break;
- case Opcodes.V1_8:
- buf.append("V1_8");
- break;
- case Opcodes.V9:
- buf.append("V9");
- break;
- default:
- buf.append(version);
- break;
- }
- buf.append(", ");
- appendAccess(access | ACCESS_CLASS);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendConstant(superName);
- buf.append(", ");
- if (interfaces != null && interfaces.length > 0) {
- buf.append("new String[] {");
- for (int i = 0; i < interfaces.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(interfaces[i]);
- }
- buf.append(" }");
+ } else {
+ stringBuilder.append("ACC_SUPER");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_VOLATILE | Opcodes.ACC_BRIDGE | Opcodes.ACC_STATIC_PHASE))
+ != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_FIELD) == 0) {
+ if ((accessFlags & ACCESS_MODULE) == 0) {
+ stringBuilder.append("ACC_BRIDGE");
} else {
- buf.append("null");
+ stringBuilder.append("ACC_STATIC_PHASE");
}
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitSource(final String file, final String debug) {
- buf.setLength(0);
- buf.append("cw.visitSource(");
- appendConstant(file);
- buf.append(", ");
- appendConstant(debug);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public Printer visitModule(final String name, final int flags,
- final String version) {
- buf.setLength(0);
- buf.append("ModuleVisitor mdv = cw.visitModule(");
- appendConstant(name);
- buf.append(", ");
- appendAccess(flags | ACCESS_MODULE);
- buf.append(", ");
- appendConstant(version);
- buf.append(");\n\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("mdv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitOuterClass(final String owner, final String name,
- final String desc) {
- buf.setLength(0);
- buf.append("cw.visitOuterClass(");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitClassAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitClassTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitClassAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitInnerClass(final String name, final String outerName,
- final String innerName, final int access) {
- buf.setLength(0);
- buf.append("cw.visitInnerClass(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(outerName);
- buf.append(", ");
- appendConstant(innerName);
- buf.append(", ");
- appendAccess(access | ACCESS_INNER);
- buf.append(");\n\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitField(final int access, final String name,
- final String desc, final String signature, final Object value) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("fv = cw.visitField(");
- appendAccess(access | ACCESS_FIELD);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendConstant(value);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("fv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitMethod(final int access, final String name,
- final String desc, final String signature, final String[] exceptions) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("mv = cw.visitMethod(");
- appendAccess(access);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- if (exceptions != null && exceptions.length > 0) {
- buf.append("new String[] {");
- for (int i = 0; i < exceptions.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(exceptions[i]);
- }
- buf.append(" }");
- } else {
- buf.append("null");
+ } else {
+ stringBuilder.append("ACC_VOLATILE");
+ }
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_VARARGS) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD)) == 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_VARARGS");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_TRANSIENT) != 0 && (accessFlags & ACCESS_FIELD) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_TRANSIENT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_NATIVE) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD)) == 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_NATIVE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ENUM) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_FIELD | ACCESS_INNER)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ENUM");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ANNOTATION) != 0
+ && (accessFlags & (ACCESS_CLASS | ACCESS_INNER)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ANNOTATION");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_ABSTRACT) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_ABSTRACT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_INTERFACE) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_INTERFACE");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_STRICT) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_STRICT");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_SYNTHETIC");
+ isEmpty = false;
+ }
+ if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ stringBuilder.append("ACC_DEPRECATED");
+ isEmpty = false;
+ }
+ if ((accessFlags & (Opcodes.ACC_MANDATED | Opcodes.ACC_MODULE)) != 0) {
+ if (!isEmpty) {
+ stringBuilder.append(" | ");
+ }
+ if ((accessFlags & ACCESS_CLASS) == 0) {
+ stringBuilder.append("ACC_MANDATED");
+ } else {
+ stringBuilder.append("ACC_MODULE");
+ }
+ isEmpty = false;
+ }
+ if (isEmpty) {
+ stringBuilder.append('0');
+ }
+ }
+
+ /**
+ * Appends a string representation of the given constant to {@link #stringBuilder}.
+ *
+ * @param value a {@link String}, {@link Type}, {@link Handle}, {@link Byte}, {@link Short},
+ * {@link Character}, {@link Integer}, {@link Float}, {@link Long} or {@link Double} object,
+ * or an array of primitive values. May be {@literal null}.
+ */
+ protected void appendConstant(final Object value) {
+ if (value == null) {
+ stringBuilder.append("null");
+ } 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("\")");
+ } 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("\", \"");
+ stringBuilder.append(handle.getName()).append("\", \"");
+ stringBuilder.append(handle.getDesc()).append("\", ");
+ stringBuilder.append(handle.isInterface()).append(")");
+ } else if (value instanceof ConstantDynamic) {
+ stringBuilder.append("new ConstantDynamic(\"");
+ ConstantDynamic constantDynamic = (ConstantDynamic) value;
+ stringBuilder.append(constantDynamic.getName()).append("\", \"");
+ stringBuilder.append(constantDynamic.getDescriptor()).append("\", ");
+ appendConstant(constantDynamic.getBootstrapMethod());
+ stringBuilder.append(", new Object[] {");
+ int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
+ for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
+ appendConstant(constantDynamic.getBootstrapMethodArgument(i));
+ if (i != bootstrapMethodArgumentCount - 1) {
+ stringBuilder.append(", ");
}
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("mv", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitClassEnd() {
- text.add("cw.visitEnd();\n\n");
- text.add("return cw.toByteArray();\n");
- text.add("}\n");
- text.add("}\n");
- }
-
- // ------------------------------------------------------------------------
- // Module
- // ------------------------------------------------------------------------
-
- @Override
- public void visitMainClass(String mainClass) {
- buf.setLength(0);
- buf.append("mdv.visitMainClass(");
- appendConstant(buf, mainClass);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitPackage(String packaze) {
- buf.setLength(0);
- buf.append("mdv.visitPackage(");
- appendConstant(buf, packaze);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitRequire(String module, int access, String version) {
- buf.setLength(0);
- buf.append("mdv.visitRequire(");
- appendConstant(buf, module);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- buf.append(", ");
- appendConstant(buf, version);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- buf.setLength(0);
- buf.append("mdv.visitExport(");
- appendConstant(buf, packaze);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- if (modules != null && modules.length > 0) {
- buf.append(", new String[] {");
- for (int i = 0; i < modules.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(modules[i]);
- }
- buf.append(" }");
- }
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- buf.setLength(0);
- buf.append("mdv.visitOpen(");
- appendConstant(buf, packaze);
- buf.append(", ");
- appendAccess(access | ACCESS_MODULE);
- if (modules != null && modules.length > 0) {
- buf.append(", new String[] {");
- for (int i = 0; i < modules.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(modules[i]);
- }
- buf.append(" }");
- }
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitUse(String service) {
- buf.setLength(0);
- buf.append("mdv.visitUse(");
- appendConstant(buf, service);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitProvide(String service, String... providers) {
- buf.setLength(0);
- buf.append("mdv.visitProvide(");
- appendConstant(buf, service);
- buf.append(", new String[] {");
- for (int i = 0; i < providers.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendConstant(providers[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitModuleEnd() {
- text.add("mdv.visitEnd();\n");
- }
-
-
- // ------------------------------------------------------------------------
- // Annotations
- // ------------------------------------------------------------------------
-
- @Override
- public void visit(final String name, final Object value) {
- buf.setLength(0);
- buf.append("av").append(id).append(".visit(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, value);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitEnum(final String name, final String desc,
- final String value) {
- buf.setLength(0);
- buf.append("av").append(id).append(".visitEnum(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, desc);
- buf.append(", ");
- appendConstant(buf, value);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitAnnotation(final String name, final String desc) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
- buf.append(id).append(".visitAnnotation(");
- appendConstant(buf, name);
- buf.append(", ");
- appendConstant(buf, desc);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", id + 1);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitArray(final String name) {
- buf.setLength(0);
- buf.append("{\n");
- buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
- buf.append(id).append(".visitArray(");
- appendConstant(buf, name);
- buf.append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", id + 1);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitAnnotationEnd() {
- buf.setLength(0);
- buf.append("av").append(id).append(".visitEnd();\n");
- text.add(buf.toString());
- }
-
- // ------------------------------------------------------------------------
- // Fields
- // ------------------------------------------------------------------------
-
- @Override
- public ASMifier visitFieldAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitFieldTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public void visitFieldAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitFieldEnd() {
- buf.setLength(0);
- buf.append(name).append(".visitEnd();\n");
- text.add(buf.toString());
- }
-
- // ------------------------------------------------------------------------
- // Methods
- // ------------------------------------------------------------------------
-
- @Override
- public void visitParameter(String parameterName, int access) {
- buf.setLength(0);
- buf.append(name).append(".visitParameter(");
- appendString(buf, parameterName);
- buf.append(", ");
- appendAccess(access);
- text.add(buf.append(");\n").toString());
- }
-
- @Override
- public ASMifier visitAnnotationDefault() {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitAnnotationDefault();\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public ASMifier visitMethodAnnotation(final String desc,
- final boolean visible) {
- return visitAnnotation(desc, visible);
- }
-
- @Override
- public ASMifier visitMethodTypeAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation(typeRef, typePath, desc, visible);
- }
-
- @Override
- public ASMifier visitParameterAnnotation(final int parameter,
- final String desc, final boolean visible) {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitParameterAnnotation(").append(parameter)
- .append(", ");
- appendConstant(desc);
- buf.append(", ").append(visible).append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitMethodAttribute(final Attribute attr) {
- visitAttribute(attr);
- }
-
- @Override
- public void visitCode() {
- text.add(name + ".visitCode();\n");
- }
-
- @Override
- public void visitFrame(final int type, final int nLocal,
- final Object[] local, final int nStack, final Object[] stack) {
- buf.setLength(0);
- switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- declareFrameTypes(nLocal, local);
- declareFrameTypes(nStack, stack);
- if (type == Opcodes.F_NEW) {
- buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
- } else {
- buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
- }
- buf.append(nLocal).append(", new Object[] {");
- appendFrameTypes(nLocal, local);
- buf.append("}, ").append(nStack).append(", new Object[] {");
- appendFrameTypes(nStack, stack);
- buf.append('}');
+ }
+ stringBuilder.append("})");
+ } else if (value instanceof Byte) {
+ stringBuilder.append("new Byte((byte)").append(value).append(')');
+ } else if (value instanceof Boolean) {
+ stringBuilder.append(((Boolean) value).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE");
+ } else if (value instanceof Short) {
+ stringBuilder.append("new Short((short)").append(value).append(')');
+ } else if (value instanceof Character) {
+ stringBuilder
+ .append("new Character((char)")
+ .append((int) ((Character) value).charValue())
+ .append(')');
+ } else if (value instanceof Integer) {
+ stringBuilder.append("new Integer(").append(value).append(')');
+ } else if (value instanceof Float) {
+ stringBuilder.append("new Float(\"").append(value).append("\")");
+ } else if (value instanceof Long) {
+ stringBuilder.append("new Long(").append(value).append("L)");
+ } else if (value instanceof Double) {
+ stringBuilder.append("new Double(\"").append(value).append("\")");
+ } else if (value instanceof byte[]) {
+ byte[] byteArray = (byte[]) value;
+ stringBuilder.append("new byte[] {");
+ for (int i = 0; i < byteArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(byteArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof boolean[]) {
+ boolean[] booleanArray = (boolean[]) value;
+ stringBuilder.append("new boolean[] {");
+ for (int i = 0; i < booleanArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(booleanArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof short[]) {
+ short[] shortArray = (short[]) value;
+ stringBuilder.append("new short[] {");
+ for (int i = 0; i < shortArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append("(short)").append(shortArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof char[]) {
+ char[] charArray = (char[]) value;
+ stringBuilder.append("new char[] {");
+ for (int i = 0; i < charArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append("(char)").append((int) charArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof int[]) {
+ int[] intArray = (int[]) value;
+ stringBuilder.append("new int[] {");
+ for (int i = 0; i < intArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(intArray[i]);
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof long[]) {
+ long[] longArray = (long[]) value;
+ stringBuilder.append("new long[] {");
+ for (int i = 0; i < longArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(longArray[i]).append('L');
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof float[]) {
+ float[] floatArray = (float[]) value;
+ stringBuilder.append("new float[] {");
+ for (int i = 0; i < floatArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(floatArray[i]).append('f');
+ }
+ stringBuilder.append('}');
+ } else if (value instanceof double[]) {
+ double[] doubleArray = (double[]) value;
+ stringBuilder.append("new double[] {");
+ for (int i = 0; i < doubleArray.length; i++) {
+ stringBuilder.append(i == 0 ? "" : ",").append(doubleArray[i]).append('d');
+ }
+ stringBuilder.append('}');
+ }
+ }
+
+ /**
+ * Calls {@link #declareLabel} for each label in the given stack map frame types.
+ *
+ * @param numTypes the number of stack map frame types in 'frameTypes'.
+ * @param frameTypes an array of stack map frame types, in the format described in {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ */
+ private void declareFrameTypes(final int numTypes, final Object[] frameTypes) {
+ for (int i = 0; i < numTypes; ++i) {
+ if (frameTypes[i] instanceof Label) {
+ declareLabel((Label) frameTypes[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends the given stack map frame types to {@link #stringBuilder}.
+ *
+ * @param numTypes the number of stack map frame types in 'frameTypes'.
+ * @param frameTypes an array of stack map frame types, in the format described in {@link
+ * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ */
+ private void appendFrameTypes(final int numTypes, final Object[] frameTypes) {
+ for (int i = 0; i < numTypes; ++i) {
+ if (i > 0) {
+ stringBuilder.append(", ");
+ }
+ if (frameTypes[i] instanceof String) {
+ appendConstant(frameTypes[i]);
+ } else if (frameTypes[i] instanceof Integer) {
+ switch (((Integer) frameTypes[i]).intValue()) {
+ case 0:
+ stringBuilder.append("Opcodes.TOP");
break;
- case Opcodes.F_APPEND:
- declareFrameTypes(nLocal, local);
- buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
- .append(nLocal).append(", new Object[] {");
- appendFrameTypes(nLocal, local);
- buf.append("}, 0, null");
+ case 1:
+ stringBuilder.append("Opcodes.INTEGER");
break;
- case Opcodes.F_CHOP:
- buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
- .append(nLocal).append(", null, 0, null");
+ case 2:
+ stringBuilder.append("Opcodes.FLOAT");
break;
- case Opcodes.F_SAME:
- buf.append(name).append(
- ".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ case 3:
+ stringBuilder.append("Opcodes.DOUBLE");
break;
- case Opcodes.F_SAME1:
- declareFrameTypes(1, stack);
- buf.append(name).append(
- ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
- appendFrameTypes(1, stack);
- buf.append('}');
+ case 4:
+ stringBuilder.append("Opcodes.LONG");
break;
+ case 5:
+ stringBuilder.append("Opcodes.NULL");
+ break;
+ case 6:
+ stringBuilder.append("Opcodes.UNINITIALIZED_THIS");
+ break;
+ default:
+ throw new IllegalArgumentException();
}
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitInsn(final int opcode) {
- buf.setLength(0);
- buf.append(name).append(".visitInsn(").append(OPCODES[opcode])
- .append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitIntInsn(final int opcode, final int operand) {
- buf.setLength(0);
- buf.append(name)
- .append(".visitIntInsn(")
- .append(OPCODES[opcode])
- .append(", ")
- .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
- .toString(operand)).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitVarInsn(final int opcode, final int var) {
- buf.setLength(0);
- buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode])
- .append(", ").append(var).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitTypeInsn(final int opcode, final String type) {
- buf.setLength(0);
- buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode])
- .append(", ");
- appendConstant(type);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitFieldInsn(final int opcode, final String owner,
- final String name, final String desc) {
- buf.setLength(0);
- buf.append(this.name).append(".visitFieldInsn(")
- .append(OPCODES[opcode]).append(", ");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Deprecated
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc) {
- if (api >= Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc,
- opcode == Opcodes.INVOKEINTERFACE);
- }
-
- @Override
- public void visitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- if (api < Opcodes.ASM5) {
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- return;
- }
- doVisitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- private void doVisitMethodInsn(final int opcode, final String owner,
- final String name, final String desc, final boolean itf) {
- buf.setLength(0);
- buf.append(this.name).append(".visitMethodInsn(")
- .append(OPCODES[opcode]).append(", ");
- appendConstant(owner);
- buf.append(", ");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- buf.append(itf ? "true" : "false");
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
- Object... bsmArgs) {
- buf.setLength(0);
- buf.append(this.name).append(".visitInvokeDynamicInsn(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(bsm);
- buf.append(", new Object[]{");
- for (int i = 0; i < bsmArgs.length; ++i) {
- appendConstant(bsmArgs[i]);
- if (i != bsmArgs.length - 1) {
- buf.append(", ");
- }
- }
- buf.append("});\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitJumpInsn(final int opcode, final Label label) {
- buf.setLength(0);
- declareLabel(label);
- buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode])
- .append(", ");
- appendLabel(label);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLabel(final Label label) {
- buf.setLength(0);
- declareLabel(label);
- buf.append(name).append(".visitLabel(");
- appendLabel(label);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLdcInsn(final Object cst) {
- buf.setLength(0);
- buf.append(name).append(".visitLdcInsn(");
- appendConstant(cst);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitIincInsn(final int var, final int increment) {
- buf.setLength(0);
- buf.append(name).append(".visitIincInsn(").append(var).append(", ")
- .append(increment).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitTableSwitchInsn(final int min, final int max,
- final Label dflt, final Label... labels) {
- buf.setLength(0);
- for (int i = 0; i < labels.length; ++i) {
- declareLabel(labels[i]);
- }
- declareLabel(dflt);
-
- buf.append(name).append(".visitTableSwitchInsn(").append(min)
- .append(", ").append(max).append(", ");
- appendLabel(dflt);
- buf.append(", new Label[] {");
- for (int i = 0; i < labels.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(labels[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
- final Label[] labels) {
- buf.setLength(0);
- for (int i = 0; i < labels.length; ++i) {
- declareLabel(labels[i]);
- }
- declareLabel(dflt);
-
- buf.append(name).append(".visitLookupSwitchInsn(");
- appendLabel(dflt);
- buf.append(", new int[] {");
- for (int i = 0; i < keys.length; ++i) {
- buf.append(i == 0 ? " " : ", ").append(keys[i]);
- }
- buf.append(" }, new Label[] {");
- for (int i = 0; i < labels.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(labels[i]);
- }
- buf.append(" });\n");
- text.add(buf.toString());
- }
-
- @Override
- public void visitMultiANewArrayInsn(final String desc, final int dims) {
- buf.setLength(0);
- buf.append(name).append(".visitMultiANewArrayInsn(");
- appendConstant(desc);
- buf.append(", ").append(dims).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitInsnAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath,
- desc, visible);
- }
-
- @Override
- public void visitTryCatchBlock(final Label start, final Label end,
- final Label handler, final String type) {
- buf.setLength(0);
- declareLabel(start);
- declareLabel(end);
- declareLabel(handler);
- buf.append(name).append(".visitTryCatchBlock(");
- appendLabel(start);
- buf.append(", ");
- appendLabel(end);
- buf.append(", ");
- appendLabel(handler);
- buf.append(", ");
- appendConstant(type);
- buf.append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public ASMifier visitTryCatchAnnotation(final int typeRef,
- final TypePath typePath, final String desc, final boolean visible) {
- return visitTypeAnnotation("visitTryCatchAnnotation", typeRef,
- typePath, desc, visible);
- }
-
- @Override
- public void visitLocalVariable(final String name, final String desc,
- final String signature, final Label start, final Label end,
- final int index) {
- buf.setLength(0);
- buf.append(this.name).append(".visitLocalVariable(");
- appendConstant(name);
- buf.append(", ");
- appendConstant(desc);
- buf.append(", ");
- appendConstant(signature);
- buf.append(", ");
- appendLabel(start);
- buf.append(", ");
- appendLabel(end);
- buf.append(", ").append(index).append(");\n");
- text.add(buf.toString());
- }
-
- @Override
- public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
- Label[] start, Label[] end, int[] index, String desc,
- boolean visible) {
- buf.setLength(0);
- buf.append("{\n").append("av0 = ").append(name)
- .append(".visitLocalVariableAnnotation(");
- buf.append(typeRef);
- if (typePath == null) {
- buf.append(", null, ");
- } else {
- buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
- }
- buf.append("new Label[] {");
- for (int i = 0; i < start.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(start[i]);
- }
- buf.append(" }, new Label[] {");
- for (int i = 0; i < end.length; ++i) {
- buf.append(i == 0 ? " " : ", ");
- appendLabel(end[i]);
- }
- buf.append(" }, new int[] {");
- for (int i = 0; i < index.length; ++i) {
- buf.append(i == 0 ? " " : ", ").append(index[i]);
- }
- buf.append(" }, ");
- appendConstant(desc);
- buf.append(", ").append(visible).append(");\n");
- text.add(buf.toString());
- ASMifier a = createASMifier("av", 0);
- text.add(a.getText());
- text.add("}\n");
- return a;
- }
-
- @Override
- public void visitLineNumber(final int line, final Label start) {
- buf.setLength(0);
- buf.append(name).append(".visitLineNumber(").append(line).append(", ");
- appendLabel(
<TRUNCATED>