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.

TypePatternList.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.*;
  14. import java.util.*;
  15. import org.aspectj.weaver.*;
  16. import org.aspectj.util.*;
  17. public class TypePatternList extends PatternNode {
  18. private TypePattern[] typePatterns;
  19. int ellipsisCount = 0;
  20. public static final TypePatternList EMPTY =
  21. new TypePatternList(new TypePattern[] {});
  22. public static final TypePatternList ANY =
  23. new TypePatternList(new TypePattern[] {TypePattern.ELLIPSIS});
  24. public TypePatternList() {
  25. typePatterns = new TypePattern[0];
  26. ellipsisCount = 0;
  27. }
  28. public TypePatternList(TypePattern[] arguments) {
  29. this.typePatterns = arguments;
  30. for (int i=0; i<arguments.length; i++) {
  31. if (arguments[i] == TypePattern.ELLIPSIS) ellipsisCount++;
  32. }
  33. }
  34. public TypePatternList(List l) {
  35. this((TypePattern[]) l.toArray(new TypePattern[l.size()]));
  36. }
  37. public int size() { return typePatterns.length; }
  38. public TypePattern get(int index) {
  39. return typePatterns[index];
  40. }
  41. public String toString() {
  42. StringBuffer buf = new StringBuffer();
  43. buf.append("(");
  44. for (int i=0, len=typePatterns.length; i < len; i++) {
  45. TypePattern type = typePatterns[i];
  46. if (i > 0) buf.append(", ");
  47. if (type == TypePattern.ELLIPSIS) {
  48. buf.append("..");
  49. } else {
  50. buf.append(type.toString());
  51. }
  52. }
  53. buf.append(")");
  54. return buf.toString();
  55. }
  56. //XXX shares much code with WildTypePattern and with NamePattern
  57. /**
  58. * When called with TypePattern.STATIC this will always return either
  59. * FuzzyBoolean.YES or FuzzyBoolean.NO.
  60. *
  61. * When called with TypePattern.DYNAMIC this could return MAYBE if
  62. * at runtime it would be possible for arguments of the given static
  63. * types to dynamically match this, but it is not known for certain.
  64. *
  65. * This method will never return FuzzyBoolean.NEVER
  66. */
  67. public FuzzyBoolean matches(ResolvedTypeX[] types, TypePattern.MatchKind kind) {
  68. int nameLength = types.length;
  69. int patternLength = typePatterns.length;
  70. int nameIndex = 0;
  71. int patternIndex = 0;
  72. if (ellipsisCount == 0) {
  73. if (nameLength != patternLength) return FuzzyBoolean.NO;
  74. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  75. while (patternIndex < patternLength) {
  76. FuzzyBoolean ret = typePatterns[patternIndex++].matches(types[nameIndex++], kind);
  77. if (ret == FuzzyBoolean.NO) return ret;
  78. if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
  79. }
  80. return finalReturn;
  81. } else if (ellipsisCount == 1) {
  82. if (nameLength < patternLength-1) return FuzzyBoolean.NO;
  83. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  84. while (patternIndex < patternLength) {
  85. TypePattern p = typePatterns[patternIndex++];
  86. if (p == TypePattern.ELLIPSIS) {
  87. nameIndex = nameLength - (patternLength-patternIndex);
  88. } else {
  89. FuzzyBoolean ret = p.matches(types[nameIndex++], kind);
  90. if (ret == FuzzyBoolean.NO) return ret;
  91. if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
  92. }
  93. }
  94. return finalReturn;
  95. } else {
  96. // System.err.print("match(" + arguments + ", " + types + ") -> ");
  97. FuzzyBoolean b = outOfStar(typePatterns, types, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind);
  98. // System.err.println(b);
  99. return b;
  100. }
  101. }
  102. private static FuzzyBoolean outOfStar(final TypePattern[] pattern, final ResolvedTypeX[] target,
  103. int pi, int ti,
  104. int pLeft, int tLeft,
  105. final int starsLeft, TypePattern.MatchKind kind) {
  106. if (pLeft > tLeft) return FuzzyBoolean.NO;
  107. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  108. while (true) {
  109. // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
  110. if (tLeft == 0) return finalReturn;
  111. if (pLeft == 0) {
  112. if (starsLeft > 0) {
  113. return finalReturn;
  114. } else {
  115. return FuzzyBoolean.NO;
  116. }
  117. }
  118. if (pattern[pi] == TypePattern.ELLIPSIS) {
  119. return inStar(pattern, target, pi+1, ti, pLeft, tLeft, starsLeft-1, kind);
  120. }
  121. FuzzyBoolean ret = pattern[pi].matches(target[ti], kind);
  122. if (ret == FuzzyBoolean.NO) return ret;
  123. if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
  124. pi++; ti++; pLeft--; tLeft--;
  125. }
  126. }
  127. private static FuzzyBoolean inStar(final TypePattern[] pattern, final ResolvedTypeX[] target,
  128. int pi, int ti,
  129. final int pLeft, int tLeft,
  130. int starsLeft, TypePattern.MatchKind kind) {
  131. // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
  132. TypePattern patternChar = pattern[pi];
  133. while (patternChar == TypePattern.ELLIPSIS) {
  134. starsLeft--;
  135. patternChar = pattern[++pi];
  136. }
  137. while (true) {
  138. // invariant: if (tLeft > 0) then (ti < target.length)
  139. if (pLeft > tLeft) return FuzzyBoolean.NO;
  140. FuzzyBoolean ff = patternChar.matches(target[ti], kind);
  141. if (ff.maybeTrue()) {
  142. FuzzyBoolean xx = outOfStar(pattern, target, pi+1, ti+1, pLeft-1, tLeft-1, starsLeft, kind);
  143. if (xx.maybeTrue()) return ff.and(xx);
  144. }
  145. ti++; tLeft--;
  146. }
  147. }
  148. public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  149. for (int i=0; i<typePatterns.length; i++) {
  150. TypePattern p = typePatterns[i];
  151. if (p != null) {
  152. typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding, requireExactType);
  153. }
  154. }
  155. return this;
  156. }
  157. public TypePatternList resolveReferences(IntMap bindings) {
  158. int len = typePatterns.length;
  159. TypePattern[] ret = new TypePattern[len];
  160. for (int i=0; i < len; i++) {
  161. ret[i] = typePatterns[i].remapAdviceFormals(bindings);
  162. }
  163. return new TypePatternList(ret);
  164. }
  165. public void postRead(ResolvedTypeX enclosingType) {
  166. for (int i=0; i<typePatterns.length; i++) {
  167. TypePattern p = typePatterns[i];
  168. p.postRead(enclosingType);
  169. }
  170. }
  171. public boolean equals(Object other) {
  172. if (!(other instanceof TypePatternList)) return false;
  173. TypePatternList o = (TypePatternList)other;
  174. int len = o.typePatterns.length;
  175. if (len != this.typePatterns.length) return false;
  176. for (int i=0; i<len; i++) {
  177. if (!this.typePatterns[i].equals(o.typePatterns[i])) return false;
  178. }
  179. return true;
  180. }
  181. public int hashCode() {
  182. int result = 41;
  183. for (int i = 0, len = typePatterns.length; i < len; i++) {
  184. result = 37*result + typePatterns[i].hashCode();
  185. }
  186. return result;
  187. }
  188. public static TypePatternList read(DataInputStream s, ISourceContext context) throws IOException {
  189. short len = s.readShort();
  190. TypePattern[] arguments = new TypePattern[len];
  191. for (int i=0; i<len; i++) {
  192. arguments[i] = TypePattern.read(s, context);
  193. }
  194. TypePatternList ret = new TypePatternList(arguments);
  195. ret.readLocation(context, s);
  196. return ret;
  197. }
  198. public void write(DataOutputStream s) throws IOException {
  199. s.writeShort(typePatterns.length);
  200. for (int i=0; i<typePatterns.length; i++) {
  201. typePatterns[i].write(s);
  202. }
  203. writeLocation(s);
  204. }
  205. public TypePattern[] getTypePatterns() {
  206. return typePatterns;
  207. }
  208. }