Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

TypePatternList.java 16KB

před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 9 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 9 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 14 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
před 15 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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 org.aspectj.bridge.ISourceLocation;
  18. import org.aspectj.util.FuzzyBoolean;
  19. import org.aspectj.weaver.CompressingDataOutputStream;
  20. import org.aspectj.weaver.ISourceContext;
  21. import org.aspectj.weaver.IntMap;
  22. import org.aspectj.weaver.ResolvableTypeList;
  23. import org.aspectj.weaver.ResolvedType;
  24. import org.aspectj.weaver.UnresolvedType;
  25. import org.aspectj.weaver.VersionedDataInputStream;
  26. import org.aspectj.weaver.World;
  27. public class TypePatternList extends PatternNode {
  28. private TypePattern[] typePatterns;
  29. int ellipsisCount = 0;
  30. public static final TypePatternList EMPTY = new TypePatternList(new TypePattern[] {});
  31. public static final TypePatternList ANY = new TypePatternList(new TypePattern[] { new EllipsisTypePattern() }); // can't use
  32. // TypePattern.ELLIPSIS
  33. // because of
  34. // circular
  35. // static
  36. // dependency
  37. // that
  38. // introduces
  39. public TypePatternList() {
  40. typePatterns = new TypePattern[0];
  41. ellipsisCount = 0;
  42. }
  43. public TypePatternList(TypePattern[] arguments) {
  44. this.typePatterns = arguments;
  45. for (TypePattern argument : arguments) {
  46. if (argument == TypePattern.ELLIPSIS) {
  47. ellipsisCount++;
  48. }
  49. }
  50. }
  51. public TypePatternList(List<TypePattern> l) {
  52. this(l.toArray(new TypePattern[0]));
  53. }
  54. public int size() {
  55. return typePatterns.length;
  56. }
  57. public TypePattern get(int index) {
  58. return typePatterns[index];
  59. }
  60. @Override
  61. public String toString() {
  62. StringBuilder buf = new StringBuilder();
  63. buf.append("(");
  64. for (int i = 0, len = typePatterns.length; i < len; i++) {
  65. TypePattern type = typePatterns[i];
  66. if (i > 0) {
  67. buf.append(", ");
  68. }
  69. if (type == TypePattern.ELLIPSIS) {
  70. buf.append("..");
  71. } else {
  72. buf.append(type.toString());
  73. }
  74. }
  75. buf.append(")");
  76. return buf.toString();
  77. }
  78. /*
  79. * return true iff this pattern could ever match a signature with the given number of parameters
  80. */
  81. public boolean canMatchSignatureWithNParameters(int numParams) {
  82. if (ellipsisCount == 0) {
  83. return numParams == size();
  84. } else {
  85. return (size() - ellipsisCount) <= numParams;
  86. }
  87. }
  88. public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
  89. return matches(types, kind, null);
  90. }
  91. // XXX shares much code with WildTypePattern and with NamePattern
  92. /**
  93. * When called with TypePattern.STATIC this will always return either FuzzyBoolean.YES or FuzzyBoolean.NO.
  94. *
  95. * When called with TypePattern.DYNAMIC this could return MAYBE if at runtime it would be possible for arguments of the given
  96. * static types to dynamically match this, but it is not known for certain.
  97. *
  98. * This method will never return FuzzyBoolean.NEVER
  99. */
  100. public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  101. int nameLength = types.length;
  102. int patternLength = typePatterns.length;
  103. int nameIndex = 0;
  104. int patternIndex = 0;
  105. if (ellipsisCount == 0) {
  106. if (nameLength != patternLength) {
  107. return FuzzyBoolean.NO;
  108. }
  109. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  110. while (patternIndex < patternLength) {
  111. ResolvedType t = types[nameIndex];
  112. FuzzyBoolean ret = null;
  113. try {
  114. if (parameterAnnotations != null) {
  115. t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
  116. }
  117. ret = typePatterns[patternIndex].matches(t, kind);
  118. } finally {
  119. t.temporaryAnnotationTypes = null;
  120. }
  121. patternIndex++;
  122. nameIndex++;
  123. if (ret == FuzzyBoolean.NO) {
  124. return ret;
  125. }
  126. if (ret == FuzzyBoolean.MAYBE) {
  127. finalReturn = ret;
  128. }
  129. }
  130. return finalReturn;
  131. } else if (ellipsisCount == 1) {
  132. if (nameLength < patternLength - 1) {
  133. return FuzzyBoolean.NO;
  134. }
  135. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  136. while (patternIndex < patternLength) {
  137. TypePattern p = typePatterns[patternIndex++];
  138. if (p == TypePattern.ELLIPSIS) {
  139. nameIndex = nameLength - (patternLength - patternIndex);
  140. } else {
  141. ResolvedType t = types[nameIndex];
  142. FuzzyBoolean ret = null;
  143. try {
  144. if (parameterAnnotations != null) {
  145. t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
  146. }
  147. ret = p.matches(t, kind);
  148. } finally {
  149. t.temporaryAnnotationTypes = null;
  150. }
  151. nameIndex++;
  152. if (ret == FuzzyBoolean.NO) {
  153. return ret;
  154. }
  155. if (ret == FuzzyBoolean.MAYBE) {
  156. finalReturn = ret;
  157. }
  158. }
  159. }
  160. return finalReturn;
  161. } else {
  162. // System.err.print("match(" + arguments + ", " + types + ") -> ");
  163. FuzzyBoolean b = outOfStar(typePatterns, types, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind,
  164. parameterAnnotations);
  165. // System.err.println(b);
  166. return b;
  167. }
  168. }
  169. private static FuzzyBoolean outOfStar(final TypePattern[] pattern, final ResolvedType[] target, int pi, int ti, int pLeft,
  170. int tLeft, final int starsLeft, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  171. if (pLeft > tLeft) {
  172. return FuzzyBoolean.NO;
  173. }
  174. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  175. while (true) {
  176. // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
  177. if (tLeft == 0) {
  178. return finalReturn;
  179. }
  180. if (pLeft == 0) {
  181. if (starsLeft > 0) {
  182. return finalReturn;
  183. } else {
  184. return FuzzyBoolean.NO;
  185. }
  186. }
  187. if (pattern[pi] == TypePattern.ELLIPSIS) {
  188. return inStar(pattern, target, pi + 1, ti, pLeft, tLeft, starsLeft - 1, kind, parameterAnnotations);
  189. }
  190. FuzzyBoolean ret = null;
  191. try {
  192. if (parameterAnnotations != null) {
  193. target[ti].temporaryAnnotationTypes = parameterAnnotations[ti];
  194. }
  195. ret = pattern[pi].matches(target[ti], kind);
  196. } finally {
  197. target[ti].temporaryAnnotationTypes = null;
  198. }
  199. if (ret == FuzzyBoolean.NO) {
  200. return ret;
  201. }
  202. if (ret == FuzzyBoolean.MAYBE) {
  203. finalReturn = ret;
  204. }
  205. pi++;
  206. ti++;
  207. pLeft--;
  208. tLeft--;
  209. }
  210. }
  211. private static FuzzyBoolean inStar(final TypePattern[] pattern, final ResolvedType[] target, int pi, int ti, final int pLeft,
  212. int tLeft, int starsLeft, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  213. // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
  214. TypePattern patternChar = pattern[pi];
  215. while (patternChar == TypePattern.ELLIPSIS) {
  216. starsLeft--;
  217. patternChar = pattern[++pi];
  218. }
  219. while (true) {
  220. // invariant: if (tLeft > 0) then (ti < target.length)
  221. if (pLeft > tLeft) {
  222. return FuzzyBoolean.NO;
  223. }
  224. FuzzyBoolean ff = null;
  225. try {
  226. if (parameterAnnotations != null) {
  227. target[ti].temporaryAnnotationTypes = parameterAnnotations[ti];
  228. }
  229. ff = patternChar.matches(target[ti], kind);
  230. } finally {
  231. target[ti].temporaryAnnotationTypes = null;
  232. }
  233. if (ff.maybeTrue()) {
  234. FuzzyBoolean xx = outOfStar(pattern, target, pi + 1, ti + 1, pLeft - 1, tLeft - 1, starsLeft, kind,
  235. parameterAnnotations);
  236. if (xx.maybeTrue()) {
  237. return ff.and(xx);
  238. }
  239. }
  240. ti++;
  241. tLeft--;
  242. }
  243. }
  244. public FuzzyBoolean matches(ResolvableTypeList types, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  245. int nameLength = types.length;
  246. int patternLength = typePatterns.length;
  247. int nameIndex = 0;
  248. int patternIndex = 0;
  249. if (ellipsisCount == 0) {
  250. if (nameLength != patternLength) {
  251. return FuzzyBoolean.NO;
  252. }
  253. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  254. while (patternIndex < patternLength) {
  255. ResolvedType t = types.getResolved(nameIndex);
  256. FuzzyBoolean ret = null;
  257. try {
  258. if (parameterAnnotations != null) {
  259. t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
  260. }
  261. ret = typePatterns[patternIndex].matches(t, kind);
  262. } finally {
  263. t.temporaryAnnotationTypes = null;
  264. }
  265. patternIndex++;
  266. nameIndex++;
  267. if (ret == FuzzyBoolean.NO) {
  268. return ret;
  269. }
  270. if (ret == FuzzyBoolean.MAYBE) {
  271. finalReturn = ret;
  272. }
  273. }
  274. return finalReturn;
  275. } else if (ellipsisCount == 1) {
  276. if (nameLength < patternLength - 1) {
  277. return FuzzyBoolean.NO;
  278. }
  279. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  280. while (patternIndex < patternLength) {
  281. TypePattern p = typePatterns[patternIndex++];
  282. if (p == TypePattern.ELLIPSIS) {
  283. nameIndex = nameLength - (patternLength - patternIndex);
  284. } else {
  285. ResolvedType t = types.getResolved(nameIndex);
  286. FuzzyBoolean ret = null;
  287. try {
  288. if (parameterAnnotations != null) {
  289. t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
  290. }
  291. ret = p.matches(t, kind);
  292. } finally {
  293. t.temporaryAnnotationTypes = null;
  294. }
  295. nameIndex++;
  296. if (ret == FuzzyBoolean.NO) {
  297. return ret;
  298. }
  299. if (ret == FuzzyBoolean.MAYBE) {
  300. finalReturn = ret;
  301. }
  302. }
  303. }
  304. return finalReturn;
  305. } else {
  306. // System.err.print("match(" + arguments + ", " + types + ") -> ");
  307. FuzzyBoolean b = outOfStar(typePatterns, types, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind,
  308. parameterAnnotations);
  309. // System.err.println(b);
  310. return b;
  311. }
  312. }
  313. private static FuzzyBoolean outOfStar(final TypePattern[] pattern, ResolvableTypeList target, int pi, int ti, int pLeft,
  314. int tLeft, final int starsLeft, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  315. if (pLeft > tLeft) {
  316. return FuzzyBoolean.NO;
  317. }
  318. FuzzyBoolean finalReturn = FuzzyBoolean.YES;
  319. while (true) {
  320. // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
  321. if (tLeft == 0) {
  322. return finalReturn;
  323. }
  324. if (pLeft == 0) {
  325. if (starsLeft > 0) {
  326. return finalReturn;
  327. } else {
  328. return FuzzyBoolean.NO;
  329. }
  330. }
  331. if (pattern[pi] == TypePattern.ELLIPSIS) {
  332. return inStar(pattern, target, pi + 1, ti, pLeft, tLeft, starsLeft - 1, kind, parameterAnnotations);
  333. }
  334. FuzzyBoolean ret = null;
  335. ResolvedType type = target.getResolved(ti);
  336. try {
  337. if (parameterAnnotations != null) {
  338. type.temporaryAnnotationTypes = parameterAnnotations[ti];
  339. }
  340. ret = pattern[pi].matches(type, kind);
  341. } finally {
  342. type.temporaryAnnotationTypes = null;
  343. }
  344. if (ret == FuzzyBoolean.NO) {
  345. return ret;
  346. }
  347. if (ret == FuzzyBoolean.MAYBE) {
  348. finalReturn = ret;
  349. }
  350. pi++;
  351. ti++;
  352. pLeft--;
  353. tLeft--;
  354. }
  355. }
  356. private static FuzzyBoolean inStar(final TypePattern[] pattern, ResolvableTypeList target, int pi, int ti, final int pLeft,
  357. int tLeft, int starsLeft, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
  358. // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
  359. TypePattern patternChar = pattern[pi];
  360. while (patternChar == TypePattern.ELLIPSIS) {
  361. starsLeft--;
  362. patternChar = pattern[++pi];
  363. }
  364. while (true) {
  365. // invariant: if (tLeft > 0) then (ti < target.length)
  366. if (pLeft > tLeft) {
  367. return FuzzyBoolean.NO;
  368. }
  369. ResolvedType type = target.getResolved(ti);
  370. FuzzyBoolean ff = null;
  371. try {
  372. if (parameterAnnotations != null) {
  373. type.temporaryAnnotationTypes = parameterAnnotations[ti];
  374. }
  375. ff = patternChar.matches(type, kind);
  376. } finally {
  377. type.temporaryAnnotationTypes = null;
  378. }
  379. if (ff.maybeTrue()) {
  380. FuzzyBoolean xx = outOfStar(pattern, target, pi + 1, ti + 1, pLeft - 1, tLeft - 1, starsLeft, kind,
  381. parameterAnnotations);
  382. if (xx.maybeTrue()) {
  383. return ff.and(xx);
  384. }
  385. }
  386. ti++;
  387. tLeft--;
  388. }
  389. }
  390. /**
  391. * Return a version of this type pattern list in which all type variable references are replaced by their corresponding entry in
  392. * the map
  393. *
  394. * @param typeVariableMap
  395. * @return
  396. */
  397. public TypePatternList parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) {
  398. TypePattern[] parameterizedPatterns = new TypePattern[typePatterns.length];
  399. for (int i = 0; i < parameterizedPatterns.length; i++) {
  400. parameterizedPatterns[i] = typePatterns[i].parameterizeWith(typeVariableMap, w);
  401. }
  402. return new TypePatternList(parameterizedPatterns);
  403. }
  404. public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  405. for (int i = 0; i < typePatterns.length; i++) {
  406. TypePattern p = typePatterns[i];
  407. if (p != null) {
  408. typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding, requireExactType);
  409. }
  410. }
  411. return this;
  412. }
  413. public TypePatternList resolveReferences(IntMap bindings) {
  414. int len = typePatterns.length;
  415. TypePattern[] ret = new TypePattern[len];
  416. for (int i = 0; i < len; i++) {
  417. ret[i] = typePatterns[i].remapAdviceFormals(bindings);
  418. }
  419. return new TypePatternList(ret);
  420. }
  421. public void postRead(ResolvedType enclosingType) {
  422. for (TypePattern p : typePatterns) {
  423. p.postRead(enclosingType);
  424. }
  425. }
  426. @Override
  427. public boolean equals(Object other) {
  428. if (!(other instanceof TypePatternList)) {
  429. return false;
  430. }
  431. TypePatternList o = (TypePatternList) other;
  432. int len = o.typePatterns.length;
  433. if (len != this.typePatterns.length) {
  434. return false;
  435. }
  436. for (int i = 0; i < len; i++) {
  437. if (!this.typePatterns[i].equals(o.typePatterns[i])) {
  438. return false;
  439. }
  440. }
  441. return true;
  442. }
  443. @Override
  444. public int hashCode() {
  445. int result = 41;
  446. for (TypePattern typePattern : typePatterns) {
  447. result = 37 * result + typePattern.hashCode();
  448. }
  449. return result;
  450. }
  451. public static TypePatternList read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  452. short len = s.readShort();
  453. TypePattern[] arguments = new TypePattern[len];
  454. for (int i = 0; i < len; i++) {
  455. arguments[i] = TypePattern.read(s, context);
  456. }
  457. TypePatternList ret = new TypePatternList(arguments);
  458. if (!s.isAtLeast169()) {
  459. ret.readLocation(context, s);
  460. }
  461. return ret;
  462. }
  463. @Override
  464. public int getEnd() {
  465. throw new IllegalStateException();
  466. }
  467. @Override
  468. public ISourceContext getSourceContext() {
  469. throw new IllegalStateException();
  470. }
  471. @Override
  472. public ISourceLocation getSourceLocation() {
  473. throw new IllegalStateException();
  474. }
  475. @Override
  476. public int getStart() {
  477. throw new IllegalStateException();
  478. }
  479. @Override
  480. public void write(CompressingDataOutputStream s) throws IOException {
  481. s.writeShort(typePatterns.length);
  482. for (TypePattern typePattern : typePatterns) {
  483. typePattern.write(s);
  484. }
  485. // writeLocation(s);
  486. }
  487. public TypePattern[] getTypePatterns() {
  488. return typePatterns;
  489. }
  490. public List<UnresolvedType> getExactTypes() {
  491. List<UnresolvedType> ret = new ArrayList<>();
  492. for (TypePattern typePattern : typePatterns) {
  493. UnresolvedType t = typePattern.getExactType();
  494. if (!ResolvedType.isMissing(t)) {
  495. ret.add(t);
  496. }
  497. }
  498. return ret;
  499. }
  500. @Override
  501. public Object accept(PatternNodeVisitor visitor, Object data) {
  502. return visitor.visit(this, data);
  503. }
  504. @Override
  505. public Object traverse(PatternNodeVisitor visitor, Object data) {
  506. Object ret = accept(visitor, data);
  507. if (typePatterns != null) {
  508. for (TypePattern typePattern : typePatterns) {
  509. typePattern.traverse(visitor, ret);
  510. }
  511. }
  512. return ret;
  513. }
  514. public boolean areAllExactWithNoSubtypesAllowed() {
  515. for (TypePattern array_element : typePatterns) {
  516. if (!(array_element instanceof ExactTypePattern)) {
  517. return false;
  518. } else {
  519. ExactTypePattern etp = (ExactTypePattern) array_element;
  520. if (etp.isIncludeSubtypes()) {
  521. return false;
  522. }
  523. }
  524. }
  525. return true;
  526. }
  527. public String[] maybeGetCleanNames() {
  528. String[] theParamNames = new String[typePatterns.length];
  529. for (int i = 0; i < typePatterns.length; i++) {
  530. TypePattern string = typePatterns[i];
  531. if (!(string instanceof ExactTypePattern)) {
  532. return null;
  533. }
  534. theParamNames[i] = ((ExactTypePattern) string).getExactType().getName();
  535. }
  536. return theParamNames;
  537. }
  538. }