|
Lines 1-12
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 |
|
|
Lines 17-26
Link Here
|
| 17 |
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; |
21 |
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; |
| 18 |
import org.eclipse.jdt.internal.compiler.ast.Argument; |
22 |
import org.eclipse.jdt.internal.compiler.ast.Argument; |
| 19 |
import org.eclipse.jdt.internal.compiler.ast.ASTNode; |
23 |
import org.eclipse.jdt.internal.compiler.ast.ASTNode; |
| 20 |
import org.eclipse.jdt.internal.compiler.ast.Block; |
24 |
import org.eclipse.jdt.internal.compiler.ast.Block; |
| 21 |
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; |
25 |
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; |
|
|
26 |
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; |
| 22 |
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; |
27 |
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; |
| 23 |
import org.eclipse.jdt.internal.compiler.ast.Statement; |
28 |
import org.eclipse.jdt.internal.compiler.ast.Statement; |
| 24 |
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; |
29 |
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; |
| 25 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
30 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| 26 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
31 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
|
Lines 29-39
Link Here
|
| 29 |
|
34 |
|
| 30 |
public Block blockDeclaration; |
35 |
public Block blockDeclaration; |
| 31 |
public RecoveredStatement[] statements; |
36 |
public RecoveredStatement[] statements; |
| 32 |
public int statementCount; |
37 |
public int statementCount; |
| 33 |
public boolean preserveContent = false; |
38 |
public boolean preserveContent = false; |
| 34 |
public RecoveredLocalVariable pendingArgument; |
39 |
public RecoveredLocalVariable [] pendingArguments = null; |
| 35 |
|
40 |
|
| 36 |
int pendingModifiers; |
41 |
int pendingModifiers; |
| 37 |
int pendingModifersSourceStart = -1; |
42 |
int pendingModifersSourceStart = -1; |
| 38 |
RecoveredAnnotation[] pendingAnnotations; |
43 |
RecoveredAnnotation[] pendingAnnotations; |
| 39 |
int pendingAnnotationCount; |
44 |
int pendingAnnotationCount; |
|
Lines 54-63
Link Here
|
| 54 |
return this; // ignore this element |
59 |
return this; // ignore this element |
| 55 |
} |
60 |
} |
| 56 |
} |
61 |
} |
| 57 |
return super.add(methodDeclaration, bracketBalanceValue); |
62 |
return super.add(methodDeclaration, bracketBalanceValue); |
| 58 |
} |
63 |
} |
|
|
64 |
public void addPendingArgument(RecoveredLocalVariable pendingArg) { |
| 65 |
if (this.pendingArguments == null) { |
| 66 |
RecoveredLocalVariable recoveredLocalVariable [] = {pendingArg}; |
| 67 |
this.pendingArguments = recoveredLocalVariable; |
| 68 |
} |
| 69 |
else { |
| 70 |
int length = this.pendingArguments.length; |
| 71 |
System.arraycopy(this.pendingArguments, 0, this.pendingArguments = new RecoveredLocalVariable[length+1], 0, length); |
| 72 |
this.pendingArguments[length] = pendingArg; |
| 73 |
} |
| 74 |
} |
| 59 |
/* |
75 |
/* |
| 60 |
* Record a nested block declaration |
76 |
* Record a nested block declaration |
| 61 |
*/ |
77 |
*/ |
| 62 |
public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { |
78 |
public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { |
| 63 |
resetPendingModifiers(); |
79 |
resetPendingModifiers(); |
|
Lines 70-82
Link Here
|
| 70 |
} |
86 |
} |
| 71 |
|
87 |
|
| 72 |
RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); |
88 |
RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); |
| 73 |
|
89 |
|
| 74 |
// if we have a pending Argument, promote it into the new block |
90 |
// if we have a pending Argument, promote it into the new block |
| 75 |
if (this.pendingArgument != null){ |
91 |
if (this.pendingArguments != null) { |
| 76 |
element.attach(this.pendingArgument); |
92 |
for (int indx = 0; indx < this.pendingArguments.length; indx++) { |
| 77 |
this.pendingArgument = null; |
93 |
element.attach(this.pendingArguments[indx]); |
|
|
94 |
} |
| 95 |
this.pendingArguments = null; |
| 78 |
} |
96 |
} |
| 79 |
if(parser().statementRecoveryActivated) { |
97 |
if(parser().statementRecoveryActivated) { |
| 80 |
addBlockStatement(element); |
98 |
addBlockStatement(element); |
| 81 |
} |
99 |
} |
| 82 |
attach(element); |
100 |
attach(element); |
|
Lines 129-139
Link Here
|
| 129 |
this.pendingModifersSourceStart); |
147 |
this.pendingModifersSourceStart); |
| 130 |
} |
148 |
} |
| 131 |
resetPendingModifiers(); |
149 |
resetPendingModifiers(); |
| 132 |
|
150 |
|
| 133 |
if (localDeclaration instanceof Argument){ |
151 |
if (localDeclaration instanceof Argument){ |
| 134 |
this.pendingArgument = element; |
152 |
addPendingArgument(element); |
| 135 |
return this; |
153 |
return this; |
| 136 |
} |
154 |
} |
| 137 |
|
155 |
|
| 138 |
attach(element); |
156 |
attach(element); |
| 139 |
if (localDeclaration.declarationSourceEnd == 0) return element; |
157 |
if (localDeclaration.declarationSourceEnd == 0) return element; |
|
Lines 277-287
Link Here
|
| 277 |
return result.toString(); |
295 |
return result.toString(); |
| 278 |
} |
296 |
} |
| 279 |
/* |
297 |
/* |
| 280 |
* Rebuild a block from the nested structure which is in scope |
298 |
* Rebuild a block from the nested structure which is in scope |
| 281 |
*/ |
299 |
*/ |
| 282 |
public Block updatedBlock(int depth, Set knownTypes){ |
300 |
public Block updatedBlock(int depth, Set knownTypes) { |
|
|
301 |
return updatedBlock(depth, knownTypes, false); |
| 302 |
} |
| 303 |
public Block updatedBlock(int depth, Set knownTypes, boolean lambdaExpressionExpected) { |
| 283 |
|
304 |
|
| 284 |
// if block was not marked to be preserved or empty, then ignore it |
305 |
// if block was not marked to be preserved or empty, then ignore it |
| 285 |
if (!this.preserveContent || this.statementCount == 0) return null; |
306 |
if (!this.preserveContent || this.statementCount == 0) return null; |
| 286 |
|
307 |
|
| 287 |
Statement[] updatedStatements = new Statement[this.statementCount]; |
308 |
Statement[] updatedStatements = new Statement[this.statementCount]; |
|
Lines 323-335
Link Here
|
| 323 |
|
344 |
|
| 324 |
int lastEnd = this.blockDeclaration.sourceStart; |
345 |
int lastEnd = this.blockDeclaration.sourceStart; |
| 325 |
|
346 |
|
| 326 |
// only collect the non-null updated statements |
347 |
// only collect the non-null updated statements |
| 327 |
for (int i = 0; i < this.statementCount; i++){ |
348 |
for (int i = 0; i < this.statementCount; i++){ |
| 328 |
Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes); |
349 |
boolean lambdaExprInit = i > 0 && lambdaExpressionInitializable(this.statements[i-1]); |
|
|
350 |
Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes, lambdaExprInit); |
| 329 |
if (updatedStatement != null){ |
351 |
if (updatedStatement != null){ |
| 330 |
updatedStatements[updatedCount++] = updatedStatement; |
352 |
LambdaExpression lambdaExpr = getLambdaExpression(updatedStatement); |
|
|
353 |
if (lambdaExprInit && lambdaExpr != null) { |
| 354 |
((LocalDeclaration)updatedStatements[updatedCount-1]).initialization = lambdaExpr; |
| 355 |
} |
| 356 |
else { |
| 357 |
updatedStatements[updatedCount++] = updatedStatement; |
| 358 |
} |
| 331 |
|
359 |
|
| 332 |
if (updatedStatement instanceof LocalDeclaration) { |
360 |
if (updatedStatement instanceof LocalDeclaration) { |
| 333 |
LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement; |
361 |
LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement; |
| 334 |
if(localDeclaration.declarationSourceEnd > lastEnd) { |
362 |
if(localDeclaration.declarationSourceEnd > lastEnd) { |
| 335 |
lastEnd = localDeclaration.declarationSourceEnd; |
363 |
lastEnd = localDeclaration.declarationSourceEnd; |
|
Lines 351-361
Link Here
|
| 351 |
// resize statement collection if necessary |
379 |
// resize statement collection if necessary |
| 352 |
if (updatedCount != this.statementCount){ |
380 |
if (updatedCount != this.statementCount){ |
| 353 |
this.blockDeclaration.statements = new Statement[updatedCount]; |
381 |
this.blockDeclaration.statements = new Statement[updatedCount]; |
| 354 |
System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); |
382 |
System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount); |
| 355 |
} else { |
383 |
} else { |
| 356 |
this.blockDeclaration.statements = updatedStatements; |
384 |
LambdaExpression lambda = null; |
|
|
385 |
if (lambdaExpressionExpected && (lambda = canGetLambdaExpression(updatedStatements, updatedCount)) != null) { |
| 386 |
Statement [] stmt = {lambda}; |
| 387 |
this.blockDeclaration.statements = stmt; |
| 388 |
} |
| 389 |
else { |
| 390 |
this.blockDeclaration.statements = updatedStatements; |
| 391 |
} |
| 357 |
} |
392 |
} |
| 358 |
|
393 |
|
| 359 |
if (this.blockDeclaration.sourceEnd == 0) { |
394 |
if (this.blockDeclaration.sourceEnd == 0) { |
| 360 |
if(lastEnd < bodyEndValue) { |
395 |
if(lastEnd < bodyEndValue) { |
| 361 |
this.blockDeclaration.sourceEnd = bodyEndValue; |
396 |
this.blockDeclaration.sourceEnd = bodyEndValue; |
|
Lines 364-380
Link Here
|
| 364 |
} |
399 |
} |
| 365 |
} |
400 |
} |
| 366 |
|
401 |
|
| 367 |
return this.blockDeclaration; |
402 |
return this.blockDeclaration; |
| 368 |
} |
403 |
} |
|
|
404 |
public LambdaExpression getLambdaExpression (Statement stmnt) { |
| 405 |
if (stmnt instanceof LambdaExpression) { |
| 406 |
return (LambdaExpression)stmnt; |
| 407 |
} |
| 408 |
else if (stmnt instanceof Block && ((Block)stmnt).statements[0] instanceof LambdaExpression) { |
| 409 |
return (LambdaExpression)((Block)stmnt).statements[0]; |
| 410 |
} |
| 411 |
return null; |
| 412 |
} |
| 413 |
public LambdaExpression canGetLambdaExpression (Statement [] statementsArray, int count) { |
| 414 |
for (int indx = 0; indx < count - 1; indx++) { |
| 415 |
if (!(statementsArray[indx] instanceof Argument)) { |
| 416 |
return null; |
| 417 |
} |
| 418 |
} |
| 419 |
Argument [] arguments = new Argument [count-1]; |
| 420 |
System.arraycopy(statementsArray, 0, arguments, 0, count-1); |
| 421 |
return new LambdaExpression(parser().compilationUnit.compilationResult, arguments, statementsArray[count-1]); |
| 422 |
} |
| 369 |
/* |
423 |
/* |
| 370 |
* Rebuild a statement from the nested structure which is in scope |
424 |
* Rebuild a statement from the nested structure which is in scope |
| 371 |
*/ |
425 |
*/ |
| 372 |
public Statement updatedStatement(int depth, Set knownTypes){ |
426 |
public Statement updatedStatement(int depth, Set knownTypes){ |
| 373 |
|
427 |
|
| 374 |
return updatedBlock(depth, knownTypes); |
428 |
return updatedBlock(depth, knownTypes); |
| 375 |
} |
429 |
} |
|
|
430 |
public Statement updatedStatement(int depth, Set knownTypes, boolean lambdaExpressionExpected) { |
| 431 |
|
| 432 |
return lambdaExpressionExpected ? updatedBlock(depth, knownTypes, true) : updatedStatement(depth, knownTypes); |
| 433 |
} |
| 434 |
boolean lambdaExpressionInitializable(RecoveredStatement stmnt) { |
| 435 |
if (stmnt instanceof RecoveredLocalVariable) { |
| 436 |
RecoveredLocalVariable recLocVar = (RecoveredLocalVariable) stmnt; |
| 437 |
return recLocVar.localDeclaration != null && (recLocVar.localDeclaration.bits & ASTNode.IsInitializedByLamdaExpression) != 0; |
| 438 |
} |
| 439 |
return false; |
| 440 |
} |
| 376 |
/* |
441 |
/* |
| 377 |
* A closing brace got consumed, might have closed the current element, |
442 |
* A closing brace got consumed, might have closed the current element, |
| 378 |
* in which case both the currentElement is exited |
443 |
* in which case both the currentElement is exited |
| 379 |
*/ |
444 |
*/ |
| 380 |
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ |
445 |
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ |