diff options
author | Stephan Herrmann | 2018-04-24 20:37:28 +0000 |
---|---|---|
committer | Stephan Herrmann | 2018-04-26 14:13:30 +0000 |
commit | b9c7228db069a63b5c1805833caad7a4bb92e2ab (patch) | |
tree | 097d4e7279caff00b86c9677f9cebb44e308b2c9 | |
parent | 9dd6d6fc63b82747df87f387f31f1953595ff210 (diff) | |
download | eclipse.jdt.core-b9c7228db069a63b5c1805833caad7a4bb92e2ab.tar.gz eclipse.jdt.core-b9c7228db069a63b5c1805833caad7a4bb92e2ab.tar.xz eclipse.jdt.core-b9c7228db069a63b5c1805833caad7a4bb92e2ab.zip |
Bug 515758 - [navigation] Hyperlinking does not work for (certain)
static methods
Change-Id: Iec7c0ca3ea48a8a3856dcf0e36bccdf0a4304de1
3 files changed, 93 insertions, 35 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java index 01472ffab7..98d18e8b17 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java @@ -276,17 +276,19 @@ public void test495912() { "package xy;\n" + "public class Test {\n" + " {\n" + - " Runnable r = () -> {\n" + - " Integer i;\n" + - " byte b = <SelectOnMessageSend:i.byteValue()>;\n" + - " if (true)\n" + - " {\n" + - " if (false)\n" + - " {\n" + - " }\n" + - " }\n" + - " String s;\n" + - " };\n" + + " {\n" + + " Runnable r = () -> {\n" + + " Integer i;\n" + + " byte b = <SelectOnMessageSend:i.byteValue()>;\n" + + " if (true)\n" + + " {\n" + + " if (false)\n" + + " {\n" + + " }\n" + + " }\n" + + " String s;\n" + + " };\n" + + " }\n" + " }\n" + " public Test() {\n" + " }\n" + @@ -336,19 +338,21 @@ public void test495912a() { "package xy;\n" + "public class Test {\n" + " {\n" + - " Runnable r = () -> {\n" + - " Integer i;\n" + - " byte b = <SelectOnMessageSend:i.byteValue()>;\n" + - " if (true)\n" + + " {\n" + + " Runnable r = () -> {\n" + + " Integer i;\n" + + " byte b = <SelectOnMessageSend:i.byteValue()>;\n" + + " if (true)\n" + + " {\n" + + " if (false)\n" + + " {\n" + + " }\n" + + " }\n" + + " for (int i1;; (i1 < 42); i1 ++) \n" + " {\n" + - " if (false)\n" + - " {\n" + - " }\n" + " }\n" + - " for (int i1;; (i1 < 42); i1 ++) \n" + - " {\n" + - " }\n" + - " };\n" + + " };\n" + + " }\n" + " }\n" + " public Test() {\n" + " }\n" + diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java index 994f117c19..b0d9e3aa30 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 IBM Corporation and others. + * Copyright (c) 2014, 2018 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -2925,4 +2925,36 @@ public void testBug487791b() throws JavaModelException { assertEquals("1st type argument", "Ljava.lang.String;", typeArguments[0]); assertEquals("2nd type argument", "LExample;", typeArguments[1]); } +public void testBug515758() throws JavaModelException { + this.wc = getWorkingCopy( + "Resolve/src/Snippet.java", + "import java.util.function.Function;\n" + + "\n" + + "public class Snippet {\n" + + " void m1() {\n" + + " MyObservable.range(1, 2).groupBy(integer -> {\n" + + " return \"even\";\n" + + " });\n" + + " }\n" + + "\n" + + "}\n" + + "class MyObservable<T> {\n" + + " static MyObservable<Integer> range(int i1, int i2) {\n" + + " return new MyObservable<>();\n" + + " }\n" + + " <K> void groupBy(Function<T, K> func) {\n" + + " }\n" + + "}"); + String str = this.wc.getSource(); + String selection = "range"; + int start = str.indexOf(selection); + int length = selection.length(); + + IJavaElement[] elements = this.wc.codeSelect(start, length); + assertElementsEqual( + "Unexpected elements", + "range(int, int) [in MyObservable [in [Working copy] Snippet.java [in <default> [in src [in Resolve]]]]]", + elements + ); +} } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java index 0daa0709d6..3f60a178fe 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java @@ -78,8 +78,15 @@ public class SelectionParser extends AssistParser { 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 - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693 - private boolean selectionNodeFound; + /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693 + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=515758 + * Records whether and when we found an invocation being selected: + * 0: not found + * 1: found just now + * 2...: inside block (lambda body) within the invocation found before + * Rationale: we really need to complete parsing the invocation for resolving to succeed. + */ + private int selectionNodeFoundLevel = 0; public ASTNode assistNodeParent; // the parent node of assist node /* public fields */ @@ -839,24 +846,39 @@ protected void consumeLocalVariableDeclarationStatement() { this.lastIgnoredToken = -1; } } - if (this.selectionNodeFound) { - this.restartRecovery = true; - } + checkRestartRecovery(); } @Override protected void consumeAssignment() { super.consumeAssignment(); - if (this.selectionNodeFound) { - this.restartRecovery = true; - } + checkRestartRecovery(); } @Override protected void consumeBlockStatement() { super.consumeBlockStatement(); - if (this.selectionNodeFound) { - this.restartRecovery = true; + checkRestartRecovery(); +} +protected void checkRestartRecovery() { + if (this.selectionNodeFoundLevel > 0) { + if (--this.selectionNodeFoundLevel == 0) + this.restartRecovery = true; } } + +@Override +protected void consumeOpenBlock() { + super.consumeOpenBlock(); + if (this.selectionNodeFoundLevel > 0) + this.selectionNodeFoundLevel++; +} + +@Override +protected void consumeBlock() { + super.consumeBlock(); + if (this.selectionNodeFoundLevel > 0) + this.selectionNodeFoundLevel--; +} + @Override protected void consumeMarkerAnnotation(boolean isTypeAnnotation) { int index; @@ -1516,7 +1538,7 @@ protected MessageSend newMessageSend() { if (!this.diet){ // Don't restart recovery, not yet, until variable decl statement has been consumed. // This is to ensure chained method invocations are taken into account for resolution. - this.selectionNodeFound = true; + this.selectionNodeFoundLevel = 1; this.lastIgnoredToken = -1; } @@ -1544,7 +1566,7 @@ protected MessageSend newMessageSendWithTypeArguments() { if (!this.diet){ // Don't restart recovery, not yet, until variable decl statement has been consumed. // This is to ensure chained method invocations are taken into account for resolution. - this.selectionNodeFound = true; + this.selectionNodeFoundLevel = 1; this.lastIgnoredToken = -1; } |