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:33:55 UTC
[08/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/CheckModuleAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
old mode 100644
new mode 100755
index cdc2531..0d6d28d
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java
@@ -1,151 +1,212 @@
-/***
- * 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.util.HashSet;
-
import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
+ * A {@link ModuleVisitor} that checks that its methods are properly used.
+ *
* @author Remi Forax
*/
-public final class CheckModuleAdapter extends ModuleVisitor {
- private boolean end;
- private final boolean isOpen;
-
- private final HashSet<String> requireNames = new HashSet<String>();
- private final HashSet<String> exportNames = new HashSet<String>();
- private final HashSet<String> openNames = new HashSet<String>();
- private final HashSet<String> useNames = new HashSet<String>();
- private final HashSet<String> provideNames = new HashSet<String>();
-
- public CheckModuleAdapter(final ModuleVisitor mv, final boolean isOpen) {
- super(Opcodes.ASM6, mv);
- this.isOpen = isOpen;
+public class CheckModuleAdapter extends ModuleVisitor {
+ /** Whether the visited module is open. */
+ private final boolean isOpen;
+
+ /** The fully qualified names of the dependencies of the visited module. */
+ private final NameSet requiredModules = new NameSet("Modules requires");
+
+ /** The internal names of the packages exported by the visited module. */
+ private final NameSet exportedPackages = new NameSet("Module exports");
+
+ /** The internal names of the packages opened by the visited module. */
+ private final NameSet openedPackages = new NameSet("Module opens");
+
+ /** The internal names of the services used by the visited module. */
+ private final NameSet usedServices = new NameSet("Module uses");
+
+ /** The internal names of the services provided by the visited module. */
+ private final NameSet providedServices = new NameSet("Module provides");
+
+ /** The class version number. */
+ int classVersion;
+
+ /** Whether the {@link #visitEnd} method has been called. */
+ private boolean visitEndCalled;
+
+ /**
+ * Constructs a new {@link CheckModuleAdapter}. <i>Subclasses must not use this constructor</i>.
+ * Instead, they must use the {@link #CheckModuleAdapter(int, ModuleVisitor, boolean)} version.
+ *
+ * @param moduleVisitor the module visitor to which this adapter must delegate calls.
+ * @param isOpen whether the visited module is open. Open modules have their {@link
+ * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}.
+ * @throws IllegalStateException If a subclass calls this constructor.
+ */
+ public CheckModuleAdapter(final ModuleVisitor moduleVisitor, final boolean isOpen) {
+ this(Opcodes.ASM7, moduleVisitor, isOpen);
+ if (getClass() != CheckModuleAdapter.class) {
+ throw new IllegalStateException();
}
-
- @Override
- public void visitRequire(String module, int access, String version) {
- checkEnd();
- if (module == null) {
- throw new IllegalArgumentException("require cannot be null");
- }
- checkDeclared("requires", requireNames, module);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_STATIC_PHASE
- + Opcodes.ACC_TRANSITIVE + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_MANDATED);
- super.visitRequire(module, access, version);
+ }
+
+ /**
+ * Constructs a new {@link CheckModuleAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param moduleVisitor the module visitor to which this adapter must delegate calls.
+ * @param isOpen whether the visited module is open. Open modules have their {@link
+ * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}.
+ */
+ protected CheckModuleAdapter(
+ final int api, final ModuleVisitor moduleVisitor, final boolean isOpen) {
+ super(api, moduleVisitor);
+ this.isOpen = isOpen;
+ }
+
+ @Override
+ public void visitMainClass(final String mainClass) {
+ // Modules can only appear in V9 or more classes.
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, mainClass, "module main class");
+ super.visitMainClass(mainClass);
+ }
+
+ @Override
+ public void visitPackage(final String packaze) {
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "module package");
+ super.visitPackage(packaze);
+ }
+
+ @Override
+ public void visitRequire(final String module, final int access, final String version) {
+ checkVisitEndNotCalled();
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "required module");
+ requiredModules.checkNameNotAlreadyDeclared(module);
+ CheckClassAdapter.checkAccess(
+ access,
+ Opcodes.ACC_STATIC_PHASE
+ | Opcodes.ACC_TRANSITIVE
+ | Opcodes.ACC_SYNTHETIC
+ | Opcodes.ACC_MANDATED);
+ if (classVersion >= Opcodes.V10
+ && module.equals("java.base")
+ && (access & (Opcodes.ACC_STATIC_PHASE | Opcodes.ACC_TRANSITIVE)) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid access flags: "
+ + access
+ + " java.base can not be declared ACC_TRANSITIVE or ACC_STATIC_PHASE");
}
-
- @Override
- public void visitExport(String packaze, int access, String... modules) {
- checkEnd();
- if (packaze == null) {
- throw new IllegalArgumentException("packaze cannot be null");
- }
- CheckMethodAdapter.checkInternalName(packaze, "package name");
- checkDeclared("exports", exportNames, packaze);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_MANDATED);
- if (modules != null) {
- for (int i = 0; i < modules.length; i++) {
- if (modules[i] == null) {
- throw new IllegalArgumentException("module at index " + i + " cannot be null");
- }
- }
- }
- super.visitExport(packaze, access, modules);
+ super.visitRequire(module, access, version);
+ }
+
+ @Override
+ public void visitExport(final String packaze, final int access, final String... modules) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name");
+ exportedPackages.checkNameNotAlreadyDeclared(packaze);
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
+ if (modules != null) {
+ for (String module : modules) {
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module export to");
+ }
}
-
- @Override
- public void visitOpen(String packaze, int access, String... modules) {
- checkEnd();
- if (isOpen) {
- throw new IllegalArgumentException("an open module can not use open directive");
- }
- if (packaze == null) {
- throw new IllegalArgumentException("packaze cannot be null");
- }
- CheckMethodAdapter.checkInternalName(packaze, "package name");
- checkDeclared("opens", openNames, packaze);
- CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
- + Opcodes.ACC_MANDATED);
- if (modules != null) {
- for (int i = 0; i < modules.length; i++) {
- if (modules[i] == null) {
- throw new IllegalArgumentException("module at index " + i + " cannot be null");
- }
- }
- }
- super.visitOpen(packaze, access, modules);
+ super.visitExport(packaze, access, modules);
+ }
+
+ @Override
+ public void visitOpen(final String packaze, final int access, final String... modules) {
+ checkVisitEndNotCalled();
+ if (isOpen) {
+ throw new UnsupportedOperationException("An open module can not use open directive");
}
-
- @Override
- public void visitUse(String service) {
- checkEnd();
- CheckMethodAdapter.checkInternalName(service, "service");
- checkDeclared("uses", useNames, service);
- super.visitUse(service);
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name");
+ openedPackages.checkNameNotAlreadyDeclared(packaze);
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED);
+ if (modules != null) {
+ for (String module : modules) {
+ CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module open to");
+ }
}
-
- @Override
- public void visitProvide(String service, String... providers) {
- checkEnd();
- CheckMethodAdapter.checkInternalName(service, "service");
- checkDeclared("provides", provideNames, service);
- if (providers == null || providers.length == 0) {
- throw new IllegalArgumentException("providers cannot be null or empty");
- }
- for (int i = 0; i < providers.length; i++) {
- CheckMethodAdapter.checkInternalName(providers[i], "provider");
- }
- super.visitProvide(service, providers);
+ super.visitOpen(packaze, access, modules);
+ }
+
+ @Override
+ public void visitUse(final String service) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service");
+ usedServices.checkNameNotAlreadyDeclared(service);
+ super.visitUse(service);
+ }
+
+ @Override
+ public void visitProvide(final String service, final String... providers) {
+ checkVisitEndNotCalled();
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service");
+ providedServices.checkNameNotAlreadyDeclared(service);
+ if (providers == null || providers.length == 0) {
+ throw new IllegalArgumentException("Providers cannot be null or empty");
}
-
- @Override
- public void visitEnd() {
- checkEnd();
- end = true;
- super.visitEnd();
+ for (String provider : providers) {
+ CheckMethodAdapter.checkInternalName(Opcodes.V9, provider, "provider");
}
+ super.visitProvide(service, providers);
+ }
- private void checkEnd() {
- if (end) {
- throw new IllegalStateException(
- "Cannot call a visit method after visitEnd has been called");
- }
+ @Override
+ public void visitEnd() {
+ checkVisitEndNotCalled();
+ visitEndCalled = true;
+ super.visitEnd();
+ }
+
+ private void checkVisitEndNotCalled() {
+ if (visitEndCalled) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+
+ private static class NameSet {
+
+ private final String type;
+ private final HashSet<String> names;
+
+ NameSet(final String type) {
+ this.type = type;
+ this.names = new HashSet<String>();
}
-
- private static void checkDeclared(String directive, HashSet<String> names, String name) {
- if (!names.add(name)) {
- throw new IllegalArgumentException(directive + " " + name + " already declared");
- }
+
+ void checkNameNotAlreadyDeclared(final String name) {
+ if (!names.add(name)) {
+ throw new IllegalArgumentException(type + " " + name + " already declared");
+ }
}
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
old mode 100644
new mode 100755
index bca5dd7..8103a10
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -1,356 +1,359 @@
-/***
- * 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.util.EnumSet;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
* A {@link SignatureVisitor} that checks that its methods are properly used.
- *
+ *
* @author Eric Bruneton
*/
public class CheckSignatureAdapter extends SignatureVisitor {
- /**
- * Type to be used to check class signatures. See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int CLASS_SIGNATURE = 0;
-
- /**
- * Type to be used to check method signatures. See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int METHOD_SIGNATURE = 1;
-
- /**
- * Type to be used to check type signatures.See
- * {@link #CheckSignatureAdapter(int, SignatureVisitor)
- * CheckSignatureAdapter}.
- */
- public static final int TYPE_SIGNATURE = 2;
-
- private static final int EMPTY = 1;
-
- private static final int FORMAL = 2;
-
- private static final int BOUND = 4;
-
- private static final int SUPER = 8;
-
- private static final int PARAM = 16;
-
- private static final int RETURN = 32;
-
- private static final int SIMPLE_TYPE = 64;
-
- private static final int CLASS_TYPE = 128;
-
- private static final int END = 256;
-
- /**
- * Type of the signature to be checked.
- */
- private final int type;
-
- /**
- * State of the automaton used to check the order of method calls.
- */
- private int state;
-
- /**
- * <tt>true</tt> if the checked type signature can be 'V'.
- */
- private boolean canBeVoid;
-
- /**
- * The visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- private final SignatureVisitor sv;
-
- /**
- * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
- * not use this constructor</i>. Instead, they must use the
- * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
- *
- * @param type
- * the type of signature to be checked. See
- * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
- * {@link #TYPE_SIGNATURE}.
- * @param sv
- * the visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
- this(Opcodes.ASM6, type, sv);
+ /**
+ * Type to be used to check class signatures. See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See {@link #CheckSignatureAdapter(int,
+ * SignatureVisitor)}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ /** The valid automaton states for a {@link #visitFormalTypeParameter} method call. */
+ private static final EnumSet<State> VISIT_FORMAL_TYPE_PARAMETER_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitClassBound} method call. */
+ private static final EnumSet<State> VISIT_CLASS_BOUND_STATES = EnumSet.of(State.FORMAL);
+
+ /** The valid automaton states for a {@link #visitInterfaceBound} method call. */
+ private static final EnumSet<State> VISIT_INTERFACE_BOUND_STATES =
+ EnumSet.of(State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitSuperclass} method call. */
+ private static final EnumSet<State> VISIT_SUPER_CLASS_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND);
+
+ /** The valid automaton states for a {@link #visitInterface} method call. */
+ private static final EnumSet<State> VISIT_INTERFACE_STATES = EnumSet.of(State.SUPER);
+
+ /** The valid automaton states for a {@link #visitParameterType} method call. */
+ private static final EnumSet<State> VISIT_PARAMETER_TYPE_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM);
+
+ /** The valid automaton states for a {@link #visitReturnType} method call. */
+ private static final EnumSet<State> VISIT_RETURN_TYPE_STATES =
+ EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM);
+
+ /** The valid automaton states for a {@link #visitExceptionType} method call. */
+ private static final EnumSet<State> VISIT_EXCEPTION_TYPE_STATES = EnumSet.of(State.RETURN);
+
+ /** The possible states of the automaton used to check the order of method calls. */
+ private enum State {
+ EMPTY,
+ FORMAL,
+ BOUND,
+ SUPER,
+ PARAM,
+ RETURN,
+ SIMPLE_TYPE,
+ CLASS_TYPE,
+ END;
+ }
+
+ private static final String INVALID = "Invalid ";
+
+ /** The type of the visited signature. */
+ private final int type;
+
+ /** The current state of the automaton used to check the order of method calls. */
+ private State state;
+
+ /** Whether the visited signature can be 'V'. */
+ private boolean canBeVoid;
+
+ /** The visitor to which this adapter must delegate calls. May be {@literal null}. */
+ private final SignatureVisitor signatureVisitor;
+
+ /**
+ * Constructs a new {@link CheckSignatureAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #CheckSignatureAdapter(int, int,
+ * SignatureVisitor)} version.
+ *
+ * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link
+ * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}.
+ * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal
+ * null}.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor signatureVisitor) {
+ this(Opcodes.ASM7, type, signatureVisitor);
+ }
+
+ /**
+ * Constructs a new {@link CheckSignatureAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one of {@link
+ * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+ * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link
+ * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}.
+ * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal
+ * null}.
+ */
+ protected CheckSignatureAdapter(
+ final int api, final int type, final SignatureVisitor signatureVisitor) {
+ super(api);
+ this.type = type;
+ this.state = State.EMPTY;
+ this.signatureVisitor = signatureVisitor;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE || !VISIT_FORMAL_TYPE_PARAMETER_STATES.contains(state)) {
+ throw new IllegalStateException();
}
-
- /**
- * Creates a new {@link CheckSignatureAdapter} object.
- *
- * @param api
- * the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
- * @param type
- * the type of signature to be checked. See
- * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
- * {@link #TYPE_SIGNATURE}.
- * @param sv
- * the visitor to which this adapter must delegate calls. May be
- * <tt>null</tt>.
- */
- protected CheckSignatureAdapter(final int api, final int type,
- final SignatureVisitor sv) {
- super(api);
- this.type = type;
- this.state = EMPTY;
- this.sv = sv;
+ checkIdentifier(name, "formal type parameter");
+ state = State.FORMAL;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitFormalTypeParameter(name);
}
+ }
- // class and method signatures
-
- @Override
- public void visitFormalTypeParameter(final String name) {
- if (type == TYPE_SIGNATURE
- || (state != EMPTY && state != FORMAL && state != BOUND)) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "formal type parameter");
- state = FORMAL;
- if (sv != null) {
- sv.visitFormalTypeParameter(name);
- }
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (type == TYPE_SIGNATURE || !VISIT_CLASS_BOUND_STATES.contains(state)) {
+ throw new IllegalStateException();
}
-
- @Override
- public SignatureVisitor visitClassBound() {
- if (state != FORMAL) {
- throw new IllegalStateException();
- }
- state = BOUND;
- SignatureVisitor v = sv == null ? null : sv.visitClassBound();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.BOUND;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitClassBound());
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (type == TYPE_SIGNATURE || !VISIT_INTERFACE_BOUND_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterfaceBound());
+ }
- @Override
- public SignatureVisitor visitInterfaceBound() {
- if (state != FORMAL && state != BOUND) {
- throw new IllegalArgumentException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || !VISIT_SUPER_CLASS_STATES.contains(state)) {
+ throw new IllegalArgumentException();
+ }
+ state = State.SUPER;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitSuperclass());
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (type != CLASS_SIGNATURE || !VISIT_INTERFACE_STATES.contains(state)) {
+ throw new IllegalStateException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterface());
+ }
- // class signatures
+ // method signatures
- @Override
- public SignatureVisitor visitSuperclass() {
- if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
- throw new IllegalArgumentException();
- }
- state = SUPER;
- SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE || !VISIT_PARAMETER_TYPE_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
-
- @Override
- public SignatureVisitor visitInterface() {
- if (state != SUPER) {
- throw new IllegalStateException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitInterface();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.PARAM;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitParameterType());
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE || !VISIT_RETURN_TYPE_STATES.contains(state)) {
+ throw new IllegalArgumentException();
}
-
- // method signatures
-
- @Override
- public SignatureVisitor visitParameterType() {
- if (type != METHOD_SIGNATURE
- || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
- throw new IllegalArgumentException();
- }
- state = PARAM;
- SignatureVisitor v = sv == null ? null : sv.visitParameterType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ state = State.RETURN;
+ CheckSignatureAdapter checkSignatureAdapter =
+ new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitReturnType());
+ checkSignatureAdapter.canBeVoid = true;
+ return checkSignatureAdapter;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (type != METHOD_SIGNATURE || !VISIT_EXCEPTION_TYPE_STATES.contains(state)) {
+ throw new IllegalStateException();
}
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitExceptionType());
+ }
- @Override
- public SignatureVisitor visitReturnType() {
- if (type != METHOD_SIGNATURE
- || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
- throw new IllegalArgumentException();
- }
- state = RETURN;
- SignatureVisitor v = sv == null ? null : sv.visitReturnType();
- CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
- cv.canBeVoid = true;
- return cv;
- }
+ // type signatures
- @Override
- public SignatureVisitor visitExceptionType() {
- if (state != RETURN) {
- throw new IllegalStateException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
-
- // type signatures
-
- @Override
- public void visitBaseType(final char descriptor) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- if (descriptor == 'V') {
- if (!canBeVoid) {
- throw new IllegalArgumentException();
- }
- } else {
- if ("ZCBSIFJD".indexOf(descriptor) == -1) {
- throw new IllegalArgumentException();
- }
- }
- state = SIMPLE_TYPE;
- if (sv != null) {
- sv.visitBaseType(descriptor);
- }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
}
-
- @Override
- public void visitTypeVariable(final String name) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "type variable");
- state = SIMPLE_TYPE;
- if (sv != null) {
- sv.visitTypeVariable(name);
- }
+ state = State.SIMPLE_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitBaseType(descriptor);
}
+ }
- @Override
- public SignatureVisitor visitArrayType() {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- state = SIMPLE_TYPE;
- SignatureVisitor v = sv == null ? null : sv.visitArrayType();
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
-
- @Override
- public void visitClassType(final String name) {
- if (type != TYPE_SIGNATURE || state != EMPTY) {
- throw new IllegalStateException();
- }
- checkClassName(name, "class name");
- state = CLASS_TYPE;
- if (sv != null) {
- sv.visitClassType(name);
- }
+ checkIdentifier(name, "type variable");
+ state = State.SIMPLE_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitTypeVariable(name);
}
+ }
- @Override
- public void visitInnerClassType(final String name) {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- checkIdentifier(name, "inner class name");
- if (sv != null) {
- sv.visitInnerClassType(name);
- }
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = State.SIMPLE_TYPE;
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitArrayType());
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != State.EMPTY) {
+ throw new IllegalStateException();
}
+ checkClassName(name, "class name");
+ state = State.CLASS_TYPE;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitClassType(name);
+ }
+ }
- @Override
- public void visitTypeArgument() {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- if (sv != null) {
- sv.visitTypeArgument();
- }
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ checkIdentifier(name, "inner class name");
+ if (signatureVisitor != null) {
+ signatureVisitor.visitInnerClassType(name);
}
+ }
- @Override
- public SignatureVisitor visitTypeArgument(final char wildcard) {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- if ("+-=".indexOf(wildcard) == -1) {
- throw new IllegalArgumentException();
- }
- SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
- return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ @Override
+ public void visitTypeArgument() {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (signatureVisitor != null) {
+ signatureVisitor.visitTypeArgument();
}
+ }
- @Override
- public void visitEnd() {
- if (state != CLASS_TYPE) {
- throw new IllegalStateException();
- }
- state = END;
- if (sv != null) {
- sv.visitEnd();
- }
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
}
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ return new CheckSignatureAdapter(
+ TYPE_SIGNATURE,
+ signatureVisitor == null ? null : signatureVisitor.visitTypeArgument(wildcard));
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != State.CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = State.END;
+ if (signatureVisitor != null) {
+ signatureVisitor.visitEnd();
+ }
+ }
- private void checkClassName(final String name, final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- for (int i = 0; i < name.length(); ++i) {
- if (".;[<>:".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not contain . ; [ < > or :): " + name);
- }
- }
+ private void checkClassName(final String name, final String message) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)");
}
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[<>:".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException(
+ INVALID + message + " (must not contain . ; [ < > or :): " + name);
+ }
+ }
+ }
- private void checkIdentifier(final String name, final String msg) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not be null or empty)");
- }
- for (int i = 0; i < name.length(); ++i) {
- if (".;[/<>:".indexOf(name.charAt(i)) != -1) {
- throw new IllegalArgumentException("Invalid " + msg
- + " (must not contain . ; [ / < > or :): " + name);
- }
- }
+ private void checkIdentifier(final String name, final String message) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)");
+ }
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>:".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException(
+ INVALID + message + " (must not contain . ; [ / < > or :): " + name);
+ }
}
+ }
}