diff options
author | Stephan Herrmann | 2018-04-21 13:05:32 +0000 |
---|---|---|
committer | Stephan Herrmann | 2018-04-21 15:26:07 +0000 |
commit | 345e42a611307a2681fbe3027e3d89a313222e16 (patch) | |
tree | fd9c47575f0042513a034128652a569c8dd832d0 | |
parent | ea689a4af26390201617f298fb17b50a48435f21 (diff) | |
download | eclipse.jdt.core-345e42a611307a2681fbe3027e3d89a313222e16.tar.gz eclipse.jdt.core-345e42a611307a2681fbe3027e3d89a313222e16.tar.xz eclipse.jdt.core-345e42a611307a2681fbe3027e3d89a313222e16.zip |
properly
- recovery for the block of a ForeachStatement
Change-Id: I0fb553f21eaf48ca02e3b003849a0cf6f59873b0
6 files changed, 90 insertions, 19 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/GenericsCompletionParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/GenericsCompletionParserTest.java index 37256a874c..b22cfb90ec 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/GenericsCompletionParserTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/GenericsCompletionParserTest.java @@ -8111,10 +8111,10 @@ public void test0167_Method(){ " }\n" + " void foo() {\n" + " List<Integer> cont;\n" + - " Integer i;\n" + - " {\n" + - " <CompleteOnName:i.>;\n" + - " }\n" + + " for (Integer i : cont) \n" + + " {\n" + + " <CompleteOnName:i.>;\n" + + " }\n" + " }\n" + "}\n"; @@ -10086,10 +10086,10 @@ public void test0202_Method(){ " public Test() {\n" + " }\n" + " void bar() {\n" + - " Entry entry;\n" + - " {\n" + - " <CompleteOnName:entry.>;\n" + - " }\n" + + " for (Entry entry : (Set<Entry>) var) \n" + + " {\n" + + " <CompleteOnName:entry.>;\n" + + " }\n" + " }\n" + "}\n"; @@ -10164,10 +10164,10 @@ public void test0203_Method(){ " public Test() {\n" + " }\n" + " void bar() {\n" + - " Entry entry;\n" + - " {\n" + - " <CompleteOnName:entry.>;\n" + - " }\n" + + " for (Entry entry : (ZZZ<YYY>.Set<Entry>) var) \n" + + " {\n" + + " <CompleteOnName:entry.>;\n" + + " }\n" + " }\n" + "}\n"; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests10.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests10.java index 8ff3ac113e..d82b172282 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests10.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests10.java @@ -291,7 +291,7 @@ public void testBug532476b() throws JavaModelException { "}", "i_"); assertResults( - "i_jkl[LOCAL_VARIABLE_REF]{i_jkl, null, Ljava.lang.Object;, i_jkl, null, " + (R_DEFAULT + 22) + "}", + "i_jkl[LOCAL_VARIABLE_REF]{i_jkl, null, Ljava.lang.String;, i_jkl, null, " + (R_DEFAULT + 22) + "}", result.proposals); } public void testBug532476c() throws JavaModelException { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeResolveTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeResolveTests.java index 9480c8a582..80f3795f92 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeResolveTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeResolveTests.java @@ -1446,8 +1446,7 @@ public void testBug533884a() throws Exception { deleteProject("P"); } } -// disabled: SelectionParser drops the ForeachStatement :( -public void _testBug533884b() throws Exception { +public void testBug533884b() throws Exception { if (!isJRE9) return; try { createJava10Project("P", new String[] {"src"}); @@ -1475,4 +1474,31 @@ public void _testBug533884b() throws Exception { deleteProject("P"); } } +public void testBug533884c() throws Exception { + try { + createJava10Project("P", new String[] {"src"}); + String source = "package p;\n" + + "import java.io.*;\n" + + "public class X {\n" + + " void bar(File file) {\n" + + " try (var rc = new FileInputStream(file)) { \n" + + " System.err.println(rc.read());\n" + // <= select this occurrence of 'rc' + " }\n" + + " }\n" + + "\n" + + "}\n"; + createFolder("/P/src/p"); + createFile("/P/src/p/X.java", source); + waitForAutoBuild(); + + ICompilationUnit unit = getCompilationUnit("/P/src/p/X.java"); + String select = "rc"; + IJavaElement[] elements = unit.codeSelect(source.lastIndexOf(select), select.length()); + assertEquals("should not be empty", 1, elements.length); + ILocalVariable variable = (ILocalVariable) elements[0]; + assertEquals("incorrect type", "Ljava.io.FileInputStream;", variable.getTypeSignature()); + } finally { + deleteProject("P"); + } +} } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java index d6ff6c7bc5..afc4777be5 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java @@ -231,9 +231,6 @@ public RecoveredElement buildInitialRecoveryState(){ ASTNode node = null, lastNode = null; for (int i = 0; i <= this.astPtr; i++, lastNode = node) { node = this.astStack[i]; - if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) { - node = ((ForeachStatement)node).elementVariable; - } /* check for intermediate block creation, so recovery can properly close them afterwards */ int nodeStart = node.sourceStart; for (int j = blockIndex; j <= this.realBlockPtr; j++){ @@ -334,6 +331,9 @@ public RecoveredElement buildInitialRecoveryState(){ element.add(stmt, 0); this.lastCheckPoint = stmt.sourceEnd + 1; this.isOrphanCompletionNode = false; + } else if ((stmt instanceof ForeachStatement) && ((ForeachStatement) stmt).action == null) { + element = element.add(stmt, 0); + this.lastCheckPoint = stmt.sourceEnd + 1; } } continue; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java index 7f6bd94c62..ea8f2b8022 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -169,9 +170,16 @@ public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean del RecoveredStatement element = new RecoveredStatement(stmt, this, bracketBalanceValue); attach(element); - if (stmt.sourceEnd == 0) return element; + if (!isEndKnown(stmt)) return element; return this; } +boolean isEndKnown(Statement stmt) { + if (stmt instanceof ForeachStatement) { + if (((ForeachStatement) stmt).action == null) + return false; + } + return stmt.sourceEnd != 0; +} /* * Addition of a type to an initializer (act like inside method body) */ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java index 775a88703b..ca5757d728 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java @@ -17,12 +17,15 @@ import java.util.HashSet; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.Block; +import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; public class RecoveredStatement extends RecoveredElement { public Statement statement; + RecoveredBlock nestedBlock; public RecoveredStatement(Statement statement, RecoveredElement parent, int bracketBalance){ super(parent, bracketBalance); @@ -48,6 +51,10 @@ public String toString(int tab){ return tabString(tab) + "Recovered statement:\n" + this.statement.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$ } public Statement updatedStatement(int depth, Set<TypeDeclaration> knownTypes){ + if (this.nestedBlock != null) { + this.nestedBlock.updatedStatement(depth, knownTypes); + // block has already been assigned in its parent statement + } return this.statement; } @Override @@ -70,4 +77,34 @@ public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){ } return this; } +@Override +public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { + if (this.statement instanceof ForeachStatement) { + ForeachStatement foreach = (ForeachStatement) this.statement; + + // see RecoveredBlock.add(Block, int): + resetPendingModifiers(); + + /* do not consider a nested block starting passed the block end (if set) + it must be belonging to an enclosing block */ + if (foreach.sourceEnd != 0 + && foreach.action != null // if action is unassigned then foreach.sourceEnd is not yet the real end. + && nestedBlockDeclaration.sourceStart > foreach.sourceEnd) { + return this.parent.add(nestedBlockDeclaration, bracketBalanceValue); + } + foreach.action = nestedBlockDeclaration; + + RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); + + if(parser().statementRecoveryActivated) { + addBlockStatement(element); + } + this.nestedBlock = element; + + if (nestedBlockDeclaration.sourceEnd == 0) return element; + return this; + } else { + return super.add(nestedBlockDeclaration, bracketBalanceValue); + } +} } |