001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.util.*; 011 012 // 5.1 Kinds of Conversion 013 aspect TypeConversion { 014 // 5.1.1 Identity Conversion 015 syn boolean TypeDecl.identityConversionTo(TypeDecl type) = this == type; 016 017 syn boolean TypeDecl.wideningConversionTo(TypeDecl type) = instanceOf(type); 018 syn lazy boolean TypeDecl.narrowingConversionTo(TypeDecl type) = instanceOf(type); 019 020 // 5.1.2 Widening Primitive Conversions 021 eq PrimitiveType.wideningConversionTo(TypeDecl type) = instanceOf(type); 022 023 //eq IntType.wideningConversionTo(TypeDecl type) = type.isLong() || type.isFloat() || type.isDouble(); 024 //eq FloatType.wideningConversionTo(TypeDecl type) = type.isLong(); 025 026 // 5.1.3 Narrowing Primitive Conversion 027 eq PrimitiveType.narrowingConversionTo(TypeDecl type) = type.instanceOf(this); 028 eq ShortType.narrowingConversionTo(TypeDecl type) = type.isByte() || type.isChar(); 029 eq CharType.narrowingConversionTo(TypeDecl type) = type.isByte() || type.isShort(); 030 eq ByteType.narrowingConversionTo(TypeDecl type) = type.isChar(); 031 032 // 5.1.4 Widening Reference Conversions 033 eq ReferenceType.wideningConversionTo(TypeDecl type) = instanceOf(type); 034 035 // 5.1.5 Narrowing Reference Conversions 036 eq ReferenceType.narrowingConversionTo(TypeDecl type) { 037 if(type.instanceOf(this)) 038 return true; 039 if(isClassDecl() && !getModifiers().isFinal() && type.isInterfaceDecl()) 040 return true; 041 if(isInterfaceDecl() && type.isClassDecl() && !type.getModifiers().isFinal()) 042 return true; 043 if(isInterfaceDecl() && type.instanceOf(this)) 044 return true; 045 if(fullName().equals("java.lang.Object") && type.isInterfaceDecl()) 046 return true; 047 // Dragons 048 // TODO: Check if both are interfaces with compatible methods 049 if(isArrayDecl() && type.isArrayDecl() && elementType().instanceOf(type.elementType())) 050 return true; 051 return false; 052 } 053 054 // 5.1.6 String Conversions 055 syn boolean TypeDecl.stringConversion() = true; 056 eq VoidType.stringConversion() = false; 057 058 // 5.2 Assignment Conversion 059 syn boolean TypeDecl.assignConversionTo(TypeDecl type, Expr expr) { 060 //System.out.println("@@@ " + fullName() + " assign conversion to " + type.fullName() + ", expr: " + expr); 061 boolean sourceIsConstant = expr != null ? expr.isConstant() : false; 062 //System.out.println("@@@ sourceIsConstant: " + sourceIsConstant); 063 if(identityConversionTo(type) || wideningConversionTo(type)) 064 return true; 065 //System.out.println("@@@ narrowing conversion needed"); 066 //System.out.println("@@@ value: " + expr.value()); 067 if(sourceIsConstant && (isInt() || isChar() || isShort() || isByte()) && 068 (type.isByte() || type.isShort() || type.isChar()) && 069 narrowingConversionTo(type) && expr.representableIn(type)) 070 return true; 071 //System.out.println("@@@ false"); 072 return false; 073 } 074 075 // 5.3 Method Invocation Conversion 076 syn lazy boolean TypeDecl.methodInvocationConversionTo(TypeDecl type) { 077 return identityConversionTo(type) || wideningConversionTo(type); 078 } 079 080 // 5.5 Casting Conversion 081 syn lazy boolean TypeDecl.castingConversionTo(TypeDecl type) = identityConversionTo(type) || 082 wideningConversionTo(type) || narrowingConversionTo(type); 083 084 eq ClassDecl.castingConversionTo(TypeDecl type) { 085 if(type.isArrayDecl()) { 086 return isObject(); 087 } 088 else if(type.isClassDecl()) { 089 return this == type || instanceOf(type) || type.instanceOf(this); 090 } 091 else if(type.isInterfaceDecl()) { 092 return !isFinal() || instanceOf(type); 093 } 094 else return super.castingConversionTo(type); 095 } 096 097 inh MethodDecl InterfaceDecl.unknownMethod(); 098 099 eq InterfaceDecl.castingConversionTo(TypeDecl type) { 100 if(type.isArrayDecl()) { 101 return type.instanceOf(this); 102 } 103 else if(type.isClassDecl()) { 104 return !type.isFinal() || type.instanceOf(this); 105 } 106 else if(type.isInterfaceDecl()) { 107 for(Iterator i1 = methodsIterator(); i1.hasNext(); ) { 108 MethodDecl m = (MethodDecl)i1.next(); 109 for(Iterator iter = type.methodsSignature(m.signature()).iterator(); iter.hasNext(); ) { 110 MethodDecl n = (MethodDecl)iter.next(); 111 if(n.type() != m.type()) 112 return false; 113 } 114 } 115 return true; 116 } 117 else return super.castingConversionTo(type); 118 } 119 120 eq ArrayDecl.castingConversionTo(TypeDecl type) { 121 if(type.isArrayDecl()) { 122 TypeDecl SC = componentType(); 123 TypeDecl TC = type.componentType(); 124 if(SC.isPrimitiveType() && TC.isPrimitiveType() && SC == TC) 125 return true; 126 if(SC.isReferenceType() && TC.isReferenceType()) { 127 return SC.castingConversionTo(TC); 128 } 129 return false; 130 } 131 else if(type.isClassDecl()) { 132 return type.isObject(); 133 } 134 else if(type.isInterfaceDecl()) { 135 return type == typeSerializable() || type == typeCloneable(); 136 } 137 else return super.castingConversionTo(type); 138 } 139 140 inh TypeDecl ArrayDecl.typeSerializable(); 141 inh TypeDecl ArrayDecl.typeCloneable(); 142 143 } 144 145 aspect NumericPromotion { 146 syn TypeDecl TypeDecl.unaryNumericPromotion() = this; // not unknown since this would be 147 // 5.6.1 Unary Numeric Promotion 148 syn lazy TypeDecl NumericType.unaryNumericPromotion() = this; 149 eq ByteType.unaryNumericPromotion() = typeInt(); 150 eq ShortType.unaryNumericPromotion() = typeInt(); 151 eq CharType.unaryNumericPromotion() = typeInt(); 152 153 // 5.6.2 Binary Numeric Promotion 154 syn TypeDecl TypeDecl.binaryNumericPromotion(TypeDecl type) = unknownType(); 155 syn lazy TypeDecl NumericType.binaryNumericPromotion(TypeDecl type) { 156 if(!type.isNumericType()) 157 return unknownType(); 158 return unaryNumericPromotion().instanceOf(type) ? type : unaryNumericPromotion(); 159 } 160 161 } 162 163 aspect TypeAnalysis { 164 // 4.1 The Kinds of Types and Values 165 syn boolean TypeDecl.isReferenceType() = false; 166 eq ReferenceType.isReferenceType() = true; 167 eq UnknownType.isReferenceType() = true; 168 syn boolean TypeDecl.isPrimitiveType() = false; 169 eq PrimitiveType.isPrimitiveType() = true; 170 eq UnknownType.isPrimitiveType() = true; 171 172 // 4.2 Primitive Types and Values 173 syn boolean TypeDecl.isNumericType() = false; 174 eq NumericType.isNumericType() = true; 175 eq UnknownType.isNumericType() = true; 176 177 syn boolean TypeDecl.isIntegralType() = false; 178 eq IntegralType.isIntegralType() = true; 179 eq UnknownType.isIntegralType() = true; 180 181 syn boolean TypeDecl.isBoolean() = false; 182 eq BooleanType.isBoolean() = true; 183 eq UnknownType.isBoolean() = true; 184 185 syn boolean TypeDecl.isByte() = false; 186 eq ByteType.isByte() = true; 187 syn boolean TypeDecl.isChar() = false; 188 eq CharType.isChar() = true; 189 syn boolean TypeDecl.isShort() = false; 190 eq ShortType.isShort() = true; 191 syn boolean TypeDecl.isInt() = false; 192 eq IntType.isInt() = true; 193 eq UnknownType.isInt() = true; 194 195 syn boolean TypeDecl.isFloat() = false; 196 eq FloatType.isFloat() = true; 197 syn boolean TypeDecl.isLong() = false; 198 eq LongType.isLong() = true; 199 syn boolean TypeDecl.isDouble() = false; 200 eq DoubleType.isDouble() = true; 201 202 syn boolean TypeDecl.isVoid() = false; 203 eq VoidType.isVoid() = true; 204 205 syn boolean TypeDecl.isNull() = false; 206 eq NullType.isNull() = true; 207 208 // 4.3 Reference Types and Values 209 syn boolean TypeDecl.isClassDecl() = false; 210 eq ClassDecl.isClassDecl() = true; 211 syn boolean TypeDecl.isInterfaceDecl() = false; 212 eq InterfaceDecl.isInterfaceDecl() = true; 213 syn boolean TypeDecl.isArrayDecl() = false; 214 eq ArrayDecl.isArrayDecl() = true; 215 216 inh lazy boolean TypeDecl.isAnonymous(); 217 eq ClassInstanceExpr.getTypeDecl().isAnonymous() = true; 218 eq TypeDecl.getBodyDecl().isAnonymous() = false; 219 eq Program.getChild().isAnonymous() = false; 220 221 syn boolean TypeDecl.isPrimitive() = false; 222 eq PrimitiveType.isPrimitive() = true; 223 224 syn lazy boolean TypeDecl.isString() = false; 225 eq ClassDecl.isString() = fullName().equals("java.lang.String"); 226 227 syn lazy boolean TypeDecl.isObject() = false; 228 eq ClassDecl.isObject() = name().equals("Object") && packageName().equals("java.lang"); 229 230 syn boolean TypeDecl.isUnknown() = false; 231 eq UnknownType.isUnknown() = true; 232 233 eq Program.getChild().unknownField() = unknownType().findSingleVariable("unknown"); 234 public FieldDeclaration TypeDecl.findSingleVariable(String name) { 235 return (FieldDeclaration)memberFields(name).iterator().next(); 236 } 237 eq Program.getChild().unknownMethod() { 238 for(Iterator iter = unknownType().memberMethods("unknown").iterator(); iter.hasNext(); ) { 239 MethodDecl m = (MethodDecl)iter.next(); 240 return m; 241 } 242 throw new Error("Could not find method unknown in type Unknown"); 243 } 244 eq Program.getChild().unknownConstructor() = unknownConstructor(); 245 syn lazy ConstructorDecl Program.unknownConstructor() { 246 return (ConstructorDecl)unknownType().constructors().iterator().next(); 247 } 248 249 eq AbstractDot.type() = lastAccess().type(); 250 251 syn TypeDecl FieldDeclaration.type() = getTypeAccess().type(); 252 syn TypeDecl VariableDeclaration.type() = getTypeAccess().type(); 253 syn lazy TypeDecl ParameterDeclaration.type() = getTypeAccess().type(); 254 255 inh lazy TypeDecl ArrayInit.declType(); 256 eq Program.getChild(int i).declType() = null; 257 eq FieldDecl.getVariableDecl().declType() = null; 258 eq VarDeclStmt.getVariableDecl().declType() = null; 259 260 eq FieldDeclaration.getInit().declType() = type(); 261 eq VariableDeclaration.getInit().declType() = type(); 262 eq ArrayCreationExpr.getArrayInit().declType() = type(); 263 eq ArrayInit.getInit().declType() = declType().componentType(); 264 265 eq ArrayInit.type() = declType(); 266 267 inh TypeDecl ConstructorDecl.unknownType(); 268 syn TypeDecl ConstructorDecl.type() = unknownType(); 269 syn lazy TypeDecl MethodDecl.type() = getTypeAccess().type(); 270 271 syn boolean BodyDecl.isVoid() = false; 272 eq MethodDecl.isVoid() = type().isVoid(); 273 eq FieldDeclaration.isVoid() = type().isVoid(); 274 eq ConstructorDecl.isVoid() = true; 275 276 syn lazy TypeDecl Expr.type(); 277 278 eq Access.type() = unknownType(); 279 eq TypeAccess.type() = decl(); 280 eq ArrayAccess.type() = isQualified() ? qualifier().type().componentType() : unknownType(); 281 inh TypeDecl ArrayAccess.unknownType(); 282 283 eq VarAccess.type() = decl().type(); 284 eq MethodAccess.type() = decl().type(); 285 eq ConstructorAccess.type() = decl().type(); 286 287 eq ThisAccess.type() = decl(); 288 eq SuperAccess.type() { 289 TypeDecl typeDecl = decl(); 290 if(!typeDecl.isClassDecl()) 291 return unknownType(); 292 ClassDecl classDecl = (ClassDecl)typeDecl; 293 if(!classDecl.hasSuperclass()) 294 return unknownType(); 295 return classDecl.superclass(); 296 } 297 298 eq AssignExpr.type() = getDest().type(); 299 300 eq IntegerLiteral.type() = typeInt(); 301 eq LongLiteral.type() = typeLong(); 302 eq FloatingPointLiteral.type() = typeFloat(); 303 eq DoubleLiteral.type() = typeDouble(); 304 eq BooleanLiteral.type() = typeBoolean(); 305 eq CharacterLiteral.type() = typeChar(); 306 eq StringLiteral.type() = typeString(); 307 eq NullLiteral.type() = typeNull(); 308 309 eq ParExpr.type() = getExpr().isTypeAccess() ? unknownType() : getExpr().type(); 310 311 eq ClassInstanceExpr.type() = hasTypeDecl() ? getTypeDecl() : getAccess().type(); 312 eq ArrayCreationExpr.type() = getTypeAccess().type(); 313 314 eq Unary.type() = getOperand().type(); 315 eq PlusExpr.type() = getOperand().type().unaryNumericPromotion(); 316 eq MinusExpr.type() = getOperand().type().unaryNumericPromotion(); 317 eq BitNotExpr.type() = getOperand().type().unaryNumericPromotion(); 318 eq LogNotExpr.type() = typeBoolean(); 319 320 eq CastExpr.type() = getTypeAccess().type(); 321 322 // 15.17 323 eq MultiplicativeExpr.type() = getLeftOperand().type().binaryNumericPromotion(getRightOperand().type()); 324 // 15.18 325 eq AdditiveExpr.type() = getLeftOperand().type().binaryNumericPromotion(getRightOperand().type()); 326 // 15.18 327 eq AddExpr.type() { 328 TypeDecl left = getLeftOperand().type(); 329 TypeDecl right = getRightOperand().type(); 330 if(!left.isString() && !right.isString()) 331 return super.type(); 332 else { 333 if(left.isVoid() || right.isVoid()) 334 return unknownType(); 335 // pick the string type 336 return left.isString() ? left : right; 337 } 338 } 339 340 // 15.19 341 eq ShiftExpr.type() = getLeftOperand().type().unaryNumericPromotion(); 342 343 // 15.20, 15.21 344 eq RelationalExpr.type() = typeBoolean(); 345 346 // 15.23, 15.24 347 eq LogicalExpr.type() = typeBoolean(); 348 349 // 15.22 350 eq BitwiseExpr.type() { 351 if(getLeftOperand().type().isIntegralType() && getRightOperand().type().isIntegralType()) 352 // 15.22.1 353 return getLeftOperand().type().binaryNumericPromotion(getRightOperand().type()); 354 else if(getLeftOperand().type().isBoolean() && getRightOperand().type().isBoolean()) 355 // 15.22.2 356 return typeBoolean(); 357 return unknownType(); 358 } 359 360 // 15.20.2 361 eq InstanceOfExpr.type() = typeBoolean(); 362 363 // 15.25 364 eq ConditionalExpr.type() { 365 TypeDecl trueType = getTrueExpr().type(); 366 TypeDecl falseType = getFalseExpr().type(); 367 368 if(trueType == falseType) return trueType; 369 370 if(trueType.isNumericType() && falseType.isNumericType()) { 371 if(trueType.isByte() && falseType.isShort()) return falseType; 372 if(trueType.isShort() && falseType.isByte()) return trueType; 373 if((trueType.isByte() || trueType.isShort() || trueType.isChar()) && 374 falseType.isInt() && getFalseExpr().isConstant() && getFalseExpr().representableIn(trueType)) 375 return trueType; 376 if((falseType.isByte() || falseType.isShort() || falseType.isChar()) && 377 trueType.isInt() && getTrueExpr().isConstant() && getTrueExpr().representableIn(falseType)) 378 return falseType; 379 return trueType.binaryNumericPromotion(falseType); 380 } 381 else if(trueType.isBoolean() && falseType.isBoolean()) { 382 return trueType; 383 } 384 else if(trueType.isReferenceType() && falseType.isNull()) { 385 return trueType; 386 } 387 else if(trueType.isNull() && falseType.isReferenceType()) { 388 return falseType; 389 } 390 else if(trueType.isReferenceType() && falseType.isReferenceType()) { 391 if(trueType.assignConversionTo(falseType, null)) 392 return falseType; 393 if(falseType.assignConversionTo(trueType, null)) 394 return trueType; 395 return unknownType(); 396 } 397 else 398 return unknownType(); 399 } 400 401 eq ClassAccess.type() = lookupType("java.lang", "Class"); 402 403 } 404 405 aspect TypeWideningAndIdentity { 406 407 syn lazy boolean TypeDecl.instanceOf(TypeDecl type); 408 eq TypeDecl.instanceOf(TypeDecl type) = type == this; 409 eq ClassDecl.instanceOf(TypeDecl type) = type.isSupertypeOfClassDecl(this); 410 eq InterfaceDecl.instanceOf(TypeDecl type) = type.isSupertypeOfInterfaceDecl(this); 411 eq ArrayDecl.instanceOf(TypeDecl type) = type.isSupertypeOfArrayDecl(this); 412 eq PrimitiveType.instanceOf(TypeDecl type) = type.isSupertypeOfPrimitiveType(this); 413 eq NullType.instanceOf(TypeDecl type) = type.isSupertypeOfNullType(this); 414 eq VoidType.instanceOf(TypeDecl type) = type.isSupertypeOfVoidType(this); 415 416 eq UnknownType.instanceOf(TypeDecl type) = true; 417 eq UnknownType.isSupertypeOfClassDecl(ClassDecl type) = true; 418 eq UnknownType.isSupertypeOfInterfaceDecl(InterfaceDecl type) = true; 419 eq UnknownType.isSupertypeOfArrayDecl(ArrayDecl type) = true; 420 eq UnknownType.isSupertypeOfPrimitiveType(PrimitiveType type) = true; 421 eq UnknownType.isSupertypeOfNullType(NullType type) = true; 422 423 syn boolean TypeDecl.isSupertypeOfClassDecl(ClassDecl type) = type == this; 424 eq ClassDecl.isSupertypeOfClassDecl(ClassDecl type) { 425 if(super.isSupertypeOfClassDecl(type)) 426 return true; 427 return type.hasSuperclass() && type.superclass() != null && type.superclass().instanceOf(this); 428 } 429 eq InterfaceDecl.isSupertypeOfClassDecl(ClassDecl type) { 430 if(super.isSupertypeOfClassDecl(type)) 431 return true; 432 for(Iterator iter = type.interfacesIterator(); iter.hasNext(); ) { 433 TypeDecl typeDecl = (TypeDecl)iter.next(); 434 if(typeDecl.instanceOf(this)) 435 return true; 436 } 437 return type.hasSuperclass() && type.superclass() != null && type.superclass().instanceOf(this); 438 } 439 440 syn boolean TypeDecl.isSupertypeOfInterfaceDecl(InterfaceDecl type) = type == this; 441 eq ClassDecl.isSupertypeOfInterfaceDecl(InterfaceDecl type) = isObject(); 442 eq InterfaceDecl.isSupertypeOfInterfaceDecl(InterfaceDecl type) { 443 if(super.isSupertypeOfInterfaceDecl(type)) 444 return true; 445 for(Iterator iter = type.superinterfacesIterator(); iter.hasNext(); ) { 446 TypeDecl superinterface = (TypeDecl)iter.next(); 447 if(superinterface.instanceOf(this)) 448 return true; 449 } 450 return false; 451 } 452 453 syn boolean TypeDecl.isSupertypeOfArrayDecl(ArrayDecl type) = this == type; 454 eq ClassDecl.isSupertypeOfArrayDecl(ArrayDecl type) { 455 if(super.isSupertypeOfArrayDecl(type)) 456 return true; 457 return type.hasSuperclass() && type.superclass() != null && type.superclass().instanceOf(this); 458 } 459 eq InterfaceDecl.isSupertypeOfArrayDecl(ArrayDecl type) { 460 if(super.isSupertypeOfArrayDecl(type)) 461 return true; 462 for(Iterator iter = type.interfacesIterator(); iter.hasNext(); ) { 463 TypeDecl typeDecl = (TypeDecl)iter.next(); 464 if(typeDecl.instanceOf(this)) 465 return true; 466 } 467 return false; 468 } 469 eq ArrayDecl.isSupertypeOfArrayDecl(ArrayDecl type) { 470 if(type.elementType().isPrimitive() && elementType().isPrimitive()) 471 return type.dimension() == dimension() && type.elementType() == elementType(); 472 return type.componentType().instanceOf(componentType()); 473 } 474 475 syn boolean TypeDecl.isSupertypeOfPrimitiveType(PrimitiveType type) = type == this; 476 eq PrimitiveType.isSupertypeOfPrimitiveType(PrimitiveType type) { 477 if(super.isSupertypeOfPrimitiveType(type)) 478 return true; 479 return type.hasSuperclass() && type.superclass().isPrimitive() && type.superclass().instanceOf(this); 480 } 481 482 syn boolean TypeDecl.isSupertypeOfNullType(NullType type) = false; 483 eq ReferenceType.isSupertypeOfNullType(NullType type) = true; 484 eq NullType.isSupertypeOfNullType(NullType type) = true; 485 486 syn boolean TypeDecl.isSupertypeOfVoidType(VoidType type) = false; 487 eq VoidType.isSupertypeOfVoidType(VoidType type) = true; 488 } 489 490 aspect NestedTypes { 491 492 493 eq CompilationUnit.getChild().enclosingType() = null; 494 eq TypeDecl.getBodyDecl().enclosingType() = this; 495 496 inh TypeDecl TypeDecl.enclosingType(); 497 syn TypeDecl TypeDecl.topLevelType() { 498 if(isTopLevelType()) 499 return this; 500 return enclosingType().topLevelType(); 501 } 502 503 syn Stmt Expr.enclosingStmt() { 504 ASTNode node = this; 505 while(node != null && !(node instanceof Stmt)) 506 node = node.getParent(); 507 return (Stmt)node; 508 } 509 510 inh BodyDecl Expr.enclosingBodyDecl(); 511 inh BodyDecl Stmt.enclosingBodyDecl(); 512 inh BodyDecl TypeDecl.enclosingBodyDecl(); 513 eq Program.getChild().enclosingBodyDecl() = null; 514 eq BodyDecl.getChild().enclosingBodyDecl() = this; 515 516 517 // 8 518 inh boolean TypeDecl.isNestedType(); 519 eq CompilationUnit.getChild().isNestedType() = false; 520 eq TypeDecl.getBodyDecl().isNestedType() = true; 521 522 // 8 523 syn boolean TypeDecl.isTopLevelType() = !isNestedType(); 524 525 // 8.5 526 inh boolean TypeDecl.isMemberType(); 527 eq MemberClassDecl.getClassDecl().isMemberType() = true; 528 eq MemberInterfaceDecl.getInterfaceDecl().isMemberType() = true; 529 eq CompilationUnit.getTypeDecl().isMemberType() = false; 530 eq ClassInstanceExpr.getTypeDecl().isMemberType() = false; 531 eq Program.getChild().isMemberType() = false; 532 533 // 8.1.2 534 syn boolean TypeDecl.isInnerClass() = false; 535 eq ClassDecl.isInnerClass() = isNestedType() && !isStatic() && enclosingType().isClassDecl(); 536 syn boolean TypeDecl.isInnerType() = (isLocalClass() || isAnonymous() || (isMemberType() && !isStatic())) && !inStaticContext(); 537 538 syn boolean TypeDecl.isInnerTypeOf(TypeDecl typeDecl) = typeDecl == this || (isInnerType() && enclosingType().isInnerTypeOf(typeDecl)); 539 540 inh boolean TypeDecl.isLocalClass(); 541 eq CompilationUnit.getChild().isLocalClass() = false; 542 eq TypeDecl.getBodyDecl().isLocalClass() = false; 543 eq LocalClassDeclStmt.getClassDecl().isLocalClass() = true; 544 545 syn TypeDecl TypeDecl.withinBodyThatSubclasses(TypeDecl type) { 546 if(instanceOf(type)) 547 return this; 548 if(!isTopLevelType()) 549 return enclosingType().withinBodyThatSubclasses(type); 550 return null; 551 } 552 553 syn boolean TypeDecl.encloses(TypeDecl type) = type.enclosedBy(this); 554 555 syn boolean TypeDecl.enclosedBy(TypeDecl type) { 556 if(this == type) 557 return true; 558 if(isTopLevelType()) 559 return false; 560 return enclosingType().enclosedBy(type); 561 } 562 563 eq CompilationUnit.getChild().hostPackage() = packageName(); 564 565 inh String TypeDecl.hostPackage(); 566 inh String BodyDecl.hostPackage(); 567 inh String Expr.hostPackage(); 568 569 syn TypeDecl TypeDecl.hostType() = this; 570 571 // ES: need to broaded the propagation of hostType catch it in syn NTAs 572 eq TypeDecl.getChild().hostType() = hostType(); 573 574 eq TypeDecl.getBodyDecl().hostType() = hostType(); 575 eq TypeDecl.getModifiers().hostType() = hostType(); 576 eq ClassInstanceExpr.getTypeDecl().hostType() = hostType(); 577 eq PrimitiveType.getSuperClassAccess().hostType() = hostType(); 578 eq ClassDecl.getSuperClassAccess().hostType() = hostType(); 579 eq ClassDecl.getImplements().hostType() = hostType(); 580 eq InterfaceDecl.getSuperInterfaceId().hostType() = hostType(); 581 582 eq Program.getChild().hostType() = null; 583 eq CompilationUnit.getImportDecl().hostType() = null; 584 585 inh TypeDecl BodyDecl.hostType(); 586 inh TypeDecl Expr.hostType(); 587 inh TypeDecl Stmt.hostType(); 588 inh TypeDecl VariableDeclaration.hostType(); 589 inh TypeDecl ParameterDeclaration.hostType(); 590 591 } 592 593 594 aspect SuperClasses { 595 596 public boolean ClassDecl.hasSuperclass() { 597 return !isObject(); 598 } 599 600 public ClassDecl ClassDecl.superclass() { 601 if(isObject()) 602 return null; 603 if(hasSuperClassAccess() && !isCircular() && getSuperClassAccess().type().isClassDecl()) 604 return (ClassDecl)getSuperClassAccess().type(); 605 return (ClassDecl)typeObject(); 606 } 607 608 public boolean PrimitiveType.hasSuperclass() { 609 return !isObject(); 610 } 611 612 syn TypeDecl PrimitiveType.superclass() = getSuperClassAccess().type(); 613 614 615 public Iterator ClassDecl.interfacesIterator() { 616 return new Iterator() { 617 public boolean hasNext() { 618 computeNextCurrent(); 619 return current != null; 620 } 621 public Object next() { 622 return current; 623 } 624 public void remove() { 625 throw new UnsupportedOperationException(); 626 } 627 private int index = 0; 628 private TypeDecl current = null; 629 private void computeNextCurrent() { 630 current = null; 631 if(isObject() || isCircular()) 632 return; 633 while(index < getNumImplements()) { 634 TypeDecl typeDecl = getImplements(index++).type(); 635 if(!typeDecl.isCircular() && typeDecl.isInterfaceDecl()) { 636 current = typeDecl; 637 return; 638 } 639 } 640 } 641 }; 642 } 643 644 public Iterator InterfaceDecl.superinterfacesIterator() { 645 return new Iterator() { 646 public boolean hasNext() { 647 computeNextCurrent(); 648 return current != null; 649 } 650 public Object next() { 651 return current; 652 } 653 public void remove() { 654 throw new UnsupportedOperationException(); 655 } 656 private int index = 0; 657 private TypeDecl current = null; 658 private void computeNextCurrent() { 659 current = null; 660 if(isCircular()) return; 661 while(index < getNumSuperInterfaceId()) { 662 TypeDecl typeDecl = getSuperInterfaceId(index++).type(); 663 if(!typeDecl.isCircular() && typeDecl.isInterfaceDecl()) { 664 current = typeDecl; 665 return; 666 } 667 } 668 } 669 }; 670 } 671 672 } 673 674 aspect Circularity { 675 inh lazy TypeDecl TypeDecl.unknownType(); 676 syn lazy boolean TypeDecl.isCircular() circular [true] = false; 677 eq ClassDecl.isCircular() { 678 if(hasSuperClassAccess()) { 679 Access a = getSuperClassAccess().lastAccess(); 680 while(a != null) { 681 if(a.type().isCircular()) 682 return true; 683 a = (a.isQualified() && a.qualifier().isTypeAccess()) ? (Access)a.qualifier() : null; 684 } 685 } 686 for(int i = 0; i < getNumImplements(); i++) { 687 Access a = getImplements(i).lastAccess(); 688 while(a != null) { 689 if(a.type().isCircular()) 690 return true; 691 a = (a.isQualified() && a.qualifier().isTypeAccess()) ? (Access)a.qualifier() : null; 692 } 693 } 694 return false; 695 } 696 eq InterfaceDecl.isCircular() { 697 for(int i = 0; i < getNumSuperInterfaceId(); i++) { 698 Access a = getSuperInterfaceId(i).lastAccess(); 699 while(a != null) { 700 if(a.type().isCircular()) 701 return true; 702 a = (a.isQualified() && a.qualifier().isTypeAccess()) ? (Access)a.qualifier() : null; 703 } 704 } 705 return false; 706 } 707 }