Skip to content

Commit

Permalink
Evolving fix for Issue # 1195
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran committed Sep 5, 2023
1 parent 816bc73 commit 359b611
Show file tree
Hide file tree
Showing 29 changed files with 509 additions and 420 deletions.
9 changes: 6 additions & 3 deletions org.eclipse.jdt.core.compiler.batch/grammar/java.g
Original file line number Diff line number Diff line change
Expand Up @@ -1452,15 +1452,18 @@ StatementExpression ::= MethodInvocation
StatementExpression ::= ClassInstanceCreationExpression
/:$readableName Expression:/

IfThenStatement ::= 'if' '(' Expression ')' Statement
PostIfExpression ::= $empty
/.$putCase consumePostIfExpression(); $break ./

IfThenStatement ::= 'if' '(' Expression ')' PostIfExpression Statement
/.$putCase consumeStatementIfNoElse(); $break ./
/:$readableName IfStatement:/

IfThenElseStatement ::= 'if' '(' Expression ')' StatementNoShortIf 'else' Statement
IfThenElseStatement ::= 'if' '(' Expression ')' PostIfExpression StatementNoShortIf 'else' Statement
/.$putCase consumeStatementIfWithElse(); $break ./
/:$readableName IfStatement:/

IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' PostIfExpression StatementNoShortIf 'else' StatementNoShortIf
/.$putCase consumeStatementIfWithElse(); $break ./
/:$readableName IfStatement:/

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ public interface ParserBasicInformation {

ERROR_SYMBOL = 138,
MAX_NAME_LENGTH = 53,
NUM_STATES = 1233,
NUM_STATES = 1235,

NT_OFFSET = 138,
SCOPE_UBOUND = 322,
SCOPE_SIZE = 323,
LA_STATE_OFFSET = 18574,
LA_STATE_OFFSET = 18624,
MAX_LA = 1,
NUM_RULES = 942,
NUM_RULES = 943,
NUM_TERMINALS = 138,
NUM_NON_TERMINALS = 433,
NUM_SYMBOLS = 571,
START_STATE = 1292,
NUM_NON_TERMINALS = 434,
NUM_SYMBOLS = 572,
START_STATE = 1098,
EOFT_SYMBOL = 64,
EOLT_SYMBOL = 64,
ACCEPT_ACTION = 18573,
ERROR_ACTION = 18574;
ACCEPT_ACTION = 18623,
ERROR_ACTION = 18624;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ public void test002() throws JavaModelException {
" public X() {\n" +
" }\n" +
" public @SuppressWarnings(\"preview\") void f(Object obj, boolean b) {\n" +
" String y_;\n" +
" {\n" +
" <SelectOnName:y_>;\n" +
" {\n" +
" if (((x_ instanceof String y_) && (y_.length() > 0)))\n" +
" <SelectOnName:y_>;\n" +
" }\n" +
" }\n" +
"}\n";
Expand Down Expand Up @@ -121,8 +121,8 @@ public void test003() throws JavaModelException {
" public X() {\n" +
" }\n" +
" public @SuppressWarnings(\"preview\") void f(Object obj, boolean b) {\n" +
" String y_;\n" +
" <SelectOnName:y_>;\n" +
" if (((x_ instanceof String y_) && <SelectOnName:y_>))\n" +
" ;\n" +
" }\n" +
"}\n";
String expectedReplacedSource = "y_";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2994,4 +2994,27 @@ public void testGH1264() throws Exception {
elements
);
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/1195
// Open declaration results in ClassCastException: LocalDeclaration cannot be cast to LambdaExpression
public void testGH1195() throws Exception {
this.wc = getWorkingCopy(
"Resolve/src/Reproducer.java",
"import java.util.function.Predicate;\n" +
"\n" +
"public class Reproducer {\n" +
"\n" +
" private final Predicate<Object> predicate =\n" +
" input -> (input instanceof String withoutThisVariableNameThereIsNoError);\n" +
"}\n");
String str = this.wc.getSource();
String selection = "predicate";
int start = str.indexOf(selection);
int length = selection.length();
IJavaElement[] elements = this.wc.codeSelect(start, length);
assertElementsEqual(
"Unexpected elements",
"predicate [in Reproducer [in [Working copy] Reproducer.java [in <default> [in src [in Resolve]]]]]",
elements
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
Expand Down Expand Up @@ -412,41 +411,7 @@ public boolean visit(TypePattern pattern, BlockScope scope) {
this.lastCheckPoint = importRef.declarationSourceEnd + 1;
}
}
// This is copy of the code that processes astStack early in this method
for (int i = 0; i <= this.expressionPtr; i++, lastNode = node) {
node = this.expressionStack[i];
if (node == null || !(node instanceof InstanceOfExpression)) continue;
/* check for intermediate block creation, so recovery can properly close them afterwards */
int nodeStart = node.sourceStart;
for (int j = blockIndex; j <= this.realBlockPtr; j++){
if (this.blockStarts[j] >= 0) {
if (this.blockStarts[j] > nodeStart){
blockIndex = j; // shift the index to the new block
break;
}
if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
block = new Block(0);
block.sourceStart = lastStart = this.blockStarts[j];
element = element.add(block, 1);
}
} else {
if (-this.blockStarts[j] > nodeStart){
blockIndex = j; // shift the index to the new block
break;
}
block = new Block(0);
block.sourceStart = lastStart = -this.blockStarts[j];
element = element.add(block, 1);
}
blockIndex = j+1; // shift the index to the new block
}

InstanceOfExpression pattern = (InstanceOfExpression) node;
LocalDeclaration local = pattern.elementVariable;
if (local != null)
element = element.add(local, 0);
continue;
}
if (this.currentToken == TokenNameRBRACE) {
if (isIndirectlyInsideLambdaExpression())
this.ignoreNextClosingBrace = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.codeassist.impl.AssistParser;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
Expand All @@ -37,10 +38,12 @@
import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.GuardedPattern;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
Expand All @@ -51,6 +54,7 @@
import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
import org.eclipse.jdt.internal.compiler.ast.Pattern;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.RecordPattern;
Expand Down Expand Up @@ -84,6 +88,10 @@ public class SelectionParser extends AssistParser {
protected static final int K_BETWEEN_CASE_AND_COLONORARROW = SELECTION_PARSER + 1; // whether we are inside a block
protected static final int K_INSIDE_RETURN_STATEMENT = SELECTION_PARSER + 2; // whether we are between the keyword 'return' and the end of a return statement
protected static final int K_CAST_STATEMENT = SELECTION_PARSER + 3; // whether we are between ')' and the end of a cast statement
protected static final int K_INSIDE_THEN_STATEMENT = SELECTION_PARSER + 4; // whether we are in the then statement
protected static final int K_INSIDE_ELSE_STATEMENT = SELECTION_PARSER + 5; // whether we are in the else statement
protected static final int K_POST_AND_AND = SELECTION_PARSER + 6;
protected static final int K_POST_OR_OR = SELECTION_PARSER + 7;

/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=515758
Expand Down Expand Up @@ -207,6 +215,42 @@ private void buildMoreCompletionContext(Expression expression) {
break nextElement;
}
}
int i = this.elementPtr;
Statement orphan = expression;
Statement thenStat = null;
Statement elseStat = null;
Expression right = expression;
Expression left = null;
boolean wrapInIf = false;
while(i > -1) {
if (this.elementKindStack[i] == K_POST_AND_AND) {
left = this.expressionStack[this.elementInfoStack[i]];
right = new AND_AND_Expression(
left,
right,
AND_AND);
wrapInIf = true;
} else if (this.elementKindStack[i] == K_POST_OR_OR) {
left = this.expressionStack[this.elementInfoStack[i]];
right = new OR_OR_Expression(
left,
right,
OR_OR);
wrapInIf = true;
} else if (this.elementKindStack[i] == K_INSIDE_ELSE_STATEMENT) {
thenStat = (Statement) this.astStack[this.elementInfoStack[i]];
elseStat = orphan;
} else if (this.elementKindStack[i] == K_INSIDE_THEN_STATEMENT) {
Expression e = this.expressionStack[this.elementInfoStack[i]];
if (thenStat == null) thenStat = orphan;
parentNode = orphan = new IfStatement(e, thenStat, elseStat, 0, 0);
}
i--;
}
if (wrapInIf) {
parentNode = orphan = new IfStatement(right, new EmptyStatement(0, 0), null, 0, 0);
}

// Do not add assist node/parent into the recovery system if we are inside a lambda. The lambda will be fully recovered including the containing statement and added.
if (lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) < 0) {
if(parentNode != null) {
Expand Down Expand Up @@ -768,6 +812,31 @@ protected void consumeFormalParameter(boolean isVarArgs) {
this.listLength++;
}
}
@Override
protected void consumePostIfExpression() {
super.consumePostIfExpression();
pushOnElementStack(K_INSIDE_THEN_STATEMENT, this.expressionPtr);
}

@Override
protected void consumeStatementIfNoElse() {
super.consumeStatementIfNoElse();
if (topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_INSIDE_THEN_STATEMENT){
popElement(K_INSIDE_THEN_STATEMENT);
}
}

@Override
protected void consumeStatementIfWithElse() {
super.consumeStatementIfWithElse();
if (topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_INSIDE_ELSE_STATEMENT){
popElement(K_INSIDE_ELSE_STATEMENT);
}
if (topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_INSIDE_THEN_STATEMENT){
popElement(K_INSIDE_THEN_STATEMENT);
}
}

@Override
protected void consumeInsideCastExpression() {
super.consumeInsideCastExpression();
Expand Down Expand Up @@ -838,20 +907,11 @@ protected void consumeInstanceOfExpressionWithName() {
if (length > 0) {
Pattern pattern = (Pattern) this.patternStack[this.patternPtr--];
pushOnExpressionStack(getUnspecifiedReferenceOptimized());
consumePatternInsideInstanceof(pattern);
if (this.expressionStack[this.expressionPtr] != this.assistNode) {
// Push only when the selection node is not the expression of this
// pattern matching instanceof expression
LocalDeclaration patternVariableIntroduced = pattern.getPatternVariable();
if (patternVariableIntroduced != null) {
// filter out patternVariableIntroduced based on current selection if there is an assist node
if (this.assistNode == null || (this.selectionStart <= patternVariableIntroduced.sourceStart
&& this.selectionEnd >= patternVariableIntroduced.sourceEnd)) {
if(!(pattern instanceof RecordPattern))
pushOnAstStack(patternVariableIntroduced);
}
}
if ((this.selectionStart >= pattern.sourceStart)
&& (this.selectionEnd <= pattern.sourceEnd)) {
this.isOrphanCompletionNode = true;
this.restartRecovery = true;
this.lastIgnoredToken = -1;
}
Expand Down Expand Up @@ -921,6 +981,25 @@ protected void consumeAssignment() {
super.consumeAssignment();
checkRestartRecovery();
}

@Override
protected void consumeBinaryExpression(int op) {
super.consumeBinaryExpression(op);
if (op == AND_AND)
popElement(K_POST_AND_AND);
else if (op == OR_OR)
popElement(K_POST_OR_OR);
}

@Override
protected void consumeBinaryExpressionWithName(int op) {
super.consumeBinaryExpressionWithName(op);
if (op == AND_AND)
popElement(K_POST_AND_AND);
else if (op == OR_OR)
popElement(K_POST_OR_OR);
}

@Override
protected void consumeBlockStatement() {
super.consumeBlockStatement();
Expand Down Expand Up @@ -1352,6 +1431,17 @@ protected void consumeToken(int token) {
break;
}
break;
case TokenNameelse:
if (topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_INSIDE_THEN_STATEMENT) {
pushOnElementStack(K_INSIDE_ELSE_STATEMENT, this.astPtr);
}
break;
case TokenNameAND_AND:
pushOnElementStack(K_POST_AND_AND, this.expressionPtr);
break;
case TokenNameOR_OR:
pushOnElementStack(K_POST_OR_OR, this.expressionPtr);
break;
}
}
}
Expand Down

0 comments on commit 359b611

Please sign in to comment.