1 24 25 package org.aspectj.compiler.crosscuts.ast; 26 import org.aspectj.compiler.base.ast.*; 27 import org.aspectj.compiler.base.cst.*; 28 import org.aspectj.compiler.crosscuts.joinpoints.*; 29 30 import org.aspectj.compiler.base.*; 31 import org.aspectj.util.*; 32 33 import org.aspectj.compiler.base.TypeManager; 34 import java.util.*; 35 36 42 43 public class PatternTypeName extends GenTypeName { 44 49 Map matchCache = new HashMap(); 50 Map instanceMatchCache = new HashMap(); 51 52 public String toShortString() { 53 String ret = names.toShortString(); 54 if (includeSubTypes) 55 ret += "+"; 56 return ret; 57 } 58 59 private Formals getEnclosingFormals(ASTObject node) { 60 if (node == null) 61 return null; 62 if (node instanceof Formals) 63 return (Formals) node; 64 if (node instanceof AdviceDec) 65 return ((AdviceDec) node).getFormals(); 66 if (node instanceof PointcutDec) 67 return ((PointcutDec) node).getFormals(); 68 return getEnclosingFormals(node.getParent()); 69 } 70 71 private FormalDec getEnclosingAfterFormal(ASTObject node) { 72 if (node == null) 73 return null; 74 if (node instanceof AdviceDec) 75 return ((AdviceDec) node).getExtraFormal(); 76 return getEnclosingAfterFormal(node.getParent()); 77 } 78 79 private Pcd getEnclosingPcd(ASTObject node) { 80 if (node == null) 81 return null; 82 if (node instanceof Pcd) 83 return (Pcd) node; 84 return getEnclosingPcd(node.getParent()); 85 } 86 87 private Scope savedScope; 88 89 91 101 public ASTObject postScope(ScopeWalker walker) { 102 if (savedScope != null) 104 return this; 105 106 savedScope = walker.getScope(); 107 108 if (names.size() == 1 && names.get(0).isStar() && dimensions == 0) { 110 return new AnyTypeName(getSourceLocation()).setSource(this); 111 } 112 113 if (names.size() == 1 && dimensions == 0) { 115 Formals formals = getEnclosingFormals(this); 116 String id = names.get(0).getSimpleName(); 117 if (formals != null) { 118 FormalDec formalDec = formals.findName(id); 119 if (formalDec != null) { 120 return makeVarTypeName(formalDec); 121 } else { 122 FormalDec afterFormal = getEnclosingAfterFormal(this); 123 if (afterFormal != null && afterFormal.getId().equals(id)) { 124 getCompiler().showError( 125 this, 126 "can't refer to '" + afterFormal.toShortString() + "' from this context"); 127 return makeSimpleTypeName(getTypeManager().TYPE_NOT_FOUND); 128 } 129 } 130 } 131 } 132 133 if (names.size() == 1) { 135 String id = names.get(0).getSimpleName(); 136 if (id != null) { 137 Type primType = getTypeManager().findPrimitiveType(id); 138 if (primType != null) { 139 return makeSimpleTypeName(primType); 140 } 141 } 142 } 143 144 return this; 145 } 146 147 private SimpleTypeName makeSimpleTypeName(Type t) { 148 for (int i = 0; i < dimensions; i++) { 149 t = t.getArrayType(); 150 } 151 return new SimpleTypeName(getSourceLocation(), t, includeSubTypes); 152 } 153 154 160 private boolean anyTypeMatches() { 161 for (Iterator i = getTypeManager().getLoadedTypes().iterator(); i.hasNext();) { 163 Type t = (Type) i.next(); 164 if (this.matches(t.getNamePieces())) 165 return true; 166 } 167 168 170 for (Iterator i = getTypeManager().getAllVisibleTypeNames().iterator(); 171 i.hasNext(); 172 ) { 173 List pieces = (List) i.next(); 174 if (this.matches(pieces)) 175 return true; 176 } 177 return false; 178 } 179 180 184 public void checkSpec() { 185 Name cstName = names.makeName(); 186 187 if (cstName != null) { 189 cstName.setParent(this); 194 195 Type t = cstName.resolveType(savedScope, false); 196 if (t.isMissing()) { 197 getCompiler().showWarning(this, ErrorHandler.invalidAbsoluteTypeName); 198 super.checkSpec(); 199 return; 200 } 201 SimpleTypeName s = makeSimpleTypeName(t); 202 this.replaceWith(s); 203 s.checkSpec(); 204 return; 205 } else { 206 if (ErrorHandler.invalidWildcardTypeName.shouldDisplay(getCompiler())) { 208 if (!anyTypeMatches()) { 209 getCompiler().showWarning(this, ErrorHandler.invalidWildcardTypeName); 210 } 211 } 212 } 213 super.checkSpec(); 214 } 215 216 protected GenTypeName makeVarTypeName(FormalDec formalDec) { 217 formalDec.isBound = true; 218 219 if (includeSubTypes || getParent() instanceof GenTypeName) { 220 showError("formal binding can not be done as part of a GTN"); 221 return this; 222 } 223 224 if (!getEnclosingPcd(this).allowsNameBinding()) { 225 showError("name binding is only allowed in target, this, and args PCDs"); 226 return this; 227 } 228 return new VarTypeName(getSourceLocation(), formalDec); 229 } 230 231 public ASTObject postCopy(CopyWalker walker, ASTObject oldObject) { 232 savedScope = ((PatternTypeName) oldObject).savedScope; 233 return this; 234 } 235 236 public FuzzyBoolean matchesInstance(Type type) { 237 FuzzyBoolean ret = (FuzzyBoolean) instanceMatchCache.get(type); 238 239 if (ret != null) 240 return ret; 241 242 Set tests = new HashSet(); 243 boolean isMatch = matches(null, type, false, tests); 244 if (!isMatch) { 245 ret = FuzzyBoolean.NO; 246 } else if (tests.size() == 0) { 247 ret = FuzzyBoolean.YES; 248 } else { 249 ret = FuzzyBoolean.MAYBE; 250 } 251 252 instanceMatchCache.put(type, ret); 253 254 return ret; 256 } 257 258 void addInstanceTests(Set instanceTests, Expr expr, JpPlan plan) { 259 if (instanceTests.size() == 0) 260 return; 261 262 instanceTests = Type.filterTopTypes(instanceTests); 263 264 Expr testExpr = null; 265 final AST ast = getAST(); 266 for (Iterator i = instanceTests.iterator(); i.hasNext();) { 267 Type matchingType = (Type) i.next(); 268 if (expr.getType().isSubtypeOf(matchingType)) 269 continue; 270 Expr instanceTest = ast.makeParen(ast.makeInstanceof(expr, matchingType)); 271 if (testExpr == null) 272 testExpr = instanceTest; 273 else 274 testExpr = ast.makeBinop("||", testExpr, instanceTest); 275 } 276 if (testExpr != null) 277 plan.addExprTest(testExpr); 278 } 279 280 public JpPlan makePlan(JoinPoint jp, Expr expr) { 281 JpPlan plan = new JpPlan(jp); 284 if (expr.getType() == null) { 286 return JpPlan.NO_PLAN; 288 } 289 Set instanceTests = new HashSet(); 290 if (matches(plan, expr.getType(), false, instanceTests)) { 291 addInstanceTests(instanceTests, expr, plan); 293 return plan; 294 } else { 295 return JpPlan.NO_PLAN; 297 } 298 } 299 300 306 boolean matches( 307 JpPlan plan, 308 Type asType, 309 boolean needsTest, 310 Set instanceofTests) 311 { 312 Type matchingType = matches(asType, true); 313 if (matchingType != null) { 315 if (needsTest) { 316 instanceofTests.add(matchingType); 317 } 318 return true; 320 } 321 322 boolean couldMatch = false; 324 Collection subTypes = asType.getDirectSubTypes(); 325 327 if (subTypes == null) 328 return false; 329 330 for (Iterator i = subTypes.iterator(); i.hasNext();) { 331 if (matches(plan, (Type) i.next(), true, instanceofTests)) 332 couldMatch = true; 333 } 334 335 return couldMatch; 336 } 337 338 public boolean matches(Type type) { 339 return matches(type, includeSubTypes) != null; 340 } 341 342 public Type matches(Type type, boolean includeSubTypes) { 343 if (basicMatch(type)) 345 return type; 346 347 if (includeSubTypes) { 348 for (Iterator i = type.getDirectSuperTypes().iterator(); i.hasNext();) { 350 Type tryType = (Type) i.next(); 351 Type matchType = matches(tryType, includeSubTypes); 352 if (matchType != null) 353 return matchType; 354 } 355 } 356 return null; 358 } 359 360 protected boolean basicMatch(Type type) { 361 Boolean cachedResult = (Boolean ) matchCache.get(type); 362 if (cachedResult != null) 363 return cachedResult.booleanValue(); 364 365 boolean ret = innerBasicMatch(type); 366 matchCache.put(type, ret ? Boolean.TRUE : Boolean.FALSE); 367 return ret; 368 } 369 370 private boolean innerBasicMatch(Type type) { 371 if (dimensions != type.getArrayDimCount()) { 374 if (dimensions == 0) 375 type = getTypeManager().getObjectType(); 376 else 377 return false; 378 } 379 380 List pieces = type.getBaseComponentType().getNamePieces(); 382 if (!matches(pieces)) { 384 return false; 385 } 386 return true; 387 } 388 389 private boolean isEllipses(NamePattern name) { 390 return name instanceof EllipsesFakeNamePattern; 391 } 392 393 protected boolean matches(List pieces) { 394 return matches(pieces, pieces.size() - 1, names.size() - 1); 395 } 396 397 protected boolean matches( 398 List pieces, 399 int pieceIndex, 400 int nameIndex) { 401 if (nameIndex < 0) { 402 pieceIndex += 1; 404 if (pieceIndex == 0) 406 return true; 407 408 if (savedScope == null) { 411 showError("no saved scope"); 412 } 413 414 Type importType = savedScope.findType((String ) pieces.get(pieceIndex), this); 415 if (importType == null) return false; 416 417 List importPieces = importType.getNamePieces(); 418 return importPieces.equals(pieces.subList(0, pieceIndex+1)); 419 } 420 421 if (pieceIndex < 0) 422 return false; 423 424 NamePattern name = names.get(nameIndex); 425 if (isEllipses(name)) { 426 for (; pieceIndex >= 0; pieceIndex--) { 427 if (matches(pieces, pieceIndex, nameIndex - 1)) 429 return true; 430 } 431 return false; 432 } else { 433 if (name.matches((String ) pieces.get(pieceIndex))) { 434 return matches(pieces, pieceIndex - 1, nameIndex - 1); 435 } else { 436 return false; 437 } 438 } 439 } 440 441 protected NamePatterns names; 443 public NamePatterns getNames() { 444 return names; 445 } 446 public void setNames(NamePatterns _names) { 447 names = _names; 448 } 449 450 protected boolean includeSubTypes; 451 public boolean getIncludeSubTypes() { 452 return includeSubTypes; 453 } 454 public void setIncludeSubTypes(boolean _includeSubTypes) { 455 includeSubTypes = _includeSubTypes; 456 } 457 458 protected int dimensions; 459 public int getDimensions() { 460 return dimensions; 461 } 462 public void setDimensions(int _dimensions) { 463 dimensions = _dimensions; 464 } 465 466 public PatternTypeName( 467 SourceLocation location, 468 NamePatterns _names, 469 boolean _includeSubTypes, 470 int _dimensions) { 471 super(location); 472 setNames(_names); 473 setIncludeSubTypes(_includeSubTypes); 474 setDimensions(_dimensions); 475 } 476 protected PatternTypeName(SourceLocation source) { 477 super(source); 478 } 479 480 public ASTObject copyWalk(CopyWalker walker) { 481 PatternTypeName ret = new PatternTypeName(getSourceLocation()); 482 ret.preCopy(walker, this); 483 ret.names = names; 484 ret.includeSubTypes = includeSubTypes; 485 ret.dimensions = dimensions; 486 return ret; 487 } 488 489 public String getDefaultDisplayName() { 490 return "PatternTypeName(names: " 491 + names 492 + ", " 493 + "includeSubTypes: " 494 + includeSubTypes 495 + ", " 496 + "dimensions: " 497 + dimensions 498 + ")"; 499 } 500 501 503 } | Popular Tags |