123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /* *******************************************************************
- * Copyright (c) 2005 Contributors.
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * Adrian Colyer Initial implementation
- * ******************************************************************/
- package org.aspectj.weaver.patterns;
-
- import java.io.IOException;
-
- import org.aspectj.weaver.CompressingDataOutputStream;
- import org.aspectj.weaver.ISourceContext;
- import org.aspectj.weaver.UnresolvedType;
- import org.aspectj.weaver.VersionedDataInputStream;
-
- /**
- * @author colyer Represents a type variable as declared as part of a type declaration, parameter declaration, or type parameter
- * specification.
- * <p>
- * For example:
- * </p>
- * <ul>
- * <li><T> T genericMethod(T t) {...}</li>
- * <li>static <T extends Foo> T staticGenericMethod(T t) {...}</li>
- * <li>Foo<T extends Bar & IGoo>
- * </ul>
- */
- public class TypeVariablePattern extends PatternNode {
-
- private static final String anything = "?";
-
- private String name; // eg. "T"
- private TypePattern upperBound; // default is object unless of the form T extends Bar
- private TypePattern[] interfaceBounds; // additional upper bounds (must be interfaces) arising from
- // declarations of the form T extends Bar & IGoo, IDoo
- private TypePattern lowerBound; // only set if type variable is of the form T super Bar
-
- /**
- * Create a named type variable with upper bound Object and no lower bounds. Use this constructor for the simple "T" case
- */
- public TypeVariablePattern(String variableName) {
- this.name = variableName;
- this.upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
- this.lowerBound = null;
- this.interfaceBounds = null;
- }
-
- /**
- * Create a named type variable with the given upper bound and no lower bounds Use this constructor for the T extends Foo case
- *
- * @param variableName
- * @param upperBound
- */
- public TypeVariablePattern(String variableName, TypePattern upperBound) {
- this.name = variableName;
- this.upperBound = upperBound;
- this.lowerBound = null;
- this.interfaceBounds = null;
- }
-
- public TypeVariablePattern(String variableName, TypePattern upperLimit, TypePattern[] interfaceBounds, TypePattern lowerBound) {
- this.name = variableName;
- this.upperBound = upperLimit;
- if (upperBound == null) {
- upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
- }
- this.interfaceBounds = interfaceBounds;
- this.lowerBound = lowerBound;
- }
-
- public Object accept(PatternNodeVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isAnythingPattern() {
- return name.equals(anything);
- }
-
- public TypePattern getRawTypePattern() {
- return upperBound;
- }
-
- public TypePattern getUpperBound() {
- return upperBound;
- }
-
- public boolean hasLowerBound() {
- return (lowerBound != null);
- }
-
- public TypePattern getLowerBound() {
- return lowerBound;
- }
-
- public boolean hasAdditionalInterfaceBounds() {
- return (interfaceBounds != null);
- }
-
- public TypePattern[] getAdditionalInterfaceBounds() {
- if (interfaceBounds != null) {
- return interfaceBounds;
- } else {
- return new TypePattern[0];
- }
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof TypeVariablePattern)) {
- return false;
- }
- TypeVariablePattern other = (TypeVariablePattern) obj;
- if (!name.equals(other.name)) {
- return false;
- }
- if (!upperBound.equals(other.upperBound)) {
- return false;
- }
- if (lowerBound != null) {
- if (other.lowerBound == null) {
- return false;
- }
- if (!lowerBound.equals(other.lowerBound)) {
- return false;
- }
- } else {
- if (other.lowerBound != null) {
- return false;
- }
- }
- if (interfaceBounds != null) {
- if (other.interfaceBounds == null) {
- return false;
- }
- if (interfaceBounds.length != other.interfaceBounds.length) {
- return false;
- }
- for (int i = 0; i < interfaceBounds.length; i++) {
- if (!interfaceBounds[i].equals(other.interfaceBounds[i])) {
- return false;
- }
- }
- } else {
- if (other.interfaceBounds != null) {
- return false;
- }
- }
- return true;
- }
-
- public int hashCode() {
- int hashCode = 17 + (37 * name.hashCode());
- hashCode = hashCode * 37 + upperBound.hashCode();
- if (lowerBound != null) {
- hashCode = hashCode * 37 + lowerBound.hashCode();
- }
- if (interfaceBounds != null) {
- for (TypePattern interfaceBound : interfaceBounds) {
- hashCode = 37 * hashCode + interfaceBound.hashCode();
- }
- }
- return hashCode;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(name);
- sb.append(getExtendsClause());
- if (interfaceBounds != null) {
- sb.append(" & ");
- for (int i = 0; i < interfaceBounds.length; i++) {
- sb.append(interfaceBounds[i].toString());
- if (i < interfaceBounds.length) {
- sb.append(",");
- }
- }
- }
- if (lowerBound != null) {
- sb.append(" super ");
- sb.append(lowerBound.toString());
- }
- return sb.toString();
- }
-
- private String getExtendsClause() {
- if (upperBound instanceof ExactTypePattern) {
- ExactTypePattern bound = (ExactTypePattern) upperBound;
- if (bound.type == UnresolvedType.OBJECT) {
- return "";
- }
- }
- return " extends " + upperBound.toString();
- }
-
- public void write(CompressingDataOutputStream s) throws IOException {
- s.writeUTF(name);
- upperBound.write(s);
- if (interfaceBounds == null) {
- s.writeInt(0);
- } else {
- s.writeInt(interfaceBounds.length);
- for (TypePattern interfaceBound : interfaceBounds) {
- interfaceBound.write(s);
- }
- }
- s.writeBoolean(hasLowerBound());
- if (hasLowerBound()) {
- lowerBound.write(s);
- }
- writeLocation(s);
- }
-
- public static TypeVariablePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
- TypeVariablePattern tv = null;
- String name = s.readUTF();
- TypePattern upperBound = TypePattern.read(s, context);
- TypePattern[] additionalInterfaceBounds = null;
- int numInterfaceBounds = s.readInt();
- if (numInterfaceBounds > 0) {
- additionalInterfaceBounds = new TypePattern[numInterfaceBounds];
- for (int i = 0; i < additionalInterfaceBounds.length; i++) {
- additionalInterfaceBounds[i] = TypePattern.read(s, context);
- }
- }
- boolean hasLowerBound = s.readBoolean();
- TypePattern lowerBound = null;
- if (hasLowerBound) {
- lowerBound = TypePattern.read(s, context);
- }
- tv = new TypeVariablePattern(name, upperBound, additionalInterfaceBounds, lowerBound);
- tv.readLocation(context, s);
- return tv;
- }
-
- }
|