|
Lines 1-26
Link Here
|
| 1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
| 2 |
* Copyright (c) 2000, 2009 IBM Corporation and others. |
2 |
* Copyright (c) 2000, 2013 IBM Corporation and others. |
| 3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
| 4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
| 5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
| 7 |
* |
7 |
* |
|
|
8 |
* This is an implementation of an early-draft specification developed under the Java |
| 9 |
* Community Process (JCP) and is made available for testing and evaluation purposes |
| 10 |
* only. The code is not compatible with any specification of the JCP. |
| 11 |
* |
| 8 |
* Contributors: |
12 |
* Contributors: |
| 9 |
* IBM Corporation - initial API and implementation |
13 |
* IBM Corporation - initial API and implementation |
| 10 |
*******************************************************************************/ |
14 |
*******************************************************************************/ |
| 11 |
package org.eclipse.jdt.internal.compiler.parser; |
15 |
package org.eclipse.jdt.internal.compiler.parser; |
| 12 |
|
16 |
|
| 13 |
import java.util.HashSet; |
17 |
import java.util.HashSet; |
| 14 |
import java.util.Set; |
18 |
import java.util.Set; |
| 15 |
|
19 |
|
| 16 |
import org.eclipse.jdt.core.compiler.*; |
20 |
import org.eclipse.jdt.core.compiler.*; |
|
|
21 |
import org.eclipse.jdt.internal.codeassist.impl.AssistParser; |
| 17 |
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; |
22 |
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; |
| 18 |
import org.eclipse.jdt.internal.compiler.ast.Argument; |
23 |
import org.eclipse.jdt.internal.compiler.ast.Argument; |
| 19 |
import org.eclipse.jdt.internal.compiler.ast.ASTNode; |
24 |
import org.eclipse.jdt.internal.compiler.ast.ASTNode; |
| 20 |
import org.eclipse.jdt.internal.compiler.ast.Block; |
25 |
import org.eclipse.jdt.internal.compiler.ast.Block; |
| 21 |
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; |
26 |
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; |
|
|
27 |
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; |
| 22 |
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; |
28 |
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; |
| 23 |
import org.eclipse.jdt.internal.compiler.ast.Statement; |
29 |
import org.eclipse.jdt.internal.compiler.ast.Statement; |
| 24 |
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; |
30 |
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; |
| 25 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
31 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| 26 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
32 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
|
Lines 29-39
Link Here
|
| 29 |
|
35 |
|
| 30 |
public Block blockDeclaration; |
36 |
public Block blockDeclaration; |
| 31 |
public RecoveredStatement[] statements; |
37 |
public RecoveredStatement[] statements; |
| 32 |
public int statementCount; |
38 |
public int statementCount; |
| 33 |
public boolean preserveContent = false; |
39 |
public boolean preserveContent = false; |
| 34 |
public RecoveredLocalVariable pendingArgument; |
40 |
public RecoveredLocalVariable [] pendingArguments = null; |
| 35 |
|
41 |
|
| 36 |
int pendingModifiers; |
42 |
int pendingModifiers; |
| 37 |
int pendingModifersSourceStart = -1; |
43 |
int pendingModifersSourceStart = -1; |
| 38 |
RecoveredAnnotation[] pendingAnnotations; |
44 |
RecoveredAnnotation[] pendingAnnotations; |
| 39 |
int pendingAnnotationCount; |
45 |
int pendingAnnotationCount; |
|
Lines 54-63
Link Here
|
| 54 |
return this; // ignore this element |
60 |
return this; // ignore this element |
| 55 |
} |
61 |
} |
| 56 |
} |
62 |
} |
| 57 |
return super.add(methodDeclaration, bracketBalanceValue); |
63 |
return super.add(methodDeclaration, bracketBalanceValue); |
| 58 |
} |
64 |
} |
|
|
65 |
public void addPendingArgument(RecoveredLocalVariable pendingArg) { |
| 66 |
if (this.pendingArguments == null) { |
| 67 |
RecoveredLocalVariable recoveredLocalVariable [] = {pendingArg}; |
| 68 |
this.pendingArguments = recoveredLocalVariable; |
| 69 |
} |
| 70 |
else { |
| 71 |
int length = this.pendingArguments.length; |
| 72 |
System.arraycopy(this.pendingArguments, 0, this.pendingArguments = new RecoveredLocalVariable[length+1], 0, length); |
| 73 |
this.pendingArguments[length] = pendingArg; |
| 74 |
} |
| 75 |
} |
| 59 |
/* |
76 |
/* |
| 60 |
* Record a nested block declaration |
77 |
* Record a nested block declaration |
| 61 |
*/ |
78 |
*/ |
| 62 |
public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { |
79 |
public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { |
| 63 |
resetPendingModifiers(); |
80 |
resetPendingModifiers(); |
|
Lines 70-82
Link Here
|
| 70 |
} |
87 |
} |
| 71 |
|
88 |
|
| 72 |
RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); |
89 |
RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); |
| 73 |
|
90 |
|
| 74 |
// if we have a pending Argument, promote it into the new block |
91 |
// if we have a pending Argument, promote it into the new block |
| 75 |
if (this.pendingArgument != null){ |
92 |
if (this.pendingArguments != null) { |
| 76 |
element.attach(this.pendingArgument); |
93 |
for (int indx = 0; indx < this.pendingArguments.length; indx++) { |
| 77 |
this.pendingArgument = null; |
94 |
element.attach(this.pendingArguments[indx]); |
|
|
95 |
} |
| 96 |
this.pendingArguments = null; |
| 78 |
} |
97 |
} |
| 79 |
if(parser().statementRecoveryActivated) { |
98 |
if(parser().statementRecoveryActivated) { |
| 80 |
addBlockStatement(element); |
99 |
addBlockStatement(element); |
| 81 |
} |
100 |
} |
| 82 |
attach(element); |
101 |
attach(element); |
|
Lines 129-139
Link Here
|
| 129 |
this.pendingModifersSourceStart); |
148 |
this.pendingModifersSourceStart); |
| 130 |
} |
149 |
} |
| 131 |
resetPendingModifiers(); |
150 |
resetPendingModifiers(); |
| 132 |
|
151 |
|
| 133 |
if (localDeclaration instanceof Argument){ |
152 |
if (localDeclaration instanceof Argument){ |
| 134 |
this.pendingArgument = element; |
153 |
if (((Argument)localDeclaration).hasElidedType()) { |
|
|
154 |
RecoveredLambdaExpression rLexp = new RecoveredLambdaExpression(new Block(0), this, bracketBalanceValue); |
| 155 |
Parser currParser = parser(); |
| 156 |
if (currParser instanceof AssistParser) { |
| 157 |
AssistParser aParser = (AssistParser)currParser; |
| 158 |
rLexp.sentMessage = aParser.collectLambdaExpressionInformationFromParserWithoutDisturbingStacks(); |
| 159 |
rLexp.insertLambdaArgument((Argument)localDeclaration); |
| 160 |
rLexp.insertLambdaArgument(aParser.getLambdaArgumentsOnwards((Argument)localDeclaration)); |
| 161 |
} |
| 162 |
attach(rLexp); |
| 163 |
return rLexp; |
| 164 |
} |
| 165 |
addPendingArgument(element); |
| 135 |
return this; |
166 |
return this; |
| 136 |
} |
167 |
} |
| 137 |
|
168 |
|
| 138 |
attach(element); |
169 |
attach(element); |
| 139 |
if (localDeclaration.declarationSourceEnd == 0) return element; |
170 |
if (localDeclaration.declarationSourceEnd == 0) return element; |
|
Lines 277-287
Link Here
|
| 277 |
return result.toString(); |
308 |
return result.toString(); |
| 278 |
} |
309 |
} |
| 279 |
/* |
310 |
/* |
| 280 |
* Rebuild a block from the nested structure which is in scope |
311 |
* Rebuild a block from the nested structure which is in scope |
| 281 |
*/ |
312 |
*/ |
| 282 |
public Block updatedBlock(int depth, Set knownTypes){ |
313 |
public Block updatedBlock(int depth, Set knownTypes) { |
|
|
314 |
return updatedBlock(depth, knownTypes, false); |
| 315 |
} |
| 316 |
public Block updatedBlock(int depth, Set knownTypes, boolean lambdaExpressionExpected) { |
| 283 |
|
317 |
|
| 284 |
// if block was not marked to be preserved or empty, then ignore it |
318 |
// if block was not marked to be preserved or empty, then ignore it |
| 285 |
if (!this.preserveContent || this.statementCount == 0) return null; |
319 |
if (!this.preserveContent || this.statementCount == 0) return null; |
| 286 |
|
320 |
|
| 287 |
Statement[] updatedStatements = new Statement[this.statementCount]; |
321 |
Statement[] updatedStatements = new Statement[this.statementCount]; |
|
Lines 323-335
Link Here
|
| 323 |
|
357 |
|
| 324 |
int lastEnd = this.blockDeclaration.sourceStart; |
358 |
int lastEnd = this.blockDeclaration.sourceStart; |
| 325 |
|
359 |
|
| 326 |
// only collect the non-null updated statements |
360 |
// only collect the non-null updated statements |
| 327 |
for (int i = 0; i < this.statementCount; i++){ |
361 |
for (int i = 0; i < this.statementCount; i++){ |
| 328 |
Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes); |
362 |
boolean lambdaExprInit = i > 0 && lambdaExpressionInitializable(this.statements[i-1]); |
|
|
363 |
Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes, lambdaExprInit); |
| 329 |
if (updatedStatement != null){ |
364 |
if (updatedStatement != null){ |
| 330 |
updatedStatements[updatedCount++] = updatedStatement; |
365 |
LambdaExpression lambdaExpr = getLambdaExpression(updatedStatement); |
|
|
366 |
if (lambdaExprInit && lambdaExpr != null) { |
| 367 |
((LocalDeclaration)updatedStatements[updatedCount-1]).initialization = lambdaExpr; |
| 368 |
} |
| 369 |
else { |
| 370 |
updatedStatements[updatedCount++] = updatedStatement; |
| 371 |
} |
| 331 |
|
372 |
|
| 332 |
if (updatedStatement instanceof LocalDeclaration) { |
373 |
if (updatedStatement instanceof LocalDeclaration) { |
| 333 |
LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement; |
374 |
LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement; |
| 334 |
if(localDeclaration.declarationSourceEnd > lastEnd) { |
375 |
if(localDeclaration.declarationSourceEnd > lastEnd) { |
| 335 |
lastEnd = localDeclaration.declarationSourceEnd; |
376 |
lastEnd = localDeclaration.declarationSourceEnd; |
|
Lines 351-361
Link Here
|
| 351 |
// resize statement collection if necessary |
392 |
// resize statement collection if necessary |
| 352 |
if (updatedCount != this.statementCount){ |
393 |
if (updatedCount != this.statementCount){ |
| 353 |
this.blockDeclaration.statements = new Statement[updatedCount]; |
394 |
this.blockDeclaration.statements = new Statement[updatedCount]; |
| 354 |
System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); |
395 |
System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); |
| 355 |
} else { |
396 |
} else { |
| 356 |
this.blockDeclaration.statements = updatedStatements; |
397 |
LambdaExpression lambda = null; |
|
|
398 |
if (lambdaExpressionExpected && !(updatedStatements[0] instanceof LambdaExpression) && (lambda = canGetLambdaExpression(updatedStatements, updatedCount)) != null) { |
| 399 |
Statement [] stmt = {lambda}; |
| 400 |
this.blockDeclaration.statements = stmt; |
| 401 |
} |
| 402 |
else { |
| 403 |
this.blockDeclaration.statements = updatedStatements; |
| 404 |
} |
| 357 |
} |
405 |
} |
| 358 |
|
406 |
|
| 359 |
if (this.blockDeclaration.sourceEnd == 0) { |
407 |
if (this.blockDeclaration.sourceEnd == 0) { |
| 360 |
if(lastEnd < bodyEndValue) { |
408 |
if(lastEnd < bodyEndValue) { |
| 361 |
this.blockDeclaration.sourceEnd = bodyEndValue; |
409 |
this.blockDeclaration.sourceEnd = bodyEndValue; |
|
Lines 364-380
Link Here
|
| 364 |
} |
412 |
} |
| 365 |
} |
413 |
} |
| 366 |
|
414 |
|
| 367 |
return this.blockDeclaration; |
415 |
return this.blockDeclaration; |
| 368 |
} |
416 |
} |
|
|
417 |
public LambdaExpression getLambdaExpression (Statement stmnt) { |
| 418 |
if (stmnt instanceof LambdaExpression) { |
| 419 |
return (LambdaExpression)stmnt; |
| 420 |
} |
| 421 |
else if (stmnt instanceof Block && ((Block)stmnt).statements[0] instanceof LambdaExpression) { |
| 422 |
return (LambdaExpression)((Block)stmnt).statements[0]; |
| 423 |
} |
| 424 |
return null; |
| 425 |
} |
| 426 |
public LambdaExpression canGetLambdaExpression (Statement [] statementsArray, int count) { |
| 427 |
for (int indx = 0; indx < count - 1; indx++) { |
| 428 |
if (!(statementsArray[indx] instanceof Argument)) { |
| 429 |
return null; |
| 430 |
} |
| 431 |
} |
| 432 |
Argument [] arguments = new Argument [count-1]; |
| 433 |
System.arraycopy(statementsArray, 0, arguments, 0, count-1); |
| 434 |
return new LambdaExpression(parser().compilationUnit.compilationResult, arguments, statementsArray[count-1]); |
| 435 |
} |
| 369 |
/* |
436 |
/* |
| 370 |
* Rebuild a statement from the nested structure which is in scope |
437 |
* Rebuild a statement from the nested structure which is in scope |
| 371 |
*/ |
438 |
*/ |
| 372 |
public Statement updatedStatement(int depth, Set knownTypes){ |
439 |
public Statement updatedStatement(int depth, Set knownTypes){ |
| 373 |
|
440 |
|
| 374 |
return updatedBlock(depth, knownTypes); |
441 |
return updatedBlock(depth, knownTypes); |
| 375 |
} |
442 |
} |
|
|
443 |
public Statement updatedStatement(int depth, Set knownTypes, boolean lambdaExpressionExpected) { |
| 444 |
|
| 445 |
return lambdaExpressionExpected ? updatedBlock(depth, knownTypes, true) : updatedStatement(depth, knownTypes); |
| 446 |
} |
| 447 |
boolean lambdaExpressionInitializable(RecoveredStatement stmnt) { |
| 448 |
if (stmnt instanceof RecoveredLocalVariable) { |
| 449 |
RecoveredLocalVariable recLocVar = (RecoveredLocalVariable) stmnt; |
| 450 |
return recLocVar.localDeclaration != null && (recLocVar.localDeclaration.bits & ASTNode.IsInitializedByLamdaExpression) != 0; |
| 451 |
} |
| 452 |
return false; |
| 453 |
} |
| 376 |
/* |
454 |
/* |
| 377 |
* A closing brace got consumed, might have closed the current element, |
455 |
* A closing brace got consumed, might have closed the current element, |
| 378 |
* in which case both the currentElement is exited |
456 |
* in which case both the currentElement is exited |
| 379 |
*/ |
457 |
*/ |
| 380 |
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ |
458 |
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ |