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.

WildTypePattern.java 49KB

пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 12 година
пре 15 година
пре 12 година
пре 15 година
пре 12 година
пре 15 година
пре 12 година
пре 15 година
пре 12 година
пре 15 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 12 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 14 година
пре 14 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 14 година
пре 15 година
пре 14 година
пре 15 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  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 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. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.Map;
  17. import java.util.StringTokenizer;
  18. import org.aspectj.bridge.IMessage;
  19. import org.aspectj.bridge.ISourceLocation;
  20. import org.aspectj.bridge.Message;
  21. import org.aspectj.bridge.MessageUtil;
  22. import org.aspectj.util.FileUtil;
  23. import org.aspectj.util.FuzzyBoolean;
  24. import org.aspectj.weaver.AjAttribute;
  25. import org.aspectj.weaver.BCException;
  26. import org.aspectj.weaver.BoundedReferenceType;
  27. import org.aspectj.weaver.CompressingDataOutputStream;
  28. import org.aspectj.weaver.IHasPosition;
  29. import org.aspectj.weaver.ISourceContext;
  30. import org.aspectj.weaver.ReferenceType;
  31. import org.aspectj.weaver.ResolvedType;
  32. import org.aspectj.weaver.TypeFactory;
  33. import org.aspectj.weaver.TypeVariable;
  34. import org.aspectj.weaver.TypeVariableReference;
  35. import org.aspectj.weaver.UnresolvedType;
  36. import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
  37. import org.aspectj.weaver.VersionedDataInputStream;
  38. import org.aspectj.weaver.WeaverMessages;
  39. import org.aspectj.weaver.World;
  40. /**
  41. * The PatternParser always creates WildTypePatterns for type patterns in pointcut expressions (apart from *, which is sometimes
  42. * directly turned into TypePattern.ANY). resolveBindings() tries to work out what we've really got and turn it into a type pattern
  43. * that we can use for matching. This will normally be either an ExactTypePattern or a WildTypePattern.
  44. *
  45. * Here's how the process pans out for various generic and parameterized patterns: (see GenericsWildTypePatternResolvingTestCase)
  46. *
  47. * Foo where Foo exists and is generic Parser creates WildTypePattern namePatterns={Foo} resolveBindings resolves Foo to RT(Foo -
  48. * raw) return ExactTypePattern(LFoo;)
  49. *
  50. * Foo<String> where Foo exists and String meets the bounds Parser creates WildTypePattern namePatterns = {Foo},
  51. * typeParameters=WTP{String} resolveBindings resolves typeParameters to ExactTypePattern(String) resolves Foo to RT(Foo) returns
  52. * ExactTypePattern(PFoo<String>; - parameterized)
  53. *
  54. * Foo<Str*> where Foo exists and takes one bound Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{Str*}
  55. * resolveBindings resolves typeParameters to WTP{Str*} resolves Foo to RT(Foo) returns WildTypePattern(name = Foo, typeParameters =
  56. * WTP{Str*} isGeneric=false)
  57. *
  58. * Fo*<String> Parser creates WildTypePattern namePatterns = {Fo*}, typeParameters=WTP{String} resolveBindings resolves
  59. * typeParameters to ETP{String} returns WildTypePattern(name = Fo*, typeParameters = ETP{String} isGeneric=false)
  60. *
  61. *
  62. * Foo<?>
  63. *
  64. * Foo<? extends Number>
  65. *
  66. * Foo<? extends Number+>
  67. *
  68. * Foo<? super Number>
  69. *
  70. */
  71. public class WildTypePattern extends TypePattern {
  72. private static final String GENERIC_WILDCARD_CHARACTER = "?"; // signature of ? is *
  73. private static final String GENERIC_WILDCARD_SIGNATURE_CHARACTER = "*"; // signature of ? is *
  74. private NamePattern[] namePatterns;
  75. private boolean failedResolution = false;
  76. int ellipsisCount;
  77. String[] importedPrefixes;
  78. String[] knownMatches;
  79. int dim;
  80. // SECRETAPI - just for testing, turns off boundschecking temporarily...
  81. public static boolean boundscheckingoff = false;
  82. // these next three are set if the type pattern is constrained by extends or super clauses, in which case the
  83. // namePatterns must have length 1
  84. // TODO AMC: read/write/resolve of these fields
  85. TypePattern upperBound; // extends Foo
  86. TypePattern[] additionalInterfaceBounds; // extends Foo & A,B,C
  87. TypePattern lowerBound; // super Foo
  88. // if we have type parameters, these fields indicate whether we should be a generic type pattern or a parameterized
  89. // type pattern. We can only tell during resolve bindings.
  90. private boolean isGeneric = true;
  91. WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs, TypePatternList typeParams) {
  92. super(includeSubtypes, isVarArgs, typeParams);
  93. this.namePatterns = namePatterns;
  94. this.dim = dim;
  95. ellipsisCount = 0;
  96. for (NamePattern namePattern : namePatterns) {
  97. if (namePattern == NamePattern.ELLIPSIS) {
  98. ellipsisCount++;
  99. }
  100. }
  101. setLocation(namePatterns[0].getSourceContext(), namePatterns[0].getStart(), namePatterns[namePatterns.length - 1].getEnd());
  102. }
  103. public WildTypePattern(List<NamePattern> names, boolean includeSubtypes, int dim) {
  104. this(names.toArray(new NamePattern[0]), includeSubtypes, dim, false, TypePatternList.EMPTY);
  105. }
  106. public WildTypePattern(List<NamePattern> names, boolean includeSubtypes, int dim, int endPos) {
  107. this(names, includeSubtypes, dim);
  108. this.end = endPos;
  109. }
  110. public WildTypePattern(List<NamePattern> names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg) {
  111. this(names, includeSubtypes, dim);
  112. this.end = endPos;
  113. this.isVarArgs = isVarArg;
  114. }
  115. public WildTypePattern(List<NamePattern> names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg, TypePatternList typeParams,
  116. TypePattern upperBound, TypePattern[] additionalInterfaceBounds, TypePattern lowerBound) {
  117. this(names.toArray(new NamePattern[0]), includeSubtypes, dim, isVarArg, typeParams);
  118. this.end = endPos;
  119. this.upperBound = upperBound;
  120. this.lowerBound = lowerBound;
  121. this.additionalInterfaceBounds = additionalInterfaceBounds;
  122. }
  123. public WildTypePattern(List<NamePattern> names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg, TypePatternList typeParams) {
  124. this(names.toArray(new NamePattern[0]), includeSubtypes, dim, isVarArg, typeParams);
  125. this.end = endPos;
  126. }
  127. public NamePattern[] getNamePatterns() {
  128. return namePatterns;
  129. }
  130. public TypePattern getUpperBound() {
  131. return upperBound;
  132. }
  133. public TypePattern getLowerBound() {
  134. return lowerBound;
  135. }
  136. public TypePattern[] getAdditionalIntefaceBounds() {
  137. return additionalInterfaceBounds;
  138. }
  139. // called by parser after parsing a type pattern, must bump dim as well as setting flag
  140. @Override
  141. public void setIsVarArgs(boolean isVarArgs) {
  142. this.isVarArgs = isVarArgs;
  143. if (isVarArgs) {
  144. this.dim += 1;
  145. }
  146. }
  147. /*
  148. * (non-Javadoc)
  149. *
  150. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  151. */
  152. @Override
  153. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  154. if (super.couldEverMatchSameTypesAs(other)) {
  155. return true;
  156. }
  157. // false is necessary but not sufficient
  158. UnresolvedType otherType = other.getExactType();
  159. if (!ResolvedType.isMissing(otherType)) {
  160. if (namePatterns.length > 0) {
  161. if (!namePatterns[0].matches(otherType.getName())) {
  162. return false;
  163. }
  164. }
  165. }
  166. if (other instanceof WildTypePattern) {
  167. WildTypePattern owtp = (WildTypePattern) other;
  168. String mySimpleName = namePatterns[0].maybeGetSimpleName();
  169. String yourSimpleName = owtp.namePatterns[0].maybeGetSimpleName();
  170. if (mySimpleName != null && yourSimpleName != null) {
  171. return (mySimpleName.startsWith(yourSimpleName) || yourSimpleName.startsWith(mySimpleName));
  172. }
  173. }
  174. return true;
  175. }
  176. // XXX inefficient implementation
  177. // we don't know whether $ characters are from nested types, or were
  178. // part of the declared type name (generated code often uses $s in type
  179. // names). More work required on our part to get this right...
  180. public static char[][] splitNames(String s, boolean convertDollar) {
  181. List<char[]> ret = new ArrayList<>();
  182. int startIndex = 0;
  183. while (true) {
  184. int breakIndex = s.indexOf('.', startIndex); // what about /
  185. if (convertDollar && (breakIndex == -1)) {
  186. breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
  187. }
  188. if (breakIndex == -1) {
  189. break;
  190. }
  191. char[] name = s.substring(startIndex, breakIndex).toCharArray();
  192. ret.add(name);
  193. startIndex = breakIndex + 1;
  194. }
  195. ret.add(s.substring(startIndex).toCharArray());
  196. return ret.toArray(new char[ret.size()][]);
  197. }
  198. /**
  199. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(ResolvedType)
  200. */
  201. @Override
  202. protected boolean matchesExactly(ResolvedType type) {
  203. return matchesExactly(type, type);
  204. }
  205. @Override
  206. protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
  207. String targetTypeName = type.getName();
  208. // System.err.println("match: " + targetTypeName + ", " + knownMatches); //Arrays.asList(importedPrefixes));
  209. // Ensure the annotation pattern is resolved
  210. annotationPattern.resolve(type.getWorld());
  211. return matchesExactlyByName(targetTypeName.replaceFirst("(\\[\\])+$", ""), type.isAnonymous(), type.isNested()) && matchesParameters(type, STATIC)
  212. && matchesArray(type)
  213. && matchesBounds(type, STATIC)
  214. && annotationPattern.matches(annotatedType, type.temporaryAnnotationTypes).alwaysTrue();
  215. }
  216. // we've matched against the base (or raw) type, but if this type pattern specifies parameters or
  217. // type variables we need to make sure we match against them too
  218. private boolean matchesParameters(ResolvedType aType, MatchKind staticOrDynamic) {
  219. if (!isGeneric && typeParameters.size() > 0) {
  220. if (!aType.isParameterizedType()) {
  221. return false;
  222. }
  223. // we have to match type parameters
  224. return typeParameters.matches(aType.getResolvedTypeParameters(), staticOrDynamic).alwaysTrue();
  225. }
  226. return true;
  227. }
  228. @Override
  229. protected boolean matchesArray(UnresolvedType type) {
  230. return type.getDimensions() == getDimensions() ||
  231. getDimensions() == 0 && namePatterns.length > 0 && namePatterns[namePatterns.length-1].toString().endsWith("*");
  232. }
  233. // we've matched against the base (or raw) type, but if this type pattern specifies bounds because
  234. // it is a ? extends or ? super deal then we have to match them too.
  235. private boolean matchesBounds(ResolvedType aType, MatchKind staticOrDynamic) {
  236. if (!(aType instanceof BoundedReferenceType)) {
  237. return true;
  238. }
  239. BoundedReferenceType boundedRT = (BoundedReferenceType) aType;
  240. if (upperBound == null && boundedRT.getUpperBound() != null) {
  241. // for upper bound, null can also match against Object - but anything else and we're out.
  242. if (!boundedRT.getUpperBound().getName().equals(UnresolvedType.OBJECT.getName())) {
  243. return false;
  244. }
  245. }
  246. if (lowerBound == null && boundedRT.getLowerBound() != null) {
  247. return false;
  248. }
  249. if (upperBound != null) {
  250. // match ? extends
  251. if (aType.isGenericWildcard() && boundedRT.isSuper()) {
  252. return false;
  253. }
  254. if (boundedRT.getUpperBound() == null) {
  255. return false;
  256. }
  257. return upperBound.matches((ResolvedType) boundedRT.getUpperBound(), staticOrDynamic).alwaysTrue();
  258. }
  259. if (lowerBound != null) {
  260. // match ? super
  261. if (!(boundedRT.isGenericWildcard() && boundedRT.isSuper())) {
  262. return false;
  263. }
  264. return lowerBound.matches((ResolvedType) boundedRT.getLowerBound(), staticOrDynamic).alwaysTrue();
  265. }
  266. return true;
  267. }
  268. /**
  269. * Used in conjunction with checks on 'isStar()' to tell you if this pattern represents '*' or '*[]' which are different !
  270. */
  271. public int getDimensions() {
  272. return dim;
  273. }
  274. @Override
  275. public boolean isArray() {
  276. return dim > 0;
  277. }
  278. /**
  279. * @param targetTypeName
  280. * @return
  281. */
  282. private boolean matchesExactlyByName(String targetTypeName, boolean isAnonymous, boolean isNested) {
  283. // we deal with parameter matching separately...
  284. if (targetTypeName.indexOf('<') != -1) {
  285. targetTypeName = targetTypeName.substring(0, targetTypeName.indexOf('<'));
  286. }
  287. // we deal with bounds matching separately too...
  288. if (targetTypeName.startsWith(GENERIC_WILDCARD_CHARACTER)) {
  289. targetTypeName = GENERIC_WILDCARD_CHARACTER;
  290. }
  291. // XXX hack
  292. if (knownMatches == null && importedPrefixes == null) {
  293. return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
  294. }
  295. // if our pattern is length 1, then known matches are exact matches
  296. // if it's longer than that, then known matches are prefixes of a sort
  297. if (namePatterns.length == 1) {
  298. if (isAnonymous) {
  299. // we've already ruled out "*", and no other name pattern should match an anonymous type
  300. return false;
  301. }
  302. for (String knownMatch : knownMatches) {
  303. if (knownMatch.equals(targetTypeName)) {
  304. return true;
  305. }
  306. }
  307. } else {
  308. for (String knownMatch : knownMatches) {
  309. // String knownPrefix = knownMatches[i] + "$";
  310. // if (targetTypeName.startsWith(knownPrefix)) {
  311. if (targetTypeName.startsWith(knownMatch) && targetTypeName.length() > knownMatch.length()
  312. && targetTypeName.charAt(knownMatch.length()) == '$') {
  313. int pos = lastIndexOfDotOrDollar(knownMatch);
  314. if (innerMatchesExactly(targetTypeName.substring(pos + 1), isAnonymous, isNested)) {
  315. return true;
  316. }
  317. }
  318. }
  319. }
  320. // if any prefixes match, strip the prefix and check that the rest matches
  321. // assumes that prefixes have a dot at the end
  322. for (String prefix : importedPrefixes) {
  323. // System.err.println("prefix match? " + prefix + " to " + targetTypeName);
  324. if (targetTypeName.startsWith(prefix)) {
  325. if (innerMatchesExactly(targetTypeName.substring(prefix.length()), isAnonymous, isNested)) {
  326. return true;
  327. }
  328. }
  329. }
  330. return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
  331. }
  332. private int lastIndexOfDotOrDollar(String string) {
  333. for (int pos = string.length() - 1; pos > -1; pos--) {
  334. char ch = string.charAt(pos);
  335. if (ch == '.' || ch == '$') {
  336. return pos;
  337. }
  338. }
  339. return -1;
  340. }
  341. private boolean innerMatchesExactly(String s, boolean isAnonymous, boolean convertDollar /* isNested */) {
  342. List<char[]> ret = new ArrayList<>();
  343. int startIndex = 0;
  344. while (true) {
  345. int breakIndex = s.indexOf('.', startIndex); // what about /
  346. if (convertDollar && (breakIndex == -1)) {
  347. breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
  348. }
  349. if (breakIndex == -1) {
  350. break;
  351. }
  352. char[] name = s.substring(startIndex, breakIndex).toCharArray();
  353. ret.add(name);
  354. startIndex = breakIndex + 1;
  355. }
  356. ret.add(s.substring(startIndex).toCharArray());
  357. int namesLength = ret.size();
  358. int patternsLength = namePatterns.length;
  359. int namesIndex = 0;
  360. int patternsIndex = 0;
  361. if ((!namePatterns[patternsLength - 1].isAny()) && isAnonymous) {
  362. return false;
  363. }
  364. if (ellipsisCount == 0) {
  365. if (namesLength != patternsLength) {
  366. return false;
  367. }
  368. while (patternsIndex < patternsLength) {
  369. if (!namePatterns[patternsIndex++].matches(ret.get(namesIndex++))) {
  370. return false;
  371. }
  372. }
  373. return true;
  374. } else if (ellipsisCount == 1) {
  375. if (namesLength < patternsLength - 1) {
  376. return false;
  377. }
  378. while (patternsIndex < patternsLength) {
  379. NamePattern p = namePatterns[patternsIndex++];
  380. if (p == NamePattern.ELLIPSIS) {
  381. namesIndex = namesLength - (patternsLength - patternsIndex);
  382. } else {
  383. if (!p.matches(ret.get(namesIndex++))) {
  384. return false;
  385. }
  386. }
  387. }
  388. return true;
  389. } else {
  390. // System.err.print("match(\"" + Arrays.asList(namePatterns) + "\", \"" + Arrays.asList(names) + "\") -> ");
  391. boolean b = outOfStar(namePatterns, ret.toArray(new char[ret.size()][]), 0, 0, patternsLength - ellipsisCount,
  392. namesLength, ellipsisCount);
  393. // System.err.println(b);
  394. return b;
  395. }
  396. }
  397. private static boolean outOfStar(final NamePattern[] pattern, final char[][] target, int pi, int ti, int pLeft, int tLeft,
  398. final int starsLeft) {
  399. if (pLeft > tLeft) {
  400. return false;
  401. }
  402. while (true) {
  403. // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
  404. if (tLeft == 0) {
  405. return true;
  406. }
  407. if (pLeft == 0) {
  408. return (starsLeft > 0);
  409. }
  410. if (pattern[pi] == NamePattern.ELLIPSIS) {
  411. return inStar(pattern, target, pi + 1, ti, pLeft, tLeft, starsLeft - 1);
  412. }
  413. if (!pattern[pi].matches(target[ti])) {
  414. return false;
  415. }
  416. pi++;
  417. ti++;
  418. pLeft--;
  419. tLeft--;
  420. }
  421. }
  422. private static boolean inStar(final NamePattern[] pattern, final char[][] target, int pi, int ti, final int pLeft, int tLeft,
  423. int starsLeft) {
  424. // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
  425. // of course, we probably can't parse multiple ..'s in a row, but this keeps the algorithm
  426. // exactly parallel with that in NamePattern
  427. NamePattern patternChar = pattern[pi];
  428. while (patternChar == NamePattern.ELLIPSIS) {
  429. starsLeft--;
  430. patternChar = pattern[++pi];
  431. }
  432. while (true) {
  433. // invariant: if (tLeft > 0) then (ti < target.length)
  434. if (pLeft > tLeft) {
  435. return false;
  436. }
  437. if (patternChar.matches(target[ti])) {
  438. if (outOfStar(pattern, target, pi + 1, ti + 1, pLeft - 1, tLeft - 1, starsLeft)) {
  439. return true;
  440. }
  441. }
  442. ti++;
  443. tLeft--;
  444. }
  445. }
  446. /**
  447. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(ResolvedType)
  448. */
  449. @Override
  450. public FuzzyBoolean matchesInstanceof(ResolvedType type) {
  451. // XXX hack to let unmatched types just silently remain so
  452. if (maybeGetSimpleName() != null) {
  453. return FuzzyBoolean.NO;
  454. }
  455. type.getWorld().getMessageHandler().handleMessage(
  456. new Message("can't do instanceof matching on patterns with wildcards", IMessage.ERROR, null, getSourceLocation()));
  457. return FuzzyBoolean.NO;
  458. }
  459. public NamePattern extractName() {
  460. if (isIncludeSubtypes() || isVarArgs() || isArray() || (typeParameters.size() > 0)) {
  461. // we can't extract a name, the pattern is something like Foo+ and therefore
  462. // it is not ok to treat Foo as a method name!
  463. return null;
  464. }
  465. // System.err.println("extract from : " + Arrays.asList(namePatterns));
  466. int len = namePatterns.length;
  467. if (len == 1 && !annotationPattern.isAny()) {
  468. return null; // can't extract
  469. }
  470. NamePattern ret = namePatterns[len - 1];
  471. NamePattern[] newNames = new NamePattern[len - 1];
  472. System.arraycopy(namePatterns, 0, newNames, 0, len - 1);
  473. namePatterns = newNames;
  474. // System.err.println(" left : " + Arrays.asList(namePatterns));
  475. return ret;
  476. }
  477. /**
  478. * Method maybeExtractName.
  479. *
  480. * @param string
  481. * @return boolean
  482. */
  483. public boolean maybeExtractName(String string) {
  484. int len = namePatterns.length;
  485. NamePattern ret = namePatterns[len - 1];
  486. String simple = ret.maybeGetSimpleName();
  487. if (simple != null && simple.equals(string)) {
  488. extractName();
  489. return true;
  490. }
  491. return false;
  492. }
  493. /**
  494. * If this type pattern has no '.' or '*' in it, then return a simple string
  495. *
  496. * otherwise, this will return null;
  497. */
  498. public String maybeGetSimpleName() {
  499. if (namePatterns.length == 1) {
  500. return namePatterns[0].maybeGetSimpleName();
  501. }
  502. return null;
  503. }
  504. /**
  505. * If this type pattern has no '*' or '..' in it
  506. */
  507. public String maybeGetCleanName() {
  508. if (namePatterns.length == 0) {
  509. throw new RuntimeException("bad name: " + namePatterns);
  510. }
  511. // System.out.println("get clean: " + this);
  512. StringBuilder buf = new StringBuilder();
  513. for (int i = 0, len = namePatterns.length; i < len; i++) {
  514. NamePattern p = namePatterns[i];
  515. String simpleName = p.maybeGetSimpleName();
  516. if (simpleName == null) {
  517. return null;
  518. }
  519. if (i > 0) {
  520. buf.append(".");
  521. }
  522. buf.append(simpleName);
  523. }
  524. // System.out.println(buf);
  525. return buf.toString();
  526. }
  527. @Override
  528. public TypePattern parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) {
  529. NamePattern[] newNamePatterns = new NamePattern[namePatterns.length];
  530. System.arraycopy(namePatterns, 0, newNamePatterns, 0, namePatterns.length);
  531. if (newNamePatterns.length == 1) {
  532. String simpleName = newNamePatterns[0].maybeGetSimpleName();
  533. if (simpleName != null) {
  534. if (typeVariableMap.containsKey(simpleName)) {
  535. String newName = ((ReferenceType) typeVariableMap.get(simpleName)).getName().replace('$', '.');
  536. StringTokenizer strTok = new StringTokenizer(newName, ".");
  537. newNamePatterns = new NamePattern[strTok.countTokens()];
  538. int index = 0;
  539. while (strTok.hasMoreTokens()) {
  540. newNamePatterns[index++] = new NamePattern(strTok.nextToken());
  541. }
  542. }
  543. }
  544. }
  545. WildTypePattern ret = new WildTypePattern(newNamePatterns, includeSubtypes, dim, isVarArgs, typeParameters
  546. .parameterizeWith(typeVariableMap, w));
  547. ret.annotationPattern = this.annotationPattern.parameterizeWith(typeVariableMap, w);
  548. if (additionalInterfaceBounds == null) {
  549. ret.additionalInterfaceBounds = null;
  550. } else {
  551. ret.additionalInterfaceBounds = new TypePattern[additionalInterfaceBounds.length];
  552. for (int i = 0; i < additionalInterfaceBounds.length; i++) {
  553. ret.additionalInterfaceBounds[i] = additionalInterfaceBounds[i].parameterizeWith(typeVariableMap, w);
  554. }
  555. }
  556. ret.upperBound = upperBound != null ? upperBound.parameterizeWith(typeVariableMap, w) : null;
  557. ret.lowerBound = lowerBound != null ? lowerBound.parameterizeWith(typeVariableMap, w) : null;
  558. ret.isGeneric = isGeneric;
  559. ret.knownMatches = knownMatches;
  560. ret.importedPrefixes = importedPrefixes;
  561. ret.copyLocationFrom(this);
  562. return ret;
  563. }
  564. /**
  565. * Need to determine if I'm really a pattern or a reference to a formal
  566. *
  567. * We may wish to further optimize the case of pattern vs. non-pattern
  568. *
  569. * We will be replaced by what we return
  570. */
  571. @Override
  572. public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  573. if (isNamePatternStar()) {
  574. TypePattern anyPattern = maybeResolveToAnyPattern(scope, bindings, allowBinding, requireExactType);
  575. if (anyPattern != null) {
  576. if (requireExactType) {
  577. scope.getWorld().getMessageHandler().handleMessage(
  578. MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));
  579. return NO;
  580. } else {
  581. return anyPattern;
  582. }
  583. }
  584. }
  585. TypePattern bindingTypePattern = maybeResolveToBindingTypePattern(scope, bindings, allowBinding, requireExactType);
  586. if (bindingTypePattern != null) {
  587. return bindingTypePattern;
  588. }
  589. annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);
  590. // resolve any type parameters
  591. if (typeParameters != null && typeParameters.size() > 0) {
  592. typeParameters.resolveBindings(scope, bindings, allowBinding, requireExactType);
  593. isGeneric = false;
  594. }
  595. // resolve any bounds
  596. if (upperBound != null) {
  597. upperBound = upperBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
  598. }
  599. if (lowerBound != null) {
  600. lowerBound = lowerBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
  601. // amc - additional interface bounds only needed if we support type vars again.
  602. }
  603. String fullyQualifiedName = maybeGetCleanName();
  604. if (fullyQualifiedName != null) {
  605. return resolveBindingsFromFullyQualifiedTypeName(fullyQualifiedName, scope, bindings, allowBinding, requireExactType);
  606. } else {
  607. if (requireExactType) {
  608. scope.getWorld().getMessageHandler().handleMessage(
  609. MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));
  610. return NO;
  611. }
  612. importedPrefixes = scope.getImportedPrefixes();
  613. knownMatches = preMatch(scope.getImportedNames());
  614. return this; // pattern contains wildcards so can't be resolved to an ExactTypePattern...
  615. // XXX need to implement behavior for Lint.invalidWildcardTypeName
  616. }
  617. }
  618. private TypePattern maybeResolveToAnyPattern(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  619. // If there is an annotation specified we have to
  620. // use a special variant of Any TypePattern called
  621. // AnyWithAnnotation
  622. if (annotationPattern == AnnotationTypePattern.ANY) {
  623. if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null
  624. && (additionalInterfaceBounds == null || additionalInterfaceBounds.length == 0)) { // pr72531
  625. return TypePattern.ANY; // ??? loses source location
  626. }
  627. } else if (!isVarArgs) {
  628. annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);
  629. AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);
  630. ret.setLocation(sourceContext, start, end);
  631. return ret;
  632. }
  633. return null; // can't resolve to a simple "any" pattern
  634. }
  635. private TypePattern maybeResolveToBindingTypePattern(IScope scope, Bindings bindings, boolean allowBinding,
  636. boolean requireExactType) {
  637. String simpleName = maybeGetSimpleName();
  638. if (simpleName != null) {
  639. FormalBinding formalBinding = scope.lookupFormal(simpleName);
  640. if (formalBinding != null) {
  641. if (bindings == null) {
  642. scope.message(IMessage.ERROR, this, "negation doesn't allow binding");
  643. return this;
  644. }
  645. if (!allowBinding) {
  646. scope.message(IMessage.ERROR, this, "name binding only allowed in target, this, and args pcds");
  647. return this;
  648. }
  649. BindingTypePattern binding = new BindingTypePattern(formalBinding, isVarArgs);
  650. binding.copyLocationFrom(this);
  651. bindings.register(binding, scope);
  652. return binding;
  653. }
  654. }
  655. return null; // not possible to resolve to a binding type pattern
  656. }
  657. private TypePattern resolveBindingsFromFullyQualifiedTypeName(String fullyQualifiedName, IScope scope, Bindings bindings,
  658. boolean allowBinding, boolean requireExactType) {
  659. String originalName = fullyQualifiedName;
  660. ResolvedType resolvedTypeInTheWorld = null;
  661. UnresolvedType type;
  662. // System.out.println("resolve: " + cleanName);
  663. // ??? this loop has too many inefficiencies to count
  664. resolvedTypeInTheWorld = lookupTypeInWorldIncludingPrefixes(scope.getWorld(), fullyQualifiedName, scope
  665. .getImportedPrefixes());
  666. if (resolvedTypeInTheWorld.isGenericWildcard()) {
  667. type = resolvedTypeInTheWorld;
  668. } else {
  669. type = lookupTypeInScope(scope, fullyQualifiedName, this);
  670. }
  671. if ((type instanceof ResolvedType) && ((ResolvedType) type).isMissing()) {
  672. return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding,
  673. requireExactType);
  674. } else {
  675. return resolveBindingsForExactType(scope, type, fullyQualifiedName, requireExactType);
  676. }
  677. }
  678. private UnresolvedType lookupTypeInScope(IScope scope, String typeName, IHasPosition location) {
  679. UnresolvedType type = null;
  680. while (ResolvedType.isMissing(type = scope.lookupType(typeName, location))) {
  681. int lastDot = typeName.lastIndexOf('.');
  682. if (lastDot == -1) {
  683. break;
  684. }
  685. typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);
  686. }
  687. return type;
  688. }
  689. /**
  690. * Searches the world for the ResolvedType with the given typeName. If one isn't found then for each of the supplied prefixes,
  691. * it prepends the typeName with the prefix and searches the world for the ResolvedType with this new name. If one still isn't
  692. * found then a MissingResolvedTypeWithKnownSignature is returned with the originally requested typeName (this ensures the
  693. * typeName makes sense).
  694. */
  695. private ResolvedType lookupTypeInWorldIncludingPrefixes(World world, String typeName, String[] prefixes) {
  696. ResolvedType ret = lookupTypeInWorld(world, typeName);
  697. if (!ret.isMissing()) {
  698. return ret;
  699. }
  700. ResolvedType retWithPrefix = ret;
  701. int counter = 0;
  702. while (retWithPrefix.isMissing() && (counter < prefixes.length)) {
  703. retWithPrefix = lookupTypeInWorld(world, prefixes[counter] + typeName);
  704. counter++;
  705. }
  706. if (!retWithPrefix.isMissing()) {
  707. return retWithPrefix;
  708. }
  709. return ret;
  710. }
  711. private ResolvedType lookupTypeInWorld(World world, String typeName) {
  712. UnresolvedType ut = UnresolvedType.forName(typeName);
  713. ResolvedType ret = world.resolve(ut, true);
  714. while (ret.isMissing()) {
  715. int lastDot = typeName.lastIndexOf('.');
  716. if (lastDot == -1) {
  717. break;
  718. }
  719. typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);
  720. ret = world.resolve(UnresolvedType.forName(typeName), true);
  721. }
  722. return ret;
  723. }
  724. private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName,
  725. boolean requireExactType) {
  726. TypePattern ret = null;
  727. if (aType.isTypeVariableReference()) {
  728. // we have to set the bounds on it based on the bounds of this pattern
  729. ret = resolveBindingsForTypeVariable(scope, (UnresolvedTypeVariableReferenceType) aType);
  730. } else if (typeParameters.size() > 0) {
  731. ret = resolveParameterizedType(scope, aType, requireExactType);
  732. } else if (upperBound != null || lowerBound != null) {
  733. // this must be a generic wildcard with bounds
  734. ret = resolveGenericWildcard(scope, aType);
  735. } else {
  736. if (dim != 0) {
  737. aType = UnresolvedType.makeArray(aType, dim);
  738. }
  739. ret = new ExactTypePattern(aType, includeSubtypes, isVarArgs, typeParameters);
  740. }
  741. ret.setAnnotationTypePattern(annotationPattern);
  742. ret.copyLocationFrom(this);
  743. return ret;
  744. }
  745. private TypePattern resolveGenericWildcard(IScope scope, UnresolvedType aType) {
  746. if (!aType.getSignature().equals(GENERIC_WILDCARD_SIGNATURE_CHARACTER)) {
  747. throw new IllegalStateException("Can only have bounds for a generic wildcard");
  748. }
  749. boolean canBeExact = true;
  750. if ((upperBound != null) && ResolvedType.isMissing(upperBound.getExactType())) {
  751. canBeExact = false;
  752. }
  753. if ((lowerBound != null) && ResolvedType.isMissing(lowerBound.getExactType())) {
  754. canBeExact = false;
  755. }
  756. if (canBeExact) {
  757. ResolvedType type = null;
  758. if (upperBound != null) {
  759. if (upperBound.isIncludeSubtypes()) {
  760. canBeExact = false;
  761. } else {
  762. ReferenceType upper = (ReferenceType) upperBound.getExactType().resolve(scope.getWorld());
  763. type = new BoundedReferenceType(upper, true, scope.getWorld());
  764. }
  765. } else {
  766. if (lowerBound.isIncludeSubtypes()) {
  767. canBeExact = false;
  768. } else {
  769. ReferenceType lower = (ReferenceType) lowerBound.getExactType().resolve(scope.getWorld());
  770. type = new BoundedReferenceType(lower, false, scope.getWorld());
  771. }
  772. }
  773. if (canBeExact) {
  774. // might have changed if we find out include subtypes is set on one of the bounds...
  775. return new ExactTypePattern(type, includeSubtypes, isVarArgs, typeParameters);
  776. }
  777. }
  778. // we weren't able to resolve to an exact type pattern...
  779. // leave as wild type pattern
  780. importedPrefixes = scope.getImportedPrefixes();
  781. knownMatches = preMatch(scope.getImportedNames());
  782. return this;
  783. }
  784. private TypePattern resolveParameterizedType(IScope scope, UnresolvedType aType, boolean requireExactType) {
  785. ResolvedType rt = aType.resolve(scope.getWorld());
  786. if (!verifyTypeParameters(rt, scope, requireExactType)) {
  787. return TypePattern.NO; // messages already isued
  788. }
  789. // Only if the type is exact *and* the type parameters are exact should we create an
  790. // ExactTypePattern for this WildTypePattern
  791. if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
  792. TypePattern[] typePats = typeParameters.getTypePatterns();
  793. UnresolvedType[] typeParameterTypes = new UnresolvedType[typePats.length];
  794. for (int i = 0; i < typeParameterTypes.length; i++) {
  795. typeParameterTypes[i] = ((ExactTypePattern) typePats[i]).getExactType();
  796. }
  797. // rt could be a parameterized type 156058
  798. if (rt.isParameterizedType()) {
  799. rt = rt.getGenericType();
  800. }
  801. ResolvedType type = TypeFactory.createParameterizedType(rt, typeParameterTypes, scope.getWorld());
  802. if (isGeneric) {
  803. type = type.getGenericType();
  804. }
  805. // UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes);
  806. // UnresolvedType type = scope.getWorld().resolve(tx,true);
  807. if (dim != 0) {
  808. type = ResolvedType.makeArray(type, dim);
  809. }
  810. return new ExactTypePattern(type, includeSubtypes, isVarArgs, typeParameters);
  811. } else {
  812. // AMC... just leave it as a wild type pattern then?
  813. importedPrefixes = scope.getImportedPrefixes();
  814. knownMatches = preMatch(scope.getImportedNames());
  815. return this;
  816. }
  817. }
  818. private TypePattern resolveBindingsForMissingType(ResolvedType typeFoundInWholeWorldSearch, String nameWeLookedFor,
  819. IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  820. if (requireExactType) {
  821. if (!allowBinding) {
  822. scope.getWorld().getMessageHandler().handleMessage(
  823. MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_BIND_TYPE, nameWeLookedFor),
  824. getSourceLocation()));
  825. } else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
  826. scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
  827. }
  828. return NO;
  829. } else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
  830. // Only put the lint warning out if we can't find it in the world
  831. if (typeFoundInWholeWorldSearch.isMissing()) {
  832. scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
  833. this.failedResolution = true;
  834. }
  835. }
  836. importedPrefixes = scope.getImportedPrefixes();
  837. knownMatches = preMatch(scope.getImportedNames());
  838. return this;
  839. }
  840. /**
  841. * We resolved the type to a type variable declared in the pointcut designator. Now we have to create either an exact type
  842. * pattern or a wild type pattern for it, with upper and lower bounds set accordingly. XXX none of this stuff gets serialized
  843. * yet
  844. *
  845. * @param scope
  846. * @param tvrType
  847. * @return
  848. */
  849. private TypePattern resolveBindingsForTypeVariable(IScope scope, UnresolvedTypeVariableReferenceType tvrType) {
  850. Bindings emptyBindings = new Bindings(0);
  851. if (upperBound != null) {
  852. upperBound = upperBound.resolveBindings(scope, emptyBindings, false, false);
  853. }
  854. if (lowerBound != null) {
  855. lowerBound = lowerBound.resolveBindings(scope, emptyBindings, false, false);
  856. }
  857. if (additionalInterfaceBounds != null) {
  858. TypePattern[] resolvedIfBounds = new TypePattern[additionalInterfaceBounds.length];
  859. for (int i = 0; i < resolvedIfBounds.length; i++) {
  860. resolvedIfBounds[i] = additionalInterfaceBounds[i].resolveBindings(scope, emptyBindings, false, false);
  861. }
  862. additionalInterfaceBounds = resolvedIfBounds;
  863. }
  864. if (upperBound == null && lowerBound == null && additionalInterfaceBounds == null) {
  865. // no bounds to worry about...
  866. ResolvedType rType = tvrType.resolve(scope.getWorld());
  867. if (dim != 0) {
  868. rType = ResolvedType.makeArray(rType, dim);
  869. }
  870. return new ExactTypePattern(rType, includeSubtypes, isVarArgs, typeParameters);
  871. } else {
  872. // we have to set bounds on the TypeVariable held by tvrType before resolving it
  873. boolean canCreateExactTypePattern = true;
  874. if (upperBound != null && ResolvedType.isMissing(upperBound.getExactType())) {
  875. canCreateExactTypePattern = false;
  876. }
  877. if (lowerBound != null && ResolvedType.isMissing(lowerBound.getExactType())) {
  878. canCreateExactTypePattern = false;
  879. }
  880. if (additionalInterfaceBounds != null) {
  881. for (TypePattern additionalInterfaceBound : additionalInterfaceBounds) {
  882. if (ResolvedType.isMissing(additionalInterfaceBound.getExactType())) {
  883. canCreateExactTypePattern = false;
  884. }
  885. }
  886. }
  887. if (canCreateExactTypePattern) {
  888. TypeVariable tv = tvrType.getTypeVariable();
  889. if (upperBound != null) {
  890. tv.setSuperclass(upperBound.getExactType());
  891. }
  892. if (additionalInterfaceBounds != null) {
  893. UnresolvedType[] ifBounds = new UnresolvedType[additionalInterfaceBounds.length];
  894. for (int i = 0; i < ifBounds.length; i++) {
  895. ifBounds[i] = additionalInterfaceBounds[i].getExactType();
  896. }
  897. tv.setAdditionalInterfaceBounds(ifBounds);
  898. }
  899. ResolvedType rType = tvrType.resolve(scope.getWorld());
  900. if (dim != 0) {
  901. rType = ResolvedType.makeArray(rType, dim);
  902. }
  903. return new ExactTypePattern(rType, includeSubtypes, isVarArgs, typeParameters);
  904. }
  905. return this; // leave as wild type pattern then
  906. }
  907. }
  908. /**
  909. * When this method is called, we have resolved the base type to an exact type. We also have a set of type patterns for the
  910. * parameters. Time to perform some basic checks: - can the base type be parameterized? (is it generic) - can the type parameter
  911. * pattern list match the number of parameters on the base type - do all parameter patterns meet the bounds of the respective
  912. * type variables If any of these checks fail, a warning message is issued and we return false.
  913. *
  914. * @return
  915. */
  916. private boolean verifyTypeParameters(ResolvedType baseType, IScope scope, boolean requireExactType) {
  917. ResolvedType genericType = baseType.getGenericType();
  918. if (genericType == null) {
  919. // issue message "does not match because baseType.getName() is not generic"
  920. scope.message(MessageUtil.warn(WeaverMessages.format(WeaverMessages.NOT_A_GENERIC_TYPE, baseType.getName()),
  921. getSourceLocation()));
  922. return false;
  923. }
  924. int minRequiredTypeParameters = typeParameters.size();
  925. boolean foundEllipsis = false;
  926. TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
  927. for (TypePattern typeParamPattern : typeParamPatterns) {
  928. if (typeParamPattern instanceof WildTypePattern) {
  929. WildTypePattern wtp = (WildTypePattern) typeParamPattern;
  930. if (wtp.ellipsisCount > 0) {
  931. foundEllipsis = true;
  932. minRequiredTypeParameters--;
  933. }
  934. }
  935. }
  936. TypeVariable[] tvs = genericType.getTypeVariables();
  937. if ((tvs.length < minRequiredTypeParameters) || (!foundEllipsis && minRequiredTypeParameters != tvs.length)) {
  938. // issue message "does not match because wrong no of type params"
  939. String msg = WeaverMessages.format(WeaverMessages.INCORRECT_NUMBER_OF_TYPE_ARGUMENTS, genericType.getName(),
  940. tvs.length);
  941. if (requireExactType) {
  942. scope.message(MessageUtil.error(msg, getSourceLocation()));
  943. } else {
  944. scope.message(MessageUtil.warn(msg, getSourceLocation()));
  945. }
  946. return false;
  947. }
  948. // now check that each typeParameter pattern, if exact, matches the bounds
  949. // of the type variable.
  950. // pr133307 - delay verification until type binding completion, these next few lines replace
  951. // the call to checkBoundsOK
  952. if (!boundscheckingoff) {
  953. VerifyBoundsForTypePattern verification = new VerifyBoundsForTypePattern(scope, genericType, requireExactType,
  954. typeParameters, getSourceLocation());
  955. scope.getWorld().getCrosscuttingMembersSet().recordNecessaryCheck(verification);
  956. }
  957. // return checkBoundsOK(scope,genericType,requireExactType);
  958. return true;
  959. }
  960. /**
  961. * By capturing the verification in this class, rather than performing it in verifyTypeParameters(), we can cope with situations
  962. * where the interactions between generics and declare parents would otherwise cause us problems. For example, if verifying as
  963. * we go along we may report a problem which would have been fixed by a declare parents that we haven't looked at yet. If we
  964. * create and store a verification object, we can verify this later when the type system is considered 'complete'
  965. */
  966. static class VerifyBoundsForTypePattern implements IVerificationRequired {
  967. private final IScope scope;
  968. private final ResolvedType genericType;
  969. private final boolean requireExactType;
  970. private TypePatternList typeParameters = TypePatternList.EMPTY;
  971. private final ISourceLocation sLoc;
  972. public VerifyBoundsForTypePattern(IScope scope, ResolvedType genericType, boolean requireExactType,
  973. TypePatternList typeParameters, ISourceLocation sLoc) {
  974. this.scope = scope;
  975. this.genericType = genericType;
  976. this.requireExactType = requireExactType;
  977. this.typeParameters = typeParameters;
  978. this.sLoc = sLoc;
  979. }
  980. public void verify() {
  981. TypeVariable[] tvs = genericType.getTypeVariables();
  982. TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
  983. if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
  984. for (int i = 0; i < tvs.length; i++) {
  985. UnresolvedType ut = typeParamPatterns[i].getExactType();
  986. boolean continueCheck = true;
  987. // FIXME asc dont like this but ok temporary measure. If the type parameter
  988. // is itself a type variable (from the generic aspect) then assume it'll be
  989. // ok... (see pr112105) Want to break this? Run GenericAspectK test.
  990. if (ut.isTypeVariableReference()) {
  991. continueCheck = false;
  992. }
  993. // System.err.println("Verifying "+ut.getName()+" meets bounds for "+tvs[i]);
  994. if (continueCheck && !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
  995. // issue message that type parameter does not meet specification
  996. String parameterName = ut.getName();
  997. if (ut.isTypeVariableReference()) {
  998. parameterName = ((TypeVariableReference) ut).getTypeVariable().getDisplayName();
  999. }
  1000. String msg = WeaverMessages.format(WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS, parameterName,
  1001. i + 1, tvs[i].getDisplayName(), genericType.getName());
  1002. if (requireExactType) {
  1003. scope.message(MessageUtil.error(msg, sLoc));
  1004. } else {
  1005. scope.message(MessageUtil.warn(msg, sLoc));
  1006. }
  1007. }
  1008. }
  1009. }
  1010. }
  1011. }
  1012. // pr133307 - moved to verification object
  1013. // public boolean checkBoundsOK(IScope scope,ResolvedType genericType,boolean requireExactType) {
  1014. // if (boundscheckingoff) return true;
  1015. // TypeVariable[] tvs = genericType.getTypeVariables();
  1016. // TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
  1017. // if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
  1018. // for (int i = 0; i < tvs.length; i++) {
  1019. // UnresolvedType ut = typeParamPatterns[i].getExactType();
  1020. // boolean continueCheck = true;
  1021. // // FIXME asc dont like this but ok temporary measure. If the type parameter
  1022. // // is itself a type variable (from the generic aspect) then assume it'll be
  1023. // // ok... (see pr112105) Want to break this? Run GenericAspectK test.
  1024. // if (ut.isTypeVariableReference()) {
  1025. // continueCheck = false;
  1026. // }
  1027. //
  1028. // if (continueCheck &&
  1029. // !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
  1030. // // issue message that type parameter does not meet specification
  1031. // String parameterName = ut.getName();
  1032. // if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
  1033. // String msg =
  1034. // WeaverMessages.format(
  1035. // WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
  1036. // parameterName,
  1037. // new Integer(i+1),
  1038. // tvs[i].getDisplayName(),
  1039. // genericType.getName());
  1040. // if (requireExactType) scope.message(MessageUtil.error(msg,getSourceLocation()));
  1041. // else scope.message(MessageUtil.warn(msg,getSourceLocation()));
  1042. // return false;
  1043. // }
  1044. // }
  1045. // }
  1046. // return true;
  1047. // }
  1048. @Override
  1049. public boolean isStar() {
  1050. boolean annPatternStar = annotationPattern == AnnotationTypePattern.ANY;
  1051. return (isNamePatternStar() && annPatternStar && dim == 0);
  1052. }
  1053. private boolean isNamePatternStar() {
  1054. return namePatterns.length == 1 && namePatterns[0].isAny();
  1055. }
  1056. /**
  1057. * @return those possible matches which I match exactly the last element of
  1058. */
  1059. private String[] preMatch(String[] possibleMatches) {
  1060. // if (namePatterns.length != 1) return CollectionUtil.NO_STRINGS;
  1061. List<String> ret = new ArrayList<>();
  1062. for (String possibleMatch : possibleMatches) {
  1063. char[][] names = splitNames(possibleMatch, true); // ??? not most efficient
  1064. if (namePatterns[0].matches(names[names.length - 1])) {
  1065. ret.add(possibleMatch);
  1066. continue;
  1067. }
  1068. if (possibleMatch.contains("$")) {
  1069. names = splitNames(possibleMatch, false); // ??? not most efficient
  1070. if (namePatterns[0].matches(names[names.length - 1])) {
  1071. ret.add(possibleMatch);
  1072. }
  1073. }
  1074. }
  1075. return ret.toArray(new String[0]);
  1076. }
  1077. // public void postRead(ResolvedType enclosingType) {
  1078. // this.importedPrefixes = enclosingType.getImportedPrefixes();
  1079. // this.knownNames = prematch(enclosingType.getImportedNames());
  1080. // }
  1081. @Override
  1082. public String toString() {
  1083. StringBuilder buf = new StringBuilder();
  1084. if (annotationPattern != AnnotationTypePattern.ANY) {
  1085. buf.append('(');
  1086. buf.append(annotationPattern);
  1087. buf.append(' ');
  1088. }
  1089. for (int i = 0, len = namePatterns.length; i < len; i++) {
  1090. NamePattern name = namePatterns[i];
  1091. if (name == null) {
  1092. buf.append(".");
  1093. } else {
  1094. if (i > 0) {
  1095. buf.append(".");
  1096. }
  1097. buf.append(name);
  1098. }
  1099. }
  1100. if (upperBound != null) {
  1101. buf.append(" extends ");
  1102. buf.append(upperBound);
  1103. }
  1104. if (lowerBound != null) {
  1105. buf.append(" super ");
  1106. buf.append(lowerBound);
  1107. }
  1108. if (typeParameters != null && typeParameters.size() != 0) {
  1109. buf.append("<");
  1110. buf.append(typeParameters.toString());
  1111. buf.append(">");
  1112. }
  1113. if (includeSubtypes) {
  1114. buf.append('+');
  1115. }
  1116. for (int i = 0; i < getDimensions(); i++) {
  1117. buf.append("[]");
  1118. }
  1119. if (isVarArgs) {
  1120. buf.append("...");
  1121. }
  1122. if (annotationPattern != AnnotationTypePattern.ANY) {
  1123. buf.append(')');
  1124. }
  1125. return buf.toString();
  1126. }
  1127. @Override
  1128. public boolean equals(Object other) {
  1129. if (!(other instanceof WildTypePattern)) {
  1130. return false;
  1131. }
  1132. WildTypePattern o = (WildTypePattern) other;
  1133. int len = o.namePatterns.length;
  1134. if (len != this.namePatterns.length) {
  1135. return false;
  1136. }
  1137. if (this.includeSubtypes != o.includeSubtypes) {
  1138. return false;
  1139. }
  1140. if (this.dim != o.dim) {
  1141. return false;
  1142. }
  1143. if (this.isVarArgs != o.isVarArgs) {
  1144. return false;
  1145. }
  1146. if (this.upperBound != null) {
  1147. if (o.upperBound == null) {
  1148. return false;
  1149. }
  1150. if (!this.upperBound.equals(o.upperBound)) {
  1151. return false;
  1152. }
  1153. } else {
  1154. if (o.upperBound != null) {
  1155. return false;
  1156. }
  1157. }
  1158. if (this.lowerBound != null) {
  1159. if (o.lowerBound == null) {
  1160. return false;
  1161. }
  1162. if (!this.lowerBound.equals(o.lowerBound)) {
  1163. return false;
  1164. }
  1165. } else {
  1166. if (o.lowerBound != null) {
  1167. return false;
  1168. }
  1169. }
  1170. if (!typeParameters.equals(o.typeParameters)) {
  1171. return false;
  1172. }
  1173. for (int i = 0; i < len; i++) {
  1174. if (!o.namePatterns[i].equals(this.namePatterns[i])) {
  1175. return false;
  1176. }
  1177. }
  1178. return (o.annotationPattern.equals(this.annotationPattern));
  1179. }
  1180. @Override
  1181. public int hashCode() {
  1182. int result = 17;
  1183. for (NamePattern namePattern : namePatterns) {
  1184. result = 37 * result + namePattern.hashCode();
  1185. }
  1186. result = 37 * result + (includeSubtypes ? 1 : 0);
  1187. result = 37 * result + dim;
  1188. result = 37 * result + (isVarArgs ? 1 : 0);
  1189. result = 37 * result + annotationPattern.hashCode();
  1190. result = 37 * result + typeParameters.hashCode();
  1191. if (upperBound != null) {
  1192. result = 37 * result + upperBound.hashCode();
  1193. }
  1194. if (lowerBound != null) {
  1195. result = 37 * result + lowerBound.hashCode();
  1196. }
  1197. return result;
  1198. }
  1199. private static final byte VERSION = 1; // rev on change
  1200. @Override
  1201. public void write(CompressingDataOutputStream s) throws IOException {
  1202. s.writeByte(TypePattern.WILD);
  1203. s.writeByte(VERSION);
  1204. s.writeShort(namePatterns.length);
  1205. for (NamePattern namePattern : namePatterns) {
  1206. namePattern.write(s);
  1207. }
  1208. s.writeBoolean(includeSubtypes);
  1209. s.writeInt(dim);
  1210. s.writeBoolean(isVarArgs);
  1211. typeParameters.write(s); // ! change from M2
  1212. // ??? storing this information with every type pattern is wasteful of .class
  1213. // file size. Storing it on enclosing types would be more efficient
  1214. FileUtil.writeStringArray(knownMatches, s);
  1215. FileUtil.writeStringArray(importedPrefixes, s);
  1216. writeLocation(s);
  1217. annotationPattern.write(s);
  1218. // generics info, new in M3
  1219. s.writeBoolean(isGeneric);
  1220. s.writeBoolean(upperBound != null);
  1221. if (upperBound != null) {
  1222. upperBound.write(s);
  1223. }
  1224. s.writeBoolean(lowerBound != null);
  1225. if (lowerBound != null) {
  1226. lowerBound.write(s);
  1227. }
  1228. s.writeInt(additionalInterfaceBounds == null ? 0 : additionalInterfaceBounds.length);
  1229. if (additionalInterfaceBounds != null) {
  1230. for (TypePattern additionalInterfaceBound : additionalInterfaceBounds) {
  1231. additionalInterfaceBound.write(s);
  1232. }
  1233. }
  1234. }
  1235. public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  1236. if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  1237. return readTypePattern150(s, context);
  1238. } else {
  1239. return readTypePatternOldStyle(s, context);
  1240. }
  1241. }
  1242. public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
  1243. byte version = s.readByte();
  1244. if (version > VERSION) {
  1245. throw new BCException("WildTypePattern was written by a more recent version of AspectJ, cannot read");
  1246. }
  1247. int len = s.readShort();
  1248. NamePattern[] namePatterns = new NamePattern[len];
  1249. for (int i = 0; i < len; i++) {
  1250. namePatterns[i] = NamePattern.read(s);
  1251. }
  1252. boolean includeSubtypes = s.readBoolean();
  1253. int dim = s.readInt();
  1254. boolean varArg = s.readBoolean();
  1255. TypePatternList typeParams = TypePatternList.read(s, context);
  1256. WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, varArg, typeParams);
  1257. ret.knownMatches = FileUtil.readStringArray(s);
  1258. ret.importedPrefixes = FileUtil.readStringArray(s);
  1259. ret.readLocation(context, s);
  1260. ret.setAnnotationTypePattern(AnnotationTypePattern.read(s, context));
  1261. // generics info, new in M3
  1262. ret.isGeneric = s.readBoolean();
  1263. if (s.readBoolean()) {
  1264. ret.upperBound = TypePattern.read(s, context);
  1265. }
  1266. if (s.readBoolean()) {
  1267. ret.lowerBound = TypePattern.read(s, context);
  1268. }
  1269. int numIfBounds = s.readInt();
  1270. if (numIfBounds > 0) {
  1271. ret.additionalInterfaceBounds = new TypePattern[numIfBounds];
  1272. for (int i = 0; i < numIfBounds; i++) {
  1273. ret.additionalInterfaceBounds[i] = TypePattern.read(s, context);
  1274. }
  1275. }
  1276. return ret;
  1277. }
  1278. public static TypePattern readTypePatternOldStyle(VersionedDataInputStream s, ISourceContext context) throws IOException {
  1279. int len = s.readShort();
  1280. NamePattern[] namePatterns = new NamePattern[len];
  1281. for (int i = 0; i < len; i++) {
  1282. namePatterns[i] = NamePattern.read(s);
  1283. }
  1284. boolean includeSubtypes = s.readBoolean();
  1285. int dim = s.readInt();
  1286. WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, false, null);
  1287. ret.knownMatches = FileUtil.readStringArray(s);
  1288. ret.importedPrefixes = FileUtil.readStringArray(s);
  1289. ret.readLocation(context, s);
  1290. return ret;
  1291. }
  1292. @Override
  1293. public Object accept(PatternNodeVisitor visitor, Object data) {
  1294. return visitor.visit(this, data);
  1295. }
  1296. public boolean hasFailedResolution() {
  1297. return failedResolution;
  1298. }
  1299. }