1 11 package org.eclipse.jdt.internal.compiler.parser; 12 13 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; 14 import org.eclipse.jdt.internal.compiler.ast.ASTNode; 15 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; 16 import org.eclipse.jdt.internal.compiler.ast.Block; 17 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; 18 import org.eclipse.jdt.internal.compiler.ast.Initializer; 19 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; 20 import org.eclipse.jdt.internal.compiler.ast.Statement; 21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 22 import org.eclipse.jdt.internal.compiler.ast.TypeParameter; 23 import org.eclipse.jdt.internal.compiler.ast.TypeReference; 24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 25 26 29 30 public class RecoveredType extends RecoveredStatement implements TerminalTokens { 31 public TypeDeclaration typeDeclaration; 32 33 public RecoveredType[] memberTypes; 34 public int memberTypeCount; 35 public RecoveredField[] fields; 36 public int fieldCount; 37 public RecoveredMethod[] methods; 38 public int methodCount; 39 40 public boolean preserveContent = false; public int bodyEnd; 42 43 public boolean insideEnumConstantPart = false; 44 45 public TypeParameter[] pendingTypeParameters; 46 public int pendingTypeParametersStart; 47 48 public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){ 49 super(typeDeclaration, parent, bracketBalance); 50 this.typeDeclaration = typeDeclaration; 51 if(typeDeclaration.allocation != null && typeDeclaration.allocation.type == null) { 52 this.foundOpeningBrace = true; 54 } else { 55 this.foundOpeningBrace = !bodyStartsAtHeaderEnd(); 56 } 57 this.insideEnumConstantPart = TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL; 58 if(this.foundOpeningBrace) { 59 this.bracketBalance++; 60 } 61 62 this.preserveContent = this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated; 63 } 64 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { 65 66 68 if (typeDeclaration.declarationSourceEnd != 0 69 && methodDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){ 70 this.pendingTypeParameters = null; 71 return this.parent.add(methodDeclaration, bracketBalanceValue); 72 } 73 74 if (methods == null) { 75 methods = new RecoveredMethod[5]; 76 methodCount = 0; 77 } else { 78 if (methodCount == methods.length) { 79 System.arraycopy( 80 methods, 81 0, 82 (methods = new RecoveredMethod[2 * methodCount]), 83 0, 84 methodCount); 85 } 86 } 87 RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser); 88 methods[methodCount++] = element; 89 90 if(this.pendingTypeParameters != null) { 91 element.attach(this.pendingTypeParameters, this.pendingTypeParametersStart); 92 this.pendingTypeParameters = null; 93 } 94 95 this.insideEnumConstantPart = false; 96 97 98 if (!foundOpeningBrace){ 99 foundOpeningBrace = true; 100 this.bracketBalance++; 101 } 102 103 if (methodDeclaration.declarationSourceEnd == 0) return element; 104 return this; 105 } 106 public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) { 107 this.pendingTypeParameters = null; 108 109 int modifiers = ClassFileConstants.AccDefault; 110 if(this.parser().recoveredStaticInitializerStart != 0) { 111 modifiers = ClassFileConstants.AccStatic; 112 } 113 return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalanceValue); 114 } 115 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { 116 this.pendingTypeParameters = null; 117 118 120 if (typeDeclaration.declarationSourceEnd != 0 121 && fieldDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd) { 122 return this.parent.add(fieldDeclaration, bracketBalanceValue); 123 } 124 if (fields == null) { 125 fields = new RecoveredField[5]; 126 fieldCount = 0; 127 } else { 128 if (fieldCount == fields.length) { 129 System.arraycopy( 130 fields, 131 0, 132 (fields = new RecoveredField[2 * fieldCount]), 133 0, 134 fieldCount); 135 } 136 } 137 RecoveredField element; 138 switch (fieldDeclaration.getKind()) { 139 case AbstractVariableDeclaration.FIELD: 140 case AbstractVariableDeclaration.ENUM_CONSTANT: 141 element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue); 142 break; 143 case AbstractVariableDeclaration.INITIALIZER: 144 element = new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue); 145 break; 146 default: 147 return this; 149 } 150 fields[fieldCount++] = element; 151 152 153 if (!foundOpeningBrace){ 154 foundOpeningBrace = true; 155 this.bracketBalance++; 156 } 157 158 if (fieldDeclaration.declarationSourceEnd == 0) return element; 159 return this; 160 } 161 public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) { 162 this.pendingTypeParameters = null; 163 164 166 if (typeDeclaration.declarationSourceEnd != 0 167 && memberTypeDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){ 168 return this.parent.add(memberTypeDeclaration, bracketBalanceValue); 169 } 170 171 this.insideEnumConstantPart = false; 172 173 if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ 174 if (this.methodCount > 0) { 175 RecoveredMethod lastMethod = this.methods[this.methodCount-1]; 177 lastMethod.methodDeclaration.bodyEnd = 0; lastMethod.methodDeclaration.declarationSourceEnd = 0; lastMethod.bracketBalance++; return lastMethod.add(memberTypeDeclaration, bracketBalanceValue); 181 } else { 182 return this; 184 } 185 } 186 187 if (memberTypes == null) { 188 memberTypes = new RecoveredType[5]; 189 memberTypeCount = 0; 190 } else { 191 if (memberTypeCount == memberTypes.length) { 192 System.arraycopy( 193 memberTypes, 194 0, 195 (memberTypes = new RecoveredType[2 * memberTypeCount]), 196 0, 197 memberTypeCount); 198 } 199 } 200 RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue); 201 memberTypes[memberTypeCount++] = element; 202 203 204 if (!foundOpeningBrace){ 205 foundOpeningBrace = true; 206 this.bracketBalance++; 207 } 208 209 if (memberTypeDeclaration.declarationSourceEnd == 0) return element; 210 return this; 211 } 212 public void add(TypeParameter[] parameters, int startPos) { 213 this.pendingTypeParameters = parameters; 214 this.pendingTypeParametersStart = startPos; 215 } 216 219 public int bodyEnd(){ 220 if (bodyEnd == 0) return typeDeclaration.declarationSourceEnd; 221 return bodyEnd; 222 } 223 public boolean bodyStartsAtHeaderEnd(){ 224 if (typeDeclaration.superInterfaces == null){ 225 if (typeDeclaration.superclass == null){ 226 if(typeDeclaration.typeParameters == null) { 227 return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1; 228 } else { 229 return typeDeclaration.bodyStart == typeDeclaration.typeParameters[typeDeclaration.typeParameters.length-1].sourceEnd+1; 230 } 231 } else { 232 return typeDeclaration.bodyStart == typeDeclaration.superclass.sourceEnd+1; 233 } 234 } else { 235 return typeDeclaration.bodyStart 236 == typeDeclaration.superInterfaces[typeDeclaration.superInterfaces.length-1].sourceEnd+1; 237 } 238 } 239 242 public RecoveredType enclosingType(){ 243 RecoveredElement current = parent; 244 while (current != null){ 245 if (current instanceof RecoveredType){ 246 return (RecoveredType) current; 247 } 248 current = current.parent; 249 } 250 return null; 251 } 252 public char[] name(){ 253 return typeDeclaration.name; 254 } 255 258 public ASTNode parseTree(){ 259 return typeDeclaration; 260 } 261 264 public int sourceEnd(){ 265 return this.typeDeclaration.declarationSourceEnd; 266 } 267 public String toString(int tab) { 268 StringBuffer result = new StringBuffer (tabString(tab)); 269 result.append("Recovered type:\n"); if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) { 271 result.append(tabString(tab)); 272 result.append(" "); } 274 typeDeclaration.print(tab + 1, result); 275 if (this.memberTypes != null) { 276 for (int i = 0; i < this.memberTypeCount; i++) { 277 result.append("\n"); result.append(this.memberTypes[i].toString(tab + 1)); 279 } 280 } 281 if (this.fields != null) { 282 for (int i = 0; i < this.fieldCount; i++) { 283 result.append("\n"); result.append(this.fields[i].toString(tab + 1)); 285 } 286 } 287 if (this.methods != null) { 288 for (int i = 0; i < this.methodCount; i++) { 289 result.append("\n"); result.append(this.methods[i].toString(tab + 1)); 291 } 292 } 293 return result.toString(); 294 } 295 298 public void updateBodyStart(int bodyStart){ 299 this.foundOpeningBrace = true; 300 this.typeDeclaration.bodyStart = bodyStart; 301 } 302 public Statement updatedStatement(){ 303 304 if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0 && !this.preserveContent){ 306 return null; 307 } 308 309 TypeDeclaration updatedType = this.updatedTypeDeclaration(); 310 if ((updatedType.bits & ASTNode.IsAnonymousType) != 0){ 311 312 QualifiedAllocationExpression allocation = updatedType.allocation; 313 314 if (allocation.statementEnd == -1) { 315 allocation.statementEnd = updatedType.declarationSourceEnd; 316 } 317 return allocation; 318 } 319 return updatedType; 320 } 321 public TypeDeclaration updatedTypeDeclaration(){ 322 int lastEnd = typeDeclaration.bodyStart; 323 324 if (memberTypeCount > 0){ 325 int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length; 326 TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + memberTypeCount]; 327 if (existingCount > 0){ 328 System.arraycopy(typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount); 329 } 330 if (memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){ 332 int bodyEndValue = bodyEnd(); 333 memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue; 334 memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd = bodyEndValue; 335 } 336 for (int i = 0; i < memberTypeCount; i++){ 337 memberTypeDeclarations[existingCount + i] = memberTypes[i].updatedTypeDeclaration(); 338 } 339 typeDeclaration.memberTypes = memberTypeDeclarations; 340 if(memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd > lastEnd) { 341 lastEnd = memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd; 342 } 343 } 344 345 if (fieldCount > 0){ 346 int existingCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length; 347 FieldDeclaration[] fieldDeclarations = new FieldDeclaration[existingCount + fieldCount]; 348 if (existingCount > 0){ 349 System.arraycopy(typeDeclaration.fields, 0, fieldDeclarations, 0, existingCount); 350 } 351 if (fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd == 0){ 353 int temp = bodyEnd(); 354 fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd = temp; 355 fields[fieldCount - 1].fieldDeclaration.declarationEnd = temp; 356 } 357 for (int i = 0; i < fieldCount; i++){ 358 fieldDeclarations[existingCount + i] = fields[i].updatedFieldDeclaration(); 359 } 360 typeDeclaration.fields = fieldDeclarations; 361 if(fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd > lastEnd) { 362 lastEnd = fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd; 363 } 364 } 365 366 int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length; 367 boolean hasConstructor = false, hasRecoveredConstructor = false; 368 boolean hasAbstractMethods = false; 369 int defaultConstructorIndex = -1; 370 if (methodCount > 0){ 371 AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + methodCount]; 372 for (int i = 0; i < existingCount; i++){ 373 AbstractMethodDeclaration m = typeDeclaration.methods[i]; 374 if (m.isDefaultConstructor()) defaultConstructorIndex = i; 375 if (m.isAbstract()) hasAbstractMethods = true; 376 methodDeclarations[i] = m; 377 } 378 if (methods[methodCount - 1].methodDeclaration.declarationSourceEnd == 0){ 380 int bodyEndValue = bodyEnd(); 381 methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue; 382 methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue; 383 } 384 for (int i = 0; i < methodCount; i++){ 385 AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration(); 386 if (updatedMethod.isConstructor()) hasRecoveredConstructor = true; 387 if (updatedMethod.isAbstract()) hasAbstractMethods = true; 388 methodDeclarations[existingCount + i] = updatedMethod; 389 } 390 typeDeclaration.methods = methodDeclarations; 391 if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) { 392 lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd; 393 } 394 if (hasAbstractMethods) typeDeclaration.bits |= ASTNode.HasAbstractMethods; 395 hasConstructor = typeDeclaration.checkConstructors(this.parser()); 396 } else { 397 for (int i = 0; i < existingCount; i++){ 398 if (typeDeclaration.methods[i].isConstructor()) hasConstructor = true; 399 } 400 } 401 402 if (typeDeclaration.needClassInitMethod()){ 403 boolean alreadyHasClinit = false; 404 for (int i = 0; i < existingCount; i++){ 405 if (typeDeclaration.methods[i].isClinit()){ 406 alreadyHasClinit = true; 407 break; 408 } 409 } 410 if (!alreadyHasClinit) typeDeclaration.addClinit(); 411 } 412 413 if (defaultConstructorIndex >= 0 && hasRecoveredConstructor){ 414 415 AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[typeDeclaration.methods.length - 1]; 416 if (defaultConstructorIndex != 0){ 417 System.arraycopy(typeDeclaration.methods, 0, methodDeclarations, 0, defaultConstructorIndex); 418 } 419 if (defaultConstructorIndex != typeDeclaration.methods.length-1){ 420 System.arraycopy( 421 typeDeclaration.methods, 422 defaultConstructorIndex+1, 423 methodDeclarations, 424 defaultConstructorIndex, 425 typeDeclaration.methods.length - defaultConstructorIndex - 1); 426 } 427 typeDeclaration.methods = methodDeclarations; 428 } else { 429 int kind = TypeDeclaration.kind(typeDeclaration.modifiers); 430 if (!hasConstructor && 431 kind != TypeDeclaration.INTERFACE_DECL && 432 kind != TypeDeclaration.ANNOTATION_TYPE_DECL && 433 typeDeclaration.allocation == null) { boolean insideFieldInitializer = false; 435 RecoveredElement parentElement = this.parent; 436 while (parentElement != null){ 437 if (parentElement instanceof RecoveredField){ 438 insideFieldInitializer = true; 439 break; 440 } 441 parentElement = parentElement.parent; 442 } 443 typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true); 444 } 445 } 446 if (parent instanceof RecoveredType){ 447 typeDeclaration.bits |= ASTNode.IsMemberType; 448 } else if (parent instanceof RecoveredMethod){ 449 typeDeclaration.bits |= ASTNode.IsLocalType; 450 } 451 if(typeDeclaration.declarationSourceEnd == 0) { 452 typeDeclaration.declarationSourceEnd = lastEnd; 453 typeDeclaration.bodyEnd = lastEnd; 454 } 455 return typeDeclaration; 456 } 457 461 public void updateFromParserState(){ 462 463 if(this.bodyStartsAtHeaderEnd() && typeDeclaration.allocation == null){ 465 Parser parser = this.parser(); 466 467 if (parser.listLength > 0 && parser.astLengthPtr > 0){ int length = parser.astLengthStack[parser.astLengthPtr]; 470 int astPtr = parser.astPtr - length; 471 boolean canConsume = astPtr >= 0; 472 if(canConsume) { 473 if((!(parser.astStack[astPtr] instanceof TypeDeclaration))) { 474 canConsume = false; 475 } 476 for (int i = 1, max = length + 1; i < max; i++) { 477 if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) { 478 canConsume = false; 479 } 480 } 481 } 482 if(canConsume) { 483 parser.consumeClassHeaderImplements(); 484 } 487 } else if (parser.listTypeParameterLength > 0) { 488 int length = parser.listTypeParameterLength; 489 int genericsPtr = parser.genericsPtr; 490 boolean canConsume = genericsPtr + 1 >= length && parser.astPtr > -1; 491 if(canConsume) { 492 if (!(parser.astStack[parser.astPtr] instanceof TypeDeclaration)) { 493 canConsume = false; 494 } 495 while(genericsPtr + 1 > length && !(parser.genericsStack[genericsPtr] instanceof TypeParameter)) { 496 genericsPtr--; 497 } 498 for (int i = 0; i < length; i++) { 499 if(!(parser.genericsStack[genericsPtr - i] instanceof TypeParameter)) { 500 canConsume = false; 501 } 502 } 503 } 504 if(canConsume) { 505 TypeDeclaration typeDecl = (TypeDeclaration)parser.astStack[parser.astPtr]; 506 System.arraycopy(parser.genericsStack, genericsPtr - length + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length); 507 typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1; 508 parser.listTypeParameterLength = 0; 509 parser.lastCheckPoint = typeDecl.bodyStart; 510 } 511 } 512 } 513 } 514 518 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ 519 if ((--bracketBalance <= 0) && (parent != null)){ 520 this.updateSourceEndIfNecessary(braceStart, braceEnd); 521 this.bodyEnd = braceStart - 1; 522 return parent; 523 } 524 return this; 525 } 526 530 public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ 531 532 if (bracketBalance == 0){ 533 537 Parser parser = this.parser(); 538 switch(parser.lastIgnoredToken){ 539 case -1 : 540 case TokenNameextends : 541 case TokenNameimplements : 542 case TokenNameGREATER : 543 case TokenNameRIGHT_SHIFT : 544 case TokenNameUNSIGNED_RIGHT_SHIFT : 545 if (parser.recoveredStaticInitializerStart == 0) break; 546 default: 547 this.foundOpeningBrace = true; 548 bracketBalance = 1; } 550 } 551 if (this.bracketBalance == 1){ 553 Block block = new Block(0); 554 Parser parser = this.parser(); 555 block.sourceStart = parser.scanner.startPosition; 556 Initializer init; 557 if (parser.recoveredStaticInitializerStart == 0){ 558 init = new Initializer(block, ClassFileConstants.AccDefault); 559 } else { 560 init = new Initializer(block, ClassFileConstants.AccStatic); 561 init.declarationSourceStart = parser.recoveredStaticInitializerStart; 562 } 563 init.bodyStart = parser.scanner.currentPosition; 564 return this.add(init, 1); 565 } 566 return super.updateOnOpeningBrace(braceStart, braceEnd); 567 } 568 public void updateParseTree(){ 569 this.updatedTypeDeclaration(); 570 } 571 574 public void updateSourceEndIfNecessary(int start, int end){ 575 if (this.typeDeclaration.declarationSourceEnd == 0){ 576 this.bodyEnd = 0; 577 this.typeDeclaration.declarationSourceEnd = end; 578 this.typeDeclaration.bodyEnd = end; 579 } 580 } 581 } 582 | Popular Tags |