1 11 package org.eclipse.jdt.internal.compiler.parser; 12 13 import org.eclipse.jdt.core.compiler.*; 14 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; 15 import org.eclipse.jdt.internal.compiler.ast.Argument; 16 import org.eclipse.jdt.internal.compiler.ast.ASTNode; 17 import org.eclipse.jdt.internal.compiler.ast.Block; 18 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; 19 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; 20 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; 21 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; 22 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; 23 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; 24 import org.eclipse.jdt.internal.compiler.ast.Statement; 25 import org.eclipse.jdt.internal.compiler.ast.SuperReference; 26 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 27 import org.eclipse.jdt.internal.compiler.ast.TypeParameter; 28 import org.eclipse.jdt.internal.compiler.ast.TypeReference; 29 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 30 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 31 import org.eclipse.jdt.internal.compiler.util.Util; 32 33 36 37 public class RecoveredMethod extends RecoveredElement implements TerminalTokens { 38 39 public AbstractMethodDeclaration methodDeclaration; 40 41 public RecoveredType[] localTypes; 42 public int localTypeCount; 43 44 public RecoveredBlock methodBody; 45 public boolean discardBody = true; 46 47 public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){ 48 super(parent, bracketBalance, parser); 49 this.methodDeclaration = methodDeclaration; 50 this.foundOpeningBrace = !bodyStartsAtHeaderEnd(); 51 if(this.foundOpeningBrace) { 52 this.bracketBalance++; 53 } 54 } 55 58 public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { 59 60 64 if (methodDeclaration.declarationSourceEnd > 0 65 && nestedBlockDeclaration.sourceStart 66 > methodDeclaration.declarationSourceEnd){ 67 if (this.parent == null){ 68 return this; } else { 70 return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); 71 } 72 } 73 74 if (!foundOpeningBrace){ 75 foundOpeningBrace = true; 76 this.bracketBalance++; 77 } 78 79 methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); 80 if (nestedBlockDeclaration.sourceEnd == 0) return methodBody; 81 return this; 82 } 83 86 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { 87 88 89 char[][] fieldTypeName; 90 if ((fieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 || (fieldDeclaration.type == null) || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 && CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){ 94 95 if (this.parent == null){ 96 return this; } else { 98 this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1)); 99 return this.parent.add(fieldDeclaration, bracketBalanceValue); 100 } 101 } 102 106 if (methodDeclaration.declarationSourceEnd > 0 107 && fieldDeclaration.declarationSourceStart 108 > methodDeclaration.declarationSourceEnd){ 109 if (this.parent == null){ 110 return this; } else { 112 return this.parent.add(fieldDeclaration, bracketBalanceValue); 113 } 114 } 115 116 if (!foundOpeningBrace){ 117 foundOpeningBrace = true; 118 this.bracketBalance++; 119 } 120 return this; } 123 126 public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { 127 128 129 144 146 if (methodDeclaration.declarationSourceEnd != 0 147 && localDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd){ 148 149 if (this.parent == null) { 150 return this; } else { 152 return this.parent.add(localDeclaration, bracketBalanceValue); 153 } 154 } 155 if (methodBody == null){ 156 Block block = new Block(0); 157 block.sourceStart = methodDeclaration.bodyStart; 158 RecoveredElement currentBlock = this.add(block, 1); 159 if (this.bracketBalance > 0){ 160 for (int i = 0; i < this.bracketBalance - 1; i++){ 161 currentBlock = currentBlock.add(new Block(0), 1); 162 } 163 this.bracketBalance = 1; 164 } 165 return currentBlock.add(localDeclaration, bracketBalanceValue); 166 } 167 return methodBody.add(localDeclaration, bracketBalanceValue, true); 168 } 169 172 public RecoveredElement add(Statement statement, int bracketBalanceValue) { 173 174 176 if (methodDeclaration.declarationSourceEnd != 0 177 && statement.sourceStart > methodDeclaration.declarationSourceEnd){ 178 179 if (this.parent == null) { 180 return this; } else { 182 return this.parent.add(statement, bracketBalanceValue); 183 } 184 } 185 if (methodBody == null){ 186 Block block = new Block(0); 187 block.sourceStart = methodDeclaration.bodyStart; 188 RecoveredElement currentBlock = this.add(block, 1); 189 if (this.bracketBalance > 0){ 190 for (int i = 0; i < this.bracketBalance - 1; i++){ 191 currentBlock = currentBlock.add(new Block(0), 1); 192 } 193 this.bracketBalance = 1; 194 } 195 return currentBlock.add(statement, bracketBalanceValue); 196 } 197 return methodBody.add(statement, bracketBalanceValue, true); 198 } 199 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { 200 201 203 if (methodDeclaration.declarationSourceEnd != 0 204 && typeDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd){ 205 206 if (this.parent == null) { 207 return this; } 209 return this.parent.add(typeDeclaration, bracketBalanceValue); 210 } 211 if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated){ 212 if (methodBody == null){ 213 Block block = new Block(0); 214 block.sourceStart = methodDeclaration.bodyStart; 215 this.add(block, 1); 216 } 217 return methodBody.add(typeDeclaration, bracketBalanceValue, true); 218 } 219 switch (TypeDeclaration.kind(typeDeclaration.modifiers)) { 220 case TypeDeclaration.INTERFACE_DECL : 221 case TypeDeclaration.ANNOTATION_TYPE_DECL : 222 this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1)); 223 if (this.parent == null) { 224 return this; } 226 return this.parent.add(typeDeclaration, bracketBalanceValue); 228 } 229 if (localTypes == null) { 230 localTypes = new RecoveredType[5]; 231 localTypeCount = 0; 232 } else { 233 if (localTypeCount == localTypes.length) { 234 System.arraycopy( 235 localTypes, 236 0, 237 (localTypes = new RecoveredType[2 * localTypeCount]), 238 0, 239 localTypeCount); 240 } 241 } 242 RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); 243 localTypes[localTypeCount++] = element; 244 245 246 if (!foundOpeningBrace){ 247 foundOpeningBrace = true; 248 this.bracketBalance++; 249 } 250 return element; 251 } 252 public boolean bodyStartsAtHeaderEnd(){ 253 return methodDeclaration.bodyStart == methodDeclaration.sourceEnd+1; 254 } 255 258 public ASTNode parseTree(){ 259 return methodDeclaration; 260 } 261 264 public int sourceEnd(){ 265 return this.methodDeclaration.declarationSourceEnd; 266 } 267 public String toString(int tab) { 268 StringBuffer result = new StringBuffer (tabString(tab)); 269 result.append("Recovered method:\n"); this.methodDeclaration.print(tab + 1, result); 271 if (this.localTypes != null) { 272 for (int i = 0; i < this.localTypeCount; i++) { 273 result.append("\n"); result.append(this.localTypes[i].toString(tab + 1)); 275 } 276 } 277 if (this.methodBody != null) { 278 result.append("\n"); result.append(this.methodBody.toString(tab + 1)); 280 } 281 return result.toString(); 282 } 283 286 public void updateBodyStart(int bodyStart){ 287 this.foundOpeningBrace = true; 288 this.methodDeclaration.bodyStart = bodyStart; 289 } 290 public AbstractMethodDeclaration updatedMethodDeclaration(){ 291 292 if (methodBody != null){ 293 Block block = methodBody.updatedBlock(); 294 if (block != null){ 295 methodDeclaration.statements = block.statements; 296 297 298 if (methodDeclaration.isConstructor()) { 299 ConstructorDeclaration constructor = (ConstructorDeclaration)methodDeclaration; 300 if (methodDeclaration.statements != null 301 && methodDeclaration.statements[0] instanceof ExplicitConstructorCall){ 302 constructor.constructorCall = (ExplicitConstructorCall)methodDeclaration.statements[0]; 303 int length = methodDeclaration.statements.length; 304 System.arraycopy( 305 methodDeclaration.statements, 306 1, 307 (methodDeclaration.statements = new Statement[length-1]), 308 0, 309 length-1); 310 } 311 if (constructor.constructorCall == null){ constructor.constructorCall = SuperReference.implicitSuperConstructorCall(); 313 } 314 } 315 } 316 } 317 if (localTypeCount > 0) methodDeclaration.bits |= ASTNode.HasLocalType; 318 return methodDeclaration; 319 } 320 324 public void updateFromParserState(){ 325 if(this.bodyStartsAtHeaderEnd() && this.parent != null){ 327 Parser parser = this.parser(); 328 329 if (parser.listLength > 0 && parser.astLengthPtr > 0){ 331 if (methodDeclaration.sourceEnd == parser.rParenPos) { 332 333 int length = parser.astLengthStack[parser.astLengthPtr]; 335 int astPtr = parser.astPtr - length; 336 boolean canConsume = astPtr >= 0; 337 if(canConsume) { 338 if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { 339 canConsume = false; 340 } 341 for (int i = 1, max = length + 1; i < max; i++) { 342 if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) { 343 canConsume = false; 344 } 345 } 346 } 347 if (canConsume){ 348 parser.consumeMethodHeaderThrowsClause(); 349 } else { 352 parser.listLength = 0; 353 } 354 } else { 355 356 if (parser.currentToken == TokenNameLPAREN || parser.currentToken == TokenNameSEMICOLON){ 357 358 parser.astLengthStack[parser.astLengthPtr] --; 359 parser.astPtr --; 360 parser.listLength --; 361 parser.currentToken = 0; 362 } 363 int argLength = parser.astLengthStack[parser.astLengthPtr]; 364 int argStart = parser.astPtr - argLength + 1; 365 boolean needUpdateRParenPos = parser.rParenPos < parser.lParenPos; 367 MemberValuePair[] memberValuePairs = null; 369 if (argLength > 0 && parser.astStack[parser.astPtr] instanceof MemberValuePair) { 370 System.arraycopy(parser.astStack, argStart, memberValuePairs = new MemberValuePair[argLength], 0, argLength); 371 parser.astLengthPtr--; 372 parser.astPtr -= argLength; 373 374 argLength = parser.astLengthStack[parser.astLengthPtr]; 375 argStart = parser.astPtr - argLength + 1; 376 needUpdateRParenPos = true; 377 } 378 379 int count; 381 for (count = 0; count < argLength; count++){ 382 ASTNode aNode = parser.astStack[argStart+count]; 383 if(aNode instanceof Argument) { 384 Argument argument = (Argument)aNode; 385 386 char[][] argTypeName = argument.type.getTypeName(); 387 if ((argument.modifiers & ~ClassFileConstants.AccFinal) != 0 388 || (argTypeName.length == 1 389 && CharOperation.equals(argTypeName[0], TypeBinding.VOID.sourceName()))){ 390 parser.astLengthStack[parser.astLengthPtr] = count; 391 parser.astPtr = argStart+count-1; 392 parser.listLength = count; 393 parser.currentToken = 0; 394 break; 395 } 396 if (needUpdateRParenPos) parser.rParenPos = argument.sourceEnd + 1; 397 } else { 398 parser.astLengthStack[parser.astLengthPtr] = count; 399 parser.astPtr = argStart+count-1; 400 parser.listLength = count; 401 parser.currentToken = 0; 402 break; 403 } 404 } 405 if (parser.listLength > 0 && parser.astLengthPtr > 0){ 406 407 int length = parser.astLengthStack[parser.astLengthPtr]; 409 int astPtr = parser.astPtr - length; 410 boolean canConsume = astPtr >= 0; 411 if(canConsume) { 412 if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { 413 canConsume = false; 414 } 415 for (int i = 1, max = length + 1; i < max; i++) { 416 if(!(parser.astStack[astPtr + i ] instanceof Argument)) { 417 canConsume = false; 418 } 419 } 420 } 421 if(canConsume) { 422 parser.consumeMethodHeaderRightParen(); 423 424 if (parser.currentElement == this){ methodDeclaration.sourceEnd = methodDeclaration.arguments[methodDeclaration.arguments.length-1].sourceEnd; 426 methodDeclaration.bodyStart = methodDeclaration.sourceEnd+1; 427 parser.lastCheckPoint = methodDeclaration.bodyStart; 428 } 429 } 430 } 431 432 if(memberValuePairs != null) { 433 System.arraycopy(memberValuePairs, 0, parser.astStack, parser.astPtr + 1, memberValuePairs.length); 434 parser.astPtr += memberValuePairs.length; 435 parser.astLengthStack[++parser.astLengthPtr] = memberValuePairs.length; 436 } 437 } 438 } 439 } 440 } 441 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ 442 if(this.methodDeclaration.isAnnotationMethod()) { 443 this.updateSourceEndIfNecessary(braceStart, braceEnd); 444 if(!this.foundOpeningBrace && this.parent != null) { 445 return this.parent.updateOnClosingBrace(braceStart, braceEnd); 446 } 447 return this; 448 } 449 if(this.parent != null && this.parent instanceof RecoveredType) { 450 int modifiers = ((RecoveredType)this.parent).typeDeclaration.modifiers; 451 if (TypeDeclaration.kind(modifiers) == TypeDeclaration.INTERFACE_DECL) { 452 if (!this.foundOpeningBrace) { 453 this.updateSourceEndIfNecessary(braceStart - 1, braceStart - 1); 454 return this.parent.updateOnClosingBrace(braceStart, braceEnd); 455 } 456 } 457 } 458 return super.updateOnClosingBrace(braceStart, braceEnd); 459 } 460 464 public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){ 465 466 467 if (bracketBalance == 0){ 468 472 switch(parser().lastIgnoredToken){ 473 case -1 : 474 case TokenNamethrows : 475 break; 476 default: 477 this.foundOpeningBrace = true; 478 bracketBalance = 1; } 480 } 481 return super.updateOnOpeningBrace(braceStart, braceEnd); 482 } 483 public void updateParseTree(){ 484 this.updatedMethodDeclaration(); 485 } 486 489 public void updateSourceEndIfNecessary(int braceStart, int braceEnd){ 490 if (this.methodDeclaration.declarationSourceEnd == 0) { 491 if(parser().rBraceSuccessorStart >= braceEnd) { 492 this.methodDeclaration.declarationSourceEnd = parser().rBraceEnd; 493 this.methodDeclaration.bodyEnd = parser().rBraceStart; 494 } else { 495 this.methodDeclaration.declarationSourceEnd = braceEnd; 496 this.methodDeclaration.bodyEnd = braceStart - 1; 497 } 498 } 499 } 500 void attach(TypeParameter[] parameters, int startPos) { 501 if(methodDeclaration.modifiers != ClassFileConstants.AccDefault) return; 502 503 int lastParameterEnd = parameters[parameters.length - 1].sourceEnd; 504 505 Parser parser = this.parser(); 506 Scanner scanner = parser.scanner; 507 if(Util.getLineNumber(methodDeclaration.declarationSourceStart, scanner.lineEnds, 0, scanner.linePtr) 508 != Util.getLineNumber(lastParameterEnd, scanner.lineEnds, 0, scanner.linePtr)) return; 509 510 if(parser.modifiersSourceStart > lastParameterEnd 511 && parser.modifiersSourceStart < methodDeclaration.declarationSourceStart) return; 512 513 if (this.methodDeclaration instanceof MethodDeclaration) { 514 ((MethodDeclaration)this.methodDeclaration).typeParameters = parameters; 515 this.methodDeclaration.declarationSourceStart = startPos; 516 } else if (this.methodDeclaration instanceof ConstructorDeclaration){ 517 ((ConstructorDeclaration)this.methodDeclaration).typeParameters = parameters; 518 this.methodDeclaration.declarationSourceStart = startPos; 519 } 520 } 521 } 522 | Popular Tags |