You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TypeVariablePattern.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* *******************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * Adrian Colyer Initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.IOException;
  14. import org.aspectj.weaver.CompressingDataOutputStream;
  15. import org.aspectj.weaver.ISourceContext;
  16. import org.aspectj.weaver.UnresolvedType;
  17. import org.aspectj.weaver.VersionedDataInputStream;
  18. /**
  19. * @author colyer Represents a type variable as declared as part of a type declaration, parameter declaration, or type parameter
  20. * specification.
  21. * <p>
  22. * For example:
  23. * </p>
  24. * <ul>
  25. * <li>&lt;T&gt; T genericMethod(T t) {...}</li>
  26. * <li>static &lt;T extends Foo&gt; T staticGenericMethod(T t) {...}</li>
  27. * <li>Foo&lt;T extends Bar &amp; IGoo&gt;
  28. * </ul>
  29. */
  30. public class TypeVariablePattern extends PatternNode {
  31. private static final String anything = "?";
  32. private String name; // eg. "T"
  33. private TypePattern upperBound; // default is object unless of the form T extends Bar
  34. private TypePattern[] interfaceBounds; // additional upper bounds (must be interfaces) arising from
  35. // declarations of the form T extends Bar & IGoo, IDoo
  36. private TypePattern lowerBound; // only set if type variable is of the form T super Bar
  37. /**
  38. * Create a named type variable with upper bound Object and no lower bounds. Use this constructor for the simple "T" case
  39. */
  40. public TypeVariablePattern(String variableName) {
  41. this.name = variableName;
  42. this.upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
  43. this.lowerBound = null;
  44. this.interfaceBounds = null;
  45. }
  46. /**
  47. * Create a named type variable with the given upper bound and no lower bounds Use this constructor for the T extends Foo case
  48. *
  49. * @param variableName
  50. * @param upperBound
  51. */
  52. public TypeVariablePattern(String variableName, TypePattern upperBound) {
  53. this.name = variableName;
  54. this.upperBound = upperBound;
  55. this.lowerBound = null;
  56. this.interfaceBounds = null;
  57. }
  58. public TypeVariablePattern(String variableName, TypePattern upperLimit, TypePattern[] interfaceBounds, TypePattern lowerBound) {
  59. this.name = variableName;
  60. this.upperBound = upperLimit;
  61. if (upperBound == null) {
  62. upperBound = new ExactTypePattern(UnresolvedType.OBJECT, false, false);
  63. }
  64. this.interfaceBounds = interfaceBounds;
  65. this.lowerBound = lowerBound;
  66. }
  67. public Object accept(PatternNodeVisitor visitor, Object data) {
  68. return visitor.visit(this, data);
  69. }
  70. public String getName() {
  71. return name;
  72. }
  73. public boolean isAnythingPattern() {
  74. return name.equals(anything);
  75. }
  76. public TypePattern getRawTypePattern() {
  77. return upperBound;
  78. }
  79. public TypePattern getUpperBound() {
  80. return upperBound;
  81. }
  82. public boolean hasLowerBound() {
  83. return (lowerBound != null);
  84. }
  85. public TypePattern getLowerBound() {
  86. return lowerBound;
  87. }
  88. public boolean hasAdditionalInterfaceBounds() {
  89. return (interfaceBounds != null);
  90. }
  91. public TypePattern[] getAdditionalInterfaceBounds() {
  92. if (interfaceBounds != null) {
  93. return interfaceBounds;
  94. } else {
  95. return new TypePattern[0];
  96. }
  97. }
  98. public boolean equals(Object obj) {
  99. if (!(obj instanceof TypeVariablePattern)) {
  100. return false;
  101. }
  102. TypeVariablePattern other = (TypeVariablePattern) obj;
  103. if (!name.equals(other.name)) {
  104. return false;
  105. }
  106. if (!upperBound.equals(other.upperBound)) {
  107. return false;
  108. }
  109. if (lowerBound != null) {
  110. if (other.lowerBound == null) {
  111. return false;
  112. }
  113. if (!lowerBound.equals(other.lowerBound)) {
  114. return false;
  115. }
  116. } else {
  117. if (other.lowerBound != null) {
  118. return false;
  119. }
  120. }
  121. if (interfaceBounds != null) {
  122. if (other.interfaceBounds == null) {
  123. return false;
  124. }
  125. if (interfaceBounds.length != other.interfaceBounds.length) {
  126. return false;
  127. }
  128. for (int i = 0; i < interfaceBounds.length; i++) {
  129. if (!interfaceBounds[i].equals(other.interfaceBounds[i])) {
  130. return false;
  131. }
  132. }
  133. } else {
  134. if (other.interfaceBounds != null) {
  135. return false;
  136. }
  137. }
  138. return true;
  139. }
  140. public int hashCode() {
  141. int hashCode = 17 + (37 * name.hashCode());
  142. hashCode = hashCode * 37 + upperBound.hashCode();
  143. if (lowerBound != null) {
  144. hashCode = hashCode * 37 + lowerBound.hashCode();
  145. }
  146. if (interfaceBounds != null) {
  147. for (TypePattern interfaceBound : interfaceBounds) {
  148. hashCode = 37 * hashCode + interfaceBound.hashCode();
  149. }
  150. }
  151. return hashCode;
  152. }
  153. public String toString() {
  154. StringBuilder sb = new StringBuilder();
  155. sb.append(name);
  156. sb.append(getExtendsClause());
  157. if (interfaceBounds != null) {
  158. sb.append(" & ");
  159. for (int i = 0; i < interfaceBounds.length; i++) {
  160. sb.append(interfaceBounds[i].toString());
  161. if (i < interfaceBounds.length) {
  162. sb.append(",");
  163. }
  164. }
  165. }
  166. if (lowerBound != null) {
  167. sb.append(" super ");
  168. sb.append(lowerBound.toString());
  169. }
  170. return sb.toString();
  171. }
  172. private String getExtendsClause() {
  173. if (upperBound instanceof ExactTypePattern) {
  174. ExactTypePattern bound = (ExactTypePattern) upperBound;
  175. if (bound.type == UnresolvedType.OBJECT) {
  176. return "";
  177. }
  178. }
  179. return " extends " + upperBound.toString();
  180. }
  181. public void write(CompressingDataOutputStream s) throws IOException {
  182. s.writeUTF(name);
  183. upperBound.write(s);
  184. if (interfaceBounds == null) {
  185. s.writeInt(0);
  186. } else {
  187. s.writeInt(interfaceBounds.length);
  188. for (TypePattern interfaceBound : interfaceBounds) {
  189. interfaceBound.write(s);
  190. }
  191. }
  192. s.writeBoolean(hasLowerBound());
  193. if (hasLowerBound()) {
  194. lowerBound.write(s);
  195. }
  196. writeLocation(s);
  197. }
  198. public static TypeVariablePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  199. TypeVariablePattern tv = null;
  200. String name = s.readUTF();
  201. TypePattern upperBound = TypePattern.read(s, context);
  202. TypePattern[] additionalInterfaceBounds = null;
  203. int numInterfaceBounds = s.readInt();
  204. if (numInterfaceBounds > 0) {
  205. additionalInterfaceBounds = new TypePattern[numInterfaceBounds];
  206. for (int i = 0; i < additionalInterfaceBounds.length; i++) {
  207. additionalInterfaceBounds[i] = TypePattern.read(s, context);
  208. }
  209. }
  210. boolean hasLowerBound = s.readBoolean();
  211. TypePattern lowerBound = null;
  212. if (hasLowerBound) {
  213. lowerBound = TypePattern.read(s, context);
  214. }
  215. tv = new TypeVariablePattern(name, upperBound, additionalInterfaceBounds, lowerBound);
  216. tv.readLocation(context, s);
  217. return tv;
  218. }
  219. }