Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2015-03-01 01:11:09 +0000
committerStephan Herrmann2015-04-27 20:47:34 +0000
commit594ed91e555d1955d9ad67626570809adfd08aaf (patch)
treef62e09294df4e1b81df973558b18441363b138b9
parent26b94285bfb2729a6716d2969c23f07d1464c95e (diff)
downloadeclipse.jdt.ui-594ed91e555d1955d9ad67626570809adfd08aaf.tar.gz
eclipse.jdt.ui-594ed91e555d1955d9ad67626570809adfd08aaf.tar.xz
eclipse.jdt.ui-594ed91e555d1955d9ad67626570809adfd08aaf.zip
Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
Change-Id: Ie059c052195c2127321bfae2aec215917987fb38 Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
-rw-r--r--org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/AbstractBindingLabelsTest.java161
-rw-r--r--org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabels18Test.java348
-rw-r--r--org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabelsTest.java771
-rw-r--r--org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/CoreTests.java2
-rw-r--r--org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/JavaElementLabelsTest18.java32
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java15
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java48
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/BindingLinkedLabelComposer.java791
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java4
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java31
10 files changed, 2196 insertions, 7 deletions
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/AbstractBindingLabelsTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/AbstractBindingLabelsTest.java
new file mode 100644
index 0000000000..9f705d6ced
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/AbstractBindingLabelsTest.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.core;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.IBinding;
+
+import org.eclipse.jdt.ui.PreferenceConstants;
+
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
+
+public abstract class AbstractBindingLabelsTest extends CoreTests {
+
+ public AbstractBindingLabelsTest(String name) {
+ super(name);
+ }
+
+ protected IJavaProject fJProject1;
+ protected boolean fHaveSource= true;
+
+ protected void setUp() throws Exception {
+ fJProject1= ProjectTestSetup.getProject();
+
+ IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+ store.setValue(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES, false);
+ }
+
+
+ protected void tearDown() throws Exception {
+ JavaProjectHelper.clear(fJProject1, ProjectTestSetup.getDefaultClasspath());
+ }
+
+ protected String getBindingLabel(IJavaElement elem, long flags) {
+ ASTParser parser= ASTParser.newParser(AST.JLS8);
+ parser.setResolveBindings(true);
+ parser.setProject(fJProject1);
+ IBinding binding= parser.createBindings(new IJavaElement[]{elem}, null)[0];
+ return JavaElementLinks.getBindingLabel(binding, elem, flags, fHaveSource);
+ }
+
+ protected void assertLink(String lab, String display) {
+ Pattern pattern= Pattern.compile("<a class='header' href='eclipse-javadoc:.*'>(.*)</a>");
+ Matcher matcher= pattern.matcher(lab);
+ assertEquals("number of match groups", 1, matcher.groupCount());
+ assertTrue("Label doesn't match against expected pattern: "+lab, matcher.matches());
+ assertEquals("display label", display, matcher.group(1));
+ }
+
+ protected void assertLink(String lab, String display, String title) {
+ Pattern pattern= Pattern.compile("<a class='header' href='eclipse-javadoc:.*' title='(.*)'>(.*)</a>");
+ Matcher matcher= pattern.matcher(lab);
+ assertEquals("number of match groups", 2, matcher.groupCount());
+ assertTrue("Label doesn't match against expected pattern: "+lab, matcher.matches());
+ assertEquals("title", title, matcher.group(1));
+ assertEquals("display label", display, matcher.group(2));
+ }
+
+ /*
+ * expectedMarkup may contain any number of occurrences of "{{qualifier|name}}",
+ * which will be matched as a link with link text "name" and a link title "in qualifier".
+ * Optionally, {{name}} will be matched as a link with a link text but no title.
+ */
+ protected void assertLinkMatch(String label, String expectedMarkup) {
+ // to avoid matching the entire unreadable label in one step we co-parse expected and actual value:
+ int patternPos= 0;
+ int labelPos= 0;
+ int fragmentCount= 0;
+ while (patternPos < expectedMarkup.length()) {
+ // analyze expected mark-up:
+ int open= expectedMarkup.indexOf("{{", patternPos);
+ if (open == -1)
+ break;
+ int pipe= expectedMarkup.indexOf('|', open);
+ if (pipe > -1) {
+ int nextOpen= expectedMarkup.indexOf("{{", open+2);
+ if (nextOpen > -1 && nextOpen < pipe)
+ pipe= -1; // pipe belongs to next link
+ }
+ boolean hasTitle= pipe != -1;
+ int close= expectedMarkup.indexOf("}}", hasTitle ? pipe : open);
+ if (close + 2 < expectedMarkup.length() && expectedMarkup.charAt(close+2) == '}')
+ close++; // position to the end of "}}}"
+
+ if (open > patternPos) {
+ // matching plain text:
+ String expected= expectedMarkup.substring(patternPos, open);
+ int end= label.indexOf("<a class", labelPos);
+ assertTrue("next anchor not found ("+fragmentCount+")", end != -1);
+ assertEquals("plain text ("+fragmentCount+")", escape(expected), label.substring(labelPos, end));
+ fragmentCount++;
+
+ labelPos= end;
+ }
+
+ if (close != -1) {
+ // matching a link "<a class='header' href='eclipse-javadoc:IGNORE' title='LINK_TITLE'>LINK_TEXT</a>"
+ assertTrue("link found ("+fragmentCount+")", label.substring(labelPos).startsWith( "<a class='header' href='eclipse-javadoc:"));
+ String linkText= expectedMarkup.substring(hasTitle ? pipe+1 : open+2, close);
+ String linkTitle= hasTitle ? "in "+expectedMarkup.substring(open+2, pipe) : null;
+ if (linkTitle != null) {
+ // match linkTitle & linkText:
+ int start= label.indexOf("' title='", labelPos);
+ assertTrue("title start not found", start != -1);
+ start += "' title='".length();
+ int end= label.indexOf('\'', start);
+ assertTrue("title end not found", end != -1);
+ assertEquals("title ("+fragmentCount+")", linkTitle, label.substring(start, end));
+ fragmentCount++;
+
+ start= label.indexOf("'>", end) + 2;
+ assertTrue("link text start not found", start != -1);
+ end= label.indexOf("</a>", start);
+ assertTrue("link text end not found", end != -1);
+ assertEquals("link text ("+fragmentCount+")", escape(linkText), label.substring(start, end));
+ fragmentCount++;
+
+ labelPos= end + "</a>".length();
+ } else {
+ // match only linkText
+ int start= label.indexOf("'>", labelPos) + 2;
+ assertTrue("link text start not found", start != -1);
+ int end= label.indexOf("</a>", start+1);
+ assertTrue("link text end not found", end != -1);
+ assertEquals("link text ("+fragmentCount+")", escape(linkText), label.substring(start, end));
+ fragmentCount++;
+
+ labelPos= end + "</a>".length();
+ }
+ }
+ patternPos= close+2;
+ }
+ if (patternPos < expectedMarkup.length()) {
+ // matching tailing plain text:
+ String expected= expectedMarkup.substring(patternPos);
+ assertEquals("plain text ("+(fragmentCount)+")", escape(expected), label.substring(labelPos));
+ }
+ }
+
+ protected String escape(String element) {
+ return element.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabels18Test.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabels18Test.java
new file mode 100644
index 0000000000..3ff780e6e5
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabels18Test.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.core;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+
+import org.eclipse.jdt.ui.JavaElementLabels;
+import org.eclipse.jdt.ui.PreferenceConstants;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class BindingLabels18Test extends AbstractBindingLabelsTest {
+
+ private static final Class THIS= BindingLabels18Test.class;
+
+ public BindingLabels18Test(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return setUpTest(new TestSuite(THIS));
+ }
+
+ public static Test setUpTest(Test test) {
+ return new Java18ProjectTestSetup(test);
+ }
+
+ protected void setUp() throws Exception {
+ fJProject1= Java18ProjectTestSetup.getProject();
+
+ IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+ store.setValue(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES, false);
+ }
+
+ protected void tearDown() throws Exception {
+ JavaProjectHelper.clear(fJProject1, Java18ProjectTestSetup.getDefaultClasspath());
+ }
+
+
+ public void testMethodLabelPolymorphicSignatureDeclaration() throws Exception {
+ IType methodHandle= fJProject1.findType("java.lang.invoke.MethodHandle");
+ IMethod invokeExact= methodHandle.getMethod("invokeExact", new String[] {
+ Signature.createArraySignature(Signature.createTypeSignature("java.lang.Object", true), 1)
+ });
+
+ String lab= getBindingLabel(invokeExact, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "invokeExact({{java.lang|Object}}...)");
+
+ lab= getBindingLabel(invokeExact, JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "invokeExact(arg0)");
+
+ lab= getBindingLabel(invokeExact, JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "invokeExact({{java.lang|Object}}...)");
+
+ lab= getBindingLabel(invokeExact, JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "invokeExact({{java.lang|Object}}... arg0)");
+
+ lab= getBindingLabel(invokeExact, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invokeExact({{java.lang|Object}}...)");
+ }
+
+ private IJavaElement createInvokeReference(String invocation) throws CoreException, JavaModelException {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.lang.invoke.MethodHandle;\n");
+ buf.append("public class Test {\n");
+ buf.append(" void foo(MethodHandle mh) throws Throwable {\n");
+ buf.append(" " + invocation + ";\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Test.java", content, false, null);
+
+ IJavaElement elem= cu.codeSelect(content.indexOf("invoke("), 0)[0];
+ return elem;
+ }
+
+ private void assertInvokeUnresolved(IJavaElement elem) {
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "invoke({{java.lang|Object}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "invoke(arg0)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "invoke({{java.lang|Object}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PRE_RETURNTYPE);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke({{java.lang|Object}}... arg0)");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference0() throws Exception {
+ IJavaElement elem= createInvokeReference("mh.invoke()");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke()");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke()");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke()");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference0Ret() throws Exception {
+ IJavaElement elem= createInvokeReference("String s= (String) mh.invoke()");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke()");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke()");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke()");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference1() throws Exception {
+ IJavaElement elem= createInvokeReference("mh.invoke(1)");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke(int)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "invoke(int)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke(int arg00)");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference1Array() throws Exception {
+ IJavaElement elem= createInvokeReference("mh.invoke(new Object[42])");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke({{java.lang|Object}}[])");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke({{java.lang|Object}}[])");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke({{java.lang|Object}}[] arg00)");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference2() throws Exception {
+ IJavaElement elem= createInvokeReference("mh.invoke('a', new Integer[0][])");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke(char, {{java.lang|Integer}}[][])");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke(char, {{java.lang|Integer}}[][])");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke(char arg00, {{java.lang|Integer}}[][] arg01)");
+ }
+
+ public void testMethodLabelPolymorphicSignatureReference3Ret() throws Exception {
+ IJavaElement elem= createInvokeReference("long l= (long) mh.invoke('a', new java.util.ArrayList<String>(), null)");
+
+ assertInvokeUnresolved(elem);
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke(char, {{java.util|ArrayList}}<{{java.util.ArrayList|E}}>, {{java.lang|Void}})");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "invoke(char, {{java.util|ArrayList}}, {{java.lang|Void}})");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{java.lang|Object}} invoke(char arg00, {{java.util|ArrayList}} arg01, {{java.lang|Void}} arg02)");
+ }
+
+ public void testTypeLabelLambda1() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.IntConsumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" IntConsumer c = (i) -> { };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement[] elems= cu.codeSelect(content.lastIndexOf("i"), 1);
+ IJavaElement i= elems[0];
+ String lab= getBindingLabel(i, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.C}}.{{org.test.C|c}}.() -> {...} {{IntConsumer}}.{{java.util.function.IntConsumer|accept}}(int).i");
+
+ IJavaElement lambdaMethod= i.getParent();
+ lab= getBindingLabel(lambdaMethod, JavaElementLabels.T_FULLY_QUALIFIED
+ | JavaElementLabels.M_POST_QUALIFIED | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES);
+ assertLinkMatch(lab, "accept(int i) - {{org.test.C}}.{{org.test.C|c}}.() -> {...} {{java.util.function|IntConsumer}}");
+
+ IJavaElement lambdaType= lambdaMethod.getParent();
+ lab= getBindingLabel(lambdaType, JavaElementLabels.T_POST_QUALIFIED);
+// Bindings don't have the split identity of a lambda as expected from JavaElementLabelsTest18
+ assertLinkMatch(lab, "accept(...) - {{org.test.C}}.{{org.test.C|c}}.() -> {...} {{java.util.function|IntConsumer}}");
+// assertLinkMatch(lab, "() -> {...} IntConsumer - org.test.C.c");
+ }
+
+ public void testTypeLabelLambda2() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.Consumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" Consumer<String> c = (s) -> { };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement[] elems= cu.codeSelect(content.lastIndexOf("s"), 1);
+ IJavaElement i= elems[0];
+ String lab= getBindingLabel(i, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.C}}.{{org.test.C|c}}.() -> {...} {{Consumer}}.{{java.util.function.Consumer|accept}}({{java.util.function.Consumer|T}}).s");
+
+ lab= getBindingLabel(i, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{org.test.C}}.{{org.test.C|c}}.() -> {...} {{Consumer}}.{{java.util.function.Consumer<java.lang.String>|accept}}({{java.lang|String}}).s");
+
+ IJavaElement lambdaMethod= i.getParent();
+ lab= getBindingLabel(lambdaMethod, JavaElementLabels.T_FULLY_QUALIFIED
+ | JavaElementLabels.M_POST_QUALIFIED | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES);
+ assertLinkMatch(lab, "accept({{java.util.function.Consumer|T}} arg0) - {{org.test.C}}.{{org.test.C|c}}.() -> {...} {{java.util.function|Consumer}}");
+
+ IJavaElement lambdaType= lambdaMethod.getParent();
+ lab= getBindingLabel(lambdaType, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "accept(...) - {{org.test.C}}.{{org.test.C|c}}.() -> {...} {{java.util.function|Consumer}}");
+ }
+
+ public void testAnonymousClassInLambda1() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.Consumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" Consumer<String> c = (s) -> {\n");
+ buf.append(" new Thread() { public void run() { } }.start();\n");
+ buf.append(" };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement thread= cu.getElementAt(content.lastIndexOf("Thread"));
+ String lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.C}}.{{org.test.C|c}}.() -> {...}.new Thread() {...}");
+
+ lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_POST_QUALIFIED);
+ assertLinkMatch(lab, "new Thread() {...} - {{org.test.C}}.{{org.test.C|c}}.() -> {...}");
+ }
+
+ public void testLambdaInAnonymousClass1() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.Consumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" Thread t= new Thread() {\n");
+ buf.append(" public void run() {\n");
+ buf.append(" Consumer<String> c = (s) -> { };\n");
+ buf.append(" }\n");
+ buf.append(" };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement[] elems= cu.codeSelect(content.lastIndexOf("s)"), 1);
+ IJavaElement thread= elems[0];
+ String lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "{{org.test.C}}.{{org.test.C|t}}.{{org.test.C.t|new Thread() {...}}}.{{org.test.C.t.new Thread() {...}|run}}()." +
+ "() -> {...} {{java.util.function|Consumer}}.{{java.util.function.Consumer<java.lang.String>|accept}}({{java.lang|String}}).s");
+
+ lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.F_PRE_TYPE_SIGNATURE | JavaElementLabels.F_POST_QUALIFIED);
+ assertLinkMatch(lab, "{{java.lang|String}} s - {{org.test.C}}.{{org.test.C|t}}.{{org.test.C.t|new Thread() {...}}}.{{org.test.C.t.new Thread() {...}|run}}()." +
+ "() -> {...} {{java.util.function|Consumer}}.{{java.util.function.Consumer|accept}}({{java.util.function.Consumer|T}})");
+ }
+
+ public void testLambdaInInstanceInitializer() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.Consumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" {\n");
+ buf.append(" Consumer<String> c = (s) -> { System.out.print(s.toUpperCase()); };\n");
+ buf.append(" };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement[] elems= cu.codeSelect(content.lastIndexOf("s.toUpperCase"), 1);
+ IJavaElement thread= elems[0];
+ String lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.USE_RESOLVED | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{java.lang|String}} {{org.test.C}}.{...}.() -> {...} {{java.util.function|Consumer}}.{{java.util.function.Consumer<java.lang.String>|accept}}({{java.lang|String}}).s");
+
+ lab= getBindingLabel(thread, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.F_PRE_TYPE_SIGNATURE | JavaElementLabels.F_POST_QUALIFIED);
+ assertLinkMatch(lab, "{{java.lang|String}} s - {{org.test.C}}.{...}.() -> {...} {{java.util.function|Consumer}}.{{java.util.function.Consumer|accept}}({{java.util.function.Consumer|T}})");
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabelsTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabelsTest.java
new file mode 100644
index 0000000000..1b7019a952
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/BindingLabelsTest.java
@@ -0,0 +1,771 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.core;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+
+import org.eclipse.jdt.ui.JavaElementLabels;
+
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * This test suite is copied and adjusted from {@link JavaElementLabelsTest}
+ */
+public class BindingLabelsTest extends AbstractBindingLabelsTest {
+
+ private static final Class THIS= BindingLabelsTest.class;
+
+
+ public BindingLabelsTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return setUpTest(new TestSuite(THIS));
+ }
+
+ public static Test setUpTest(Test test) {
+ return new ProjectTestSetup(test);
+ }
+
+ public void testTypeLabelOuter() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("public class Outer {\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Outer"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertEqualString(lab, "org.test.Outer");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertEqualString(lab, "Outer");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "Outer - {{org.test}}");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer");
+ */
+ }
+
+ public void testTypeLabelInner() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" public void foo(Vector vec) {\n");
+ buf.append(" }\n");
+ buf.append(" public class Inner {\n");
+ buf.append(" public int inner(Vector vec) {\n");
+ buf.append(" }\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Inner"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertEqualString(lab, "org.test.Outer.Inner");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertEqualString(lab, "Outer.Inner");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "Inner - {{org.test.Outer}}");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.Inner - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.Inner");
+ */
+ }
+
+ public void testTypeLabelLocal() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" public void foo(Vector vec) {\n");
+ buf.append(" public class Local {\n");
+ buf.append(" }\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Local"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.Outer}}.{{org.test.Outer|foo}}(...).Local");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test|Outer}}.{{org.test.Outer|foo}}(...).Local");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "Local - {{org.test.Outer}}.{{foo}}(...)");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.foo(...).Local - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.foo(...).Local");
+ */
+ }
+
+ public void testTypeParameterLabelType() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.*;\n");
+ buf.append("import java.io.Serializable;\n");
+ buf.append("public class TypeParams<Q extends ArrayList<? extends Number>, Element extends Map<String, Integer> & Serializable, NoBound> {\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("TypeParams.java", content, false, null);
+
+ IType typeParams= (IType)cu.getElementAt(content.indexOf("TypeParams"));
+ ITypeParameter[] typeParameters= typeParams.getTypeParameters();
+ ITypeParameter q= typeParameters[0];
+ ITypeParameter element= typeParameters[1];
+ ITypeParameter nobound= typeParameters[2];
+
+ String lab= getBindingLabel(q, 0);
+ assertLinkMatch(lab, "Q extends {{java.util|ArrayList}}<? extends {{java.lang|Number}}>");
+ lab= getBindingLabel(q, JavaElementLabels.ALL_POST_QUALIFIED);
+ assertLinkMatch(lab, "Q extends {{java.util|ArrayList}}<? extends {{java.lang|Number}}> - {{org.test.TypeParams}}");
+
+ lab= getBindingLabel(element, 0);
+ assertLinkMatch(lab, "Element extends {{java.util|Map}}<{{java.lang|String}}, {{java.lang|Integer}}> & {{java.io|Serializable}}");
+ lab= getBindingLabel(element, JavaElementLabels.DEFAULT_POST_QUALIFIED);
+ assertLinkMatch(lab, "Element extends {{java.util|Map}}<{{java.lang|String}}, {{java.lang|Integer}}> & {{java.io|Serializable}} - {{org.test.TypeParams}}");
+
+ lab= getBindingLabel(nobound, 0);
+ assertEqualString(lab, "NoBound");
+ lab= getBindingLabel(nobound, JavaElementLabels.TP_POST_QUALIFIED);
+ assertLinkMatch(lab, "NoBound - {{org.test.TypeParams}}");
+
+
+/* cannot select 'E' from cu.
+ IType al= (IType)cu.codeSelect(content.indexOf("ArrayList"), 0)[0];
+ ITypeParameter[] alTypeParameters= al.getTypeParameters();
+ ITypeParameter e= alTypeParameters[0];
+
+ lab= JavaElementLabels.getTextLabel(e, 0);
+ assertEqualString(lab, "E"); // no " extends java.lang.Object"!
+ */
+
+/*
+ lab= JavaElementLabels.getTextLabel(e, JavaElementLabels.ALL_POST_QUALIFIED);
+ assertEqualString(lab, "E - java.util.ArrayList");
+ */
+
+
+ lab= getBindingLabel(typeParams, 0);
+ assertEqualString(lab, "TypeParams");
+ lab= getBindingLabel(typeParams, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "TypeParams<{{org.test.TypeParams|Q}} extends {{java.util|ArrayList}}<? extends {{java.lang|Number}}>, {{org.test.TypeParams|Element}} extends {{java.util|Map}}<{{java.lang|String}}, {{java.lang|Integer}}> & {{java.io|Serializable}}, {{org.test.TypeParams|NoBound}}>");
+/*
+ lab= JavaElementLabels.getTextLabel(typeParams, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_POST_QUALIFIED);
+ assertEqualString(lab, "TypeParams<Q extends ArrayList<? extends Number>, Element extends Map<String, Integer> & Serializable, NoBound> - org.test");
+ */
+ }
+
+ public void testTypeParameterLabelMethod() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.*;\n");
+ buf.append("public class X {\n");
+ buf.append(" <Q extends ArrayList<? extends Number>, Element extends Map<String, Integer>, NoBound> Q method(Element e, NoBound n) {\n");
+ buf.append(" return null;\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("X.java", content, false, null);
+
+ IMethod method= (IMethod)cu.getElementAt(content.indexOf("method"));
+ ITypeParameter[] typeParameters= method.getTypeParameters();
+ ITypeParameter q= typeParameters[0];
+ ITypeParameter element= typeParameters[1];
+ ITypeParameter nobound= typeParameters[2];
+
+ String lab= getBindingLabel(q, 0);
+ assertLinkMatch(lab, "Q extends {{java.util|ArrayList}}<? extends {{java.lang|Number}}>");
+ lab= getBindingLabel(q, JavaElementLabels.ALL_POST_QUALIFIED);
+ assertLinkMatch(lab, "Q extends {{java.util|ArrayList}}<? extends {{java.lang|Number}}> - {{org.test.X}}.{{org.test.X|method}}({{org.test.X.method(...)|Element}}, {{org.test.X.method(...)|NoBound}})");
+
+ lab= getBindingLabel(element, 0);
+ assertLinkMatch(lab, "Element extends {{java.util|Map}}<{{java.lang|String}}, {{java.lang|Integer}}>");
+ lab= getBindingLabel(element, JavaElementLabels.DEFAULT_POST_QUALIFIED);
+ assertLinkMatch(lab, "Element extends {{java.util|Map}}<{{java.lang|String}}, {{java.lang|Integer}}> - {{org.test.X}}.{{org.test.X|method}}(Element, {{org.test.X.method(...)|NoBound}})");
+
+ lab= getBindingLabel(nobound, 0);
+ assertEqualString(lab, "NoBound");
+ lab= getBindingLabel(nobound, JavaElementLabels.TP_POST_QUALIFIED);
+ assertLinkMatch(lab, "NoBound - {{org.test.X}}.{{org.test.X|method}}({{org.test.X.method(...)|Element}}, NoBound)");
+ }
+
+ public void testTypeLabelAnonymous() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" public void foo(Vector vec) {\n");
+ buf.append(" new Object() {\n");
+ buf.append(" };\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Object"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.Outer}}.{{org.test.Outer|foo}}(...).new Object() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test|Outer}}.{{org.test.Outer|foo}}(...).new Object() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "new Object() {...} - {{org.test.Outer}}.{{org.test.Outer|foo}}(...)");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.foo(...).new Object() {...} - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.foo(...).new Object() {...}");
+ */
+ }
+
+ public void testTypeLabelAnonymousInAnonymous() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("import java.io.Serializable;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" public void foo(Vector vec) {\n");
+ buf.append(" new Object() {\n");
+ buf.append(" public void xoo() {\n");
+ buf.append(" new Serializable() {\n");
+ buf.append(" };\n");
+ buf.append(" }\n");
+ buf.append(" };\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Serializable()"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.Outer}}.{{org.test.Outer|foo}}(...).{{org.test.Outer.foo(...)|new Object() {...}}}." +
+ "{{org.test.Outer.foo(...).new Object() {...}|xoo}}()" +
+ ".new Serializable() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test|Outer}}.{{org.test.Outer|foo}}(...).{{org.test.Outer.foo(...)|new Object() {...}}}." +
+ "{{org.test.Outer.foo(...).new Object() {...}|xoo}}().new Serializable() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "new Serializable() {...} - " +
+ "{{org.test.Outer}}.{{org.test.Outer|foo}}(...).{{org.test.Outer.foo(...)|new Object() {...}}}." +
+ "{{org.test.Outer.foo(...).new Object() {...}|xoo}}()");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.foo(...).new Object() {...}.xoo().new Serializable() {...} - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.foo(...).new Object() {...}.xoo().new Serializable() {...}");
+ */
+ }
+
+ public void testTypeLabelAnonymousInFieldInitializer() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" Object o= new Thread() {\n");
+ buf.append(" };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Thread"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.Outer}}.{{org.test.Outer|o}}.new Thread() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test|Outer}}.{{org.test.Outer|o}}.new Thread() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "new Thread() {...} - {{org.test.Outer}}.{{o}}");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.o.new Thread() {...} - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.o.new Thread() {...}");
+ */
+ }
+
+ public void testTypeLabelAnonymousInInitializer() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Vector;\n");
+ buf.append("public class Outer {\n");
+ buf.append(" static {\n");
+ buf.append(" new Object() {\n");
+ buf.append(" };\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Outer.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("Object"));
+ String lab= getBindingLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.Outer}}.{...}.new Object() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_CONTAINER_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test|Outer}}.{...}.new Object() {...}");
+
+ lab= getBindingLabel(elem, JavaElementLabels.T_POST_QUALIFIED);
+ assertLinkMatch(lab, "new Object() {...} - {{org.test.Outer}}.{...}");
+
+/* *_ROOT_PATH is not relevant for javadoc hover/view
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH);
+ assertEqualString(lab, "org.test.Outer.{...}.new Object() {...} - TestSetupProject/src");
+
+ lab= JavaElementLabels.getTextLabel(elem, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.PREPEND_ROOT_PATH);
+ assertEqualString(lab, "TestSetupProject/src - org.test.Outer.{...}.new Object() {...}");
+ */
+ }
+
+ public void testTypeLabelWildcards() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("public class Wildcards<T> {\n");
+ buf.append(" Wildcards<? extends Number> upper;\n");
+ buf.append(" Wildcards<? super Number> lower;\n");
+ buf.append(" Wildcards<?> wild;\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Wildcards.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("upper"));
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{org.test|Wildcards}}<? extends {{java.lang|Number}}> upper");
+
+ elem= cu.getElementAt(content.indexOf("lower"));
+ lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{org.test|Wildcards}}<? super {{java.lang|Number}}> lower");
+
+ elem= cu.getElementAt(content.indexOf("wild"));
+ lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{org.test|Wildcards}}<?> wild");
+
+ }
+
+ public void testPackageLabels() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment packDefault= sourceFolder.getPackageFragment("");
+ IPackageFragment packOrg= sourceFolder.createPackageFragment("org", false, null);
+// IPackageFragment packOrgTest= sourceFolder.createPackageFragment("org.test", false, null);
+ IPackageFragment packOrgTestLongname= sourceFolder.createPackageFragment("org.test.longname", false, null);
+
+ // to obtain an IPackageBinding go via imported types to their #package:
+ packOrg.createCompilationUnit("T1.java", "package org;\npublic class T1 {}\n", false, null);
+ packOrgTestLongname.createCompilationUnit("T2.java", "package org.test.longname;\npublic class T2 {}\n", false, null);
+
+ StringBuffer buf= new StringBuffer();
+ buf.append("import org.T1;\n");
+ buf.append("import org.test.longname.T2;\n");
+ buf.append("public class Main {\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= packDefault.createCompilationUnit("Main.java", content, false, null);
+
+ IJavaElement main= cu.getElementAt(content.indexOf("Main"));
+ IJavaElement t1= cu.getElementAt(content.indexOf("T1"));
+ IJavaElement t2= cu.getElementAt(content.indexOf("T2"));
+
+ ASTParser parser= ASTParser.newParser(AST.JLS8);
+ parser.setResolveBindings(true);
+ parser.setProject(fJProject1);
+ IBinding[] bindings= parser.createBindings(new IJavaElement[]{main, t1, t2}, null);
+
+ String lab= JavaElementLinks.getBindingLabel(((ITypeBinding)bindings[0]).getPackage(), main.getAncestor(IJavaElement.PACKAGE_FRAGMENT), JavaElementLabels.ALL_DEFAULT, true);
+ assertEqualString(lab, "(default package)");
+ lab= JavaElementLinks.getBindingLabel(((ITypeBinding)bindings[1]).getPackage(), t1.getAncestor(IJavaElement.PACKAGE_FRAGMENT), JavaElementLabels.ALL_DEFAULT, true);
+ assertLink(lab, "org");
+ lab= JavaElementLinks.getBindingLabel(((ITypeBinding)bindings[2]).getPackage(), t2.getAncestor(IJavaElement.PACKAGE_FRAGMENT), JavaElementLabels.ALL_DEFAULT, true);
+ assertLink(lab, "org.test.longname");
+
+/* P_COMPRESSED is not relevant for hovers / javadoc view:
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "org", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "org.test.longname", JavaElementLabels.P_COMPRESSED);
+
+ assertExpectedLabel(packDefault, "(default package) - TestSetupProject/src", JavaElementLabels.P_POST_QUALIFIED);
+ assertExpectedLabel(packOrg, "org - TestSetupProject/src", JavaElementLabels.P_POST_QUALIFIED);
+ assertExpectedLabel(packOrgTestLongname, "org.test.longname - TestSetupProject/src", JavaElementLabels.P_POST_QUALIFIED);
+
+ IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+ store.setValue(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES, true);
+
+ try {
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW, "0");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "org", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, "test", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "longname", JavaElementLabels.P_COMPRESSED);
+
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW, ".");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "org", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, ".test", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "..longname", JavaElementLabels.P_COMPRESSED);
+
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW, "1~.");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "org", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, "o~.test", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "o~.t~.longname", JavaElementLabels.P_COMPRESSED);
+
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW, "2*.");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "org", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, "org.test", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "org.te*.longname", JavaElementLabels.P_COMPRESSED);
+
+
+ store.setValue(PreferenceConstants.APPEARANCE_ABBREVIATE_PACKAGE_NAMES, true);
+
+ assertExpectedLabel(packOrgTestLongname, "org.te*.longname", JavaElementLabels.P_COMPRESSED);
+
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_ABBREVIATION_PATTERN_FOR_PKG_VIEW, "#com=@C\norg=@O");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "@O", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, "@O.test", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "@O.te*.longname", JavaElementLabels.P_COMPRESSED);
+
+ store.setValue(PreferenceConstants.APPEARANCE_PKG_NAME_ABBREVIATION_PATTERN_FOR_PKG_VIEW, "org=@O\n\norg.test=@OT\n");
+
+ assertExpectedLabel(packDefault, "(default package)", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrg, "@O", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTest, "@OT", JavaElementLabels.P_COMPRESSED);
+ assertExpectedLabel(packOrgTestLongname, "@OT.longname", JavaElementLabels.P_COMPRESSED);
+
+ } finally {
+ store.setToDefault(PreferenceConstants.APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW);
+ store.setValue(PreferenceConstants.APPEARANCE_COMPRESS_PACKAGE_NAMES, false);
+ store.setToDefault(PreferenceConstants.APPEARANCE_PKG_NAME_ABBREVIATION_PATTERN_FOR_PKG_VIEW);
+ store.setValue(PreferenceConstants.APPEARANCE_ABBREVIATE_PACKAGE_NAMES, false);
+ }
+ */
+ }
+
+ public void testMethodLabelVarargsDeclaration() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("public class Varargs {\n");
+ buf.append(" public void foo(int i, String... varargs) {\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Varargs.java", content, false, null);
+
+ IJavaElement elem= cu.getElementAt(content.indexOf("foo"));
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "foo(int, {{java.lang|String}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "foo(i, varargs)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "foo(int, {{java.lang|String}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "foo(int i, {{java.lang|String}}... varargs)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "foo(int, {{java.lang|String}}...)");
+ }
+
+ public void testMethodLabelVarargsReference0() throws Exception {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Arrays;\n");
+ buf.append("public class Varargs {\n");
+ buf.append(" void foo() {\n");
+ buf.append(" Arrays.asList();\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Varargs.java", content, false, null);
+
+ IJavaElement elem= cu.codeSelect(content.indexOf("asList"), 0)[0];
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}...) <{{java.util.Arrays.asList(...)|T}}>");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "asList(arg0)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}... arg0)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "asList({{java.lang|Object}}...) <{{java.lang|Object}}>");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "asList({{java.lang|Object}}...)");
+ }
+
+ public void testMethodLabelVarargsReference1() throws Exception {
+ assertMethodLabelVarargsReference("1");
+ }
+
+ public void testMethodLabelVarargsReference2() throws Exception {
+ assertMethodLabelVarargsReference("1, 2");
+ }
+
+ public void testMethodLabelVarargsReference3() throws Exception {
+ assertMethodLabelVarargsReference("1, 2, new Integer(3)");
+ }
+
+ private void assertMethodLabelVarargsReference(String args) throws CoreException, JavaModelException {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.Arrays;\n");
+ buf.append("public class Varargs {\n");
+ buf.append(" void foo() {\n");
+ buf.append(" Arrays.asList(" + args + ");\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Varargs.java", content, false, null);
+
+ IJavaElement elem= cu.codeSelect(content.indexOf("asList"), 0)[0];
+
+ String lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}...) <{{java.util.Arrays.asList(...)|T}}>");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "asList(arg0)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}...)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_PARAMETER_TYPES);
+ assertLinkMatch(lab, "asList({{java.util.Arrays.asList(...)|T}}... arg0)");
+
+ lab= getBindingLabel(elem, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "asList({{java.lang|Integer}}...) <{{java.lang|Integer}}>");
+
+ lab= getBindingLabel(elem, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.USE_RESOLVED);
+ assertLinkMatch(lab, "asList({{java.lang|Integer}}...)");
+ }
+
+
+ public void testMethodLabelAnnotatedParameters() throws Exception {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("\n");
+ buf.append("import java.lang.annotation.Retention;\n");
+ buf.append("import java.lang.annotation.RetentionPolicy;\n");
+ buf.append("\n");
+ buf.append("public class Annotations {\n");
+ buf.append(" void foo(@Outer(a=@Ann(\"Hello world\\r\\n\\t\\\"<'#@%^&\")) String param) { }\n");
+ buf.append(" \n");
+ buf.append(" void foo2(@Ann(value=\"\", cl=Annotations.class, ints={1, 2, -19},\n");
+ buf.append(" ch='\\0', sh= 0x7FFF, r= @Retention(RetentionPolicy.SOURCE)) String param) { }\n");
+ buf.append("}\n");
+ buf.append("@interface Ann {\n");
+ buf.append(" String value();\n");
+ buf.append(" Class<?> cl() default Ann.class;\n");
+ buf.append(" int[] ints() default {1, 2};\n");
+ buf.append(" char ch() default 'a';\n");
+ buf.append(" short sh() default 1;\n");
+ buf.append(" Retention r() default @Retention(RetentionPolicy.CLASS);\n");
+ buf.append("}\n");
+ buf.append("@interface Outer {\n");
+ buf.append(" Ann a();\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("Annotations.java", content, false, null);
+
+ IJavaElement foo= cu.getElementAt(content.indexOf("foo"));
+ String lab= getBindingLabel(foo, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.M_PARAMETER_ANNOTATIONS);
+ assertLinkMatch(lab, "{{org.test.Annotations}}.foo(@{{Outer}}({{a}}=@{{Ann}}({{value}}=\"Hello world\\r\\n\\t\\\"<'#@%^&\")) {{String}})");
+
+ IJavaElement foo2= cu.getElementAt(content.indexOf("foo2"));
+ lab= getBindingLabel(foo2, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.M_PARAMETER_ANNOTATIONS);
+ assertLinkMatch(lab, "{{org.test.Annotations}}.foo2(@{{Ann}}({{value}}=\"\", {{cl}}={{Annotations}}.class, {{ints}}={1, 2, -19}, {{ch}}='\\u0000', {{sh}}=32767, {{r}}=@{{Retention}}({{value}}={{RetentionPolicy}}.{{SOURCE}})) {{String}})");
+ }
+
+ // disabled, because we cannot retrieve a binding for the selected element: local variable inside instance initializer
+ public void testLocalClassInInitializer() throws Exception {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("public class LambdaTests {\n");
+ buf.append(" {\n");
+ buf.append(" class Local implements Function<Integer, String> {\n");
+ buf.append(" @Override\n");
+ buf.append(" public String apply(Integer t) {\n");
+ buf.append(" return t.toString();\n");
+ buf.append(" }\n");
+ buf.append(" }\n");
+ buf.append("\n");
+ buf.append(" Local toStringL = new Local();\n");
+ buf.append(" System.out.println(toStringL.apply(123));\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("LambdaTests.java", content, false, null);
+
+ IJavaElement foo= cu.getElementAt(content.indexOf("Local implements"));
+ String lab= getBindingLabel(foo, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.LambdaTests}}.{...}.Local");
+
+ IJavaElement foo2= cu.codeSelect(content.indexOf("toStringL"), 9)[0];
+ lab= getBindingLabel(foo2, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_POST_QUALIFIED | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{org.test.LambdaTests.{...}|Local}} toStringL - {{org}}.{{test}}.{{LambdaTests}}.{...}");
+
+// can't select the constructor, only the type (label computation works fine once we find the binding)
+// IJavaElement ctor= cu.codeSelect(content.indexOf("Local()"), 0)[0];
+// lab= getBindingLabel(ctor, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+// assertLinkMatch(lab, "{{org.test.LambdaTests}}.{...}.{{org.test.LambdaTests.{...}.|Local}}.Local()");
+ }
+
+ public void testLocalClassInStaticInitializer() throws Exception {
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("public class LambdaTests {\n");
+ buf.append(" static {\n");
+ buf.append(" class Local implements Function<Integer, String> {\n");
+ buf.append(" @Override\n");
+ buf.append(" public String apply(Integer t) {\n");
+ buf.append(" return t.toString();\n");
+ buf.append(" }\n");
+ buf.append(" }\n");
+ buf.append("\n");
+ buf.append(" Local toStringL = new Local();\n");
+ buf.append(" System.out.println(toStringL.apply(123));\n");
+ buf.append(" }\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("LambdaTests.java", content, false, null);
+
+ IJavaElement foo= cu.getElementAt(content.indexOf("Local implements"));
+ String lab= getBindingLabel(foo, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertLinkMatch(lab, "{{org.test.LambdaTests}}.{...}.Local");
+
+ IJavaElement foo2= cu.codeSelect(content.indexOf("toStringL"), 9)[0];
+ lab= getBindingLabel(foo2, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_POST_QUALIFIED | JavaElementLabels.F_PRE_TYPE_SIGNATURE);
+ assertLinkMatch(lab, "{{org.test.LambdaTests.{...}|Local}} toStringL - {{org}}.{{test}}.{{LambdaTests}}.{...}");
+ }
+}
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/CoreTests.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/CoreTests.java
index 99ec2c5124..d4fc7ad207 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/CoreTests.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/CoreTests.java
@@ -47,6 +47,8 @@ public class CoreTests extends TestCase {
suite.addTest(ImportOrganizeTest18.suite());
suite.addTest(JavaElementLabelsTest.suite());
suite.addTest(JavaElementLabelsTest18.suite());
+ suite.addTest(BindingLabelsTest.suite());
+ suite.addTest(BindingLabels18Test.suite());
suite.addTest(JavaElementPropertyTesterTest.suite());
suite.addTest(JavaModelUtilTest.suite());
suite.addTest(MethodOverrideTest.suite());
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/JavaElementLabelsTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/JavaElementLabelsTest18.java
index 481d5b24c3..7765431068 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/JavaElementLabelsTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/core/JavaElementLabelsTest18.java
@@ -237,4 +237,36 @@ public class JavaElementLabelsTest18 extends CoreTests {
assertEqualString(lab, "() -> {...} IntConsumer - org.test.C.c");
}
+ public void testTypeLabelLambda2() throws Exception {
+
+ IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
+
+ IPackageFragment pack1= sourceFolder.createPackageFragment("org.test", false, null);
+ StringBuffer buf= new StringBuffer();
+ buf.append("package org.test;\n");
+ buf.append("import java.util.function.Consumer;\n");
+ buf.append("public class C {\n");
+ buf.append(" Consumer<String> c = (s) -> { };\n");
+ buf.append("}\n");
+ String content= buf.toString();
+ ICompilationUnit cu= pack1.createCompilationUnit("C.java", content, false, null);
+
+ IJavaElement[] elems= cu.codeSelect(content.lastIndexOf("s"), 1);
+ IJavaElement i= elems[0];
+ String lab= JavaElementLabels.getTextLabel(i, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ assertEqualString(lab, "org.test.C.c.() -> {...} Consumer.accept(String).s");
+
+ lab= JavaElementLabels.getTextLabel(i, JavaElementLabels.ALL_DEFAULT | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.USE_RESOLVED);
+ assertEqualString(lab, "org.test.C.c.() -> {...} Consumer.accept(String).s");
+
+ IJavaElement lambdaMethod= i.getParent();
+ lab= JavaElementLabels.getTextLabel(lambdaMethod, JavaElementLabels.T_FULLY_QUALIFIED
+ | JavaElementLabels.M_POST_QUALIFIED | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES);
+ assertEqualString(lab, "accept(String s) - org.test.C.c.() -> {...} Consumer");
+
+ IJavaElement lambdaType= lambdaMethod.getParent();
+ lab= JavaElementLabels.getTextLabel(lambdaType, JavaElementLabels.T_POST_QUALIFIED);
+ assertEqualString(lab, "() -> {...} Consumer - org.test.C.c");
+ }
+
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
index 6757de49b6..109ac7cc0c 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
@@ -10,6 +10,7 @@
* Genady Beryozkin <eclipse@genady.org> - [misc] Display values for constant fields in the Javadoc view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=204914
* Brock Janiczak <brockj@tpg.com.au> - [implementation] Streams not being closed in Javadoc views - https://bugs.eclipse.org/bugs/show_bug.cgi?id=214854
* Benjamin Muskalla <bmuskalla@innoopract.com> - [javadoc view] NPE on enumerations - https://bugs.eclipse.org/bugs/show_bug.cgi?id=223586
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
*******************************************************************************/
package org.eclipse.jdt.internal.ui.infoviews;
@@ -150,6 +151,7 @@ import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover.FallbackInformationPresenter;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
+import org.eclipse.jdt.internal.ui.viewsupport.BindingLinkedLabelComposer;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
@@ -1155,7 +1157,18 @@ public class JavadocView extends AbstractInfoView {
* @return a string containing the member's label
*/
private String getInfoText(IJavaElement member, String constantValue, boolean allowImage) {
- StringBuffer label= new StringBuffer(JavaElementLinks.getElementLabel(member, JavadocHover.getHeaderFlags(member)));
+ long flags= JavadocHover.getHeaderFlags(member);
+ IBinding binding= JavadocHover.getHoverBinding(member, null);
+ StringBuffer label;
+ if (binding != null) {
+ label= new StringBuffer();
+ // setting haveSource to false lets the JavadocView *always* show qualified type names,
+ // would need to track the source of our input to distinguish classfile/compilationUnit:
+ boolean haveSource= false;
+ new BindingLinkedLabelComposer(member, label, haveSource).appendBindingLabel(binding, flags);
+ } else {
+ label= new StringBuffer(JavaElementLinks.getElementLabel(member, flags));
+ }
if (member.getElementType() == IJavaElement.FIELD && constantValue != null) {
label.append(constantValue);
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
index c09cf8b592..100c74b6bf 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Genady Beryozkin <eclipse@genady.org> - [hovering] tooltip for constant string does not show constant value - https://bugs.eclipse.org/bugs/show_bug.cgi?id=85382
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
*******************************************************************************/
package org.eclipse.jdt.internal.ui.text.java.hover;
@@ -73,6 +74,7 @@ import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
@@ -88,6 +90,7 @@ import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
@@ -759,8 +762,18 @@ public class JavadocHover extends AbstractJavaEditorTextHover {
private static String getInfoText(IJavaElement element, ITypeRoot editorInputElement, IRegion hoverRegion, boolean allowImage) {
long flags= getHeaderFlags(element);
- StringBuffer label= new StringBuffer(JavaElementLinks.getElementLabel(element, flags));
+ boolean haveSource= editorInputElement instanceof ICompilationUnit;
+ ASTNode node= haveSource ? getHoveredASTNode(editorInputElement, hoverRegion) : null;
+ IBinding binding= getHoverBinding(element, node);
+
+ StringBuffer label;
+ if (binding != null) {
+ label= new StringBuffer(JavaElementLinks.getBindingLabel(binding, element, flags, haveSource));
+ } else {
+ label= new StringBuffer(JavaElementLinks.getElementLabel(element, flags));
+ }
+
if (element.getElementType() == IJavaElement.FIELD) {
String constantValue= getConstantValue((IField) element, editorInputElement, hoverRegion);
if (constantValue != null) {
@@ -778,6 +791,37 @@ public class JavadocHover extends AbstractJavaEditorTextHover {
return getImageAndLabel(element, allowImage, label.toString());
}
+
+ /**
+ * Try to acquire a binding corresponding to the given element
+ * for more precise information about (type) annotations.
+ *
+ * Currently this lookup is only enabled when null-annotations are enabled for the project.
+ *
+ * @param element the element being rendered
+ * @param node the AST node corresponding to the given element, or null, if no AST node is available.
+ * @return either a binding corresponding to the given element or null.
+ */
+ public static IBinding getHoverBinding(IJavaElement element, ASTNode node) {
+
+ if (element.getJavaProject().getOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, true).equals(JavaCore.ENABLED)) {
+ if (node == null) {
+ if (element instanceof ISourceReference) {
+ ASTParser p= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
+ p.setProject(element.getJavaProject());
+ p.setBindingsRecovery(true);
+ try {
+ return p.createBindings(new IJavaElement[] { element }, null)[0];
+ } catch (OperationCanceledException e) {
+ return null;
+ }
+ }
+ } else {
+ return resolveBinding(node);
+ }
+ }
+ return null;
+ }
private static String getImageURL(IJavaElement element) {
String imageName= null;
@@ -1080,6 +1124,8 @@ public class JavadocHover extends AbstractJavaEditorTextHover {
return ((SuperConstructorInvocation) node).resolveConstructorBinding();
} else if (node instanceof ConstructorInvocation) {
return ((ConstructorInvocation) node).resolveConstructorBinding();
+ } else if (node instanceof LambdaExpression) {
+ return ((LambdaExpression) node).resolveMethodBinding();
} else {
return null;
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/BindingLinkedLabelComposer.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/BindingLinkedLabelComposer.java
new file mode 100644
index 0000000000..8bb53a9063
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/BindingLinkedLabelComposer.java
@@ -0,0 +1,791 @@
+/*******************************************************************************
+ * Copyright (c) 2015 GK Software AG 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.viewsupport;
+
+import static org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks.JAVADOC_SCHEME;
+import static org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks.createHeaderLink;
+import static org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks.createURI;
+
+import java.net.URISyntaxException;
+
+import org.eclipse.jface.viewers.StyledString;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.IAnnotationBinding;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IPackageBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+
+import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.corext.util.Messages;
+
+import org.eclipse.jdt.ui.JavaElementLabels;
+
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaUIMessages;
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks.JavaElementLinkedLabelComposer;
+
+public class BindingLinkedLabelComposer extends JavaElementLinkedLabelComposer {
+
+ private static final String PARAMETER_ELLIPSIS_LABEL= "(...)"; //$NON-NLS-1$
+ private static final String ANON_TYPE_TAIL= "() {...}"; //$NON-NLS-1$
+ private static final String LAMBDA_LABEL= "() -&gt; {...}"; //$NON-NLS-1$
+ private static final String MISSING_LABEL= "MISSING"; //$NON-NLS-1$
+
+ private static final String INIT_NAME= ""; //$NON-NLS-1$
+
+ private static final long M_ALL_QUALIFIED= JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_FULLY_QUALIFIED;
+
+ private static final long IS_POST_QUALIFICATION= 1L << 63;
+
+ private IJavaElement fEnclosingElement;
+ private boolean fIsFromSource;
+
+ public BindingLinkedLabelComposer(IJavaElement enclosingElement, StringBuffer buffer, boolean isFromSource) {
+ super(enclosingElement, buffer);
+ fEnclosingElement= enclosingElement;
+ fIsFromSource= isFromSource;
+ }
+
+ /**
+ * <p>Supported flags:
+ * <ul>
+ * <li>{@link JavaElementLabels#ALL_FULLY_QUALIFIED} (set)</li>
+ * <li>{@link JavaElementLabels#M_PRE_RETURNTYPE}</li>
+ * <li>{@link JavaElementLabels#M_PARAMETER_ANNOTATIONS}</li>
+ * <li>{@link JavaElementLabels#M_PARAMETER_TYPES}</li>
+ * <li>{@link JavaElementLabels#M_PARAMETER_NAMES}</li>
+ * <li>{@link JavaElementLabels#M_EXCEPTIONS}</li>
+ * <li>{@link JavaElementLabels#M_PRE_TYPE_PARAMETERS}</li>
+ * <li>{@link JavaElementLabels#F_PRE_TYPE_SIGNATURE}</li>
+ * <li>{@link JavaElementLabels#T_TYPE_PARAMETERS}</li>
+ * <li>{@link JavaElementLabels#USE_RESOLVED}</li>
+ * <li>{@link JavaElementLabels#M_POST_QUALIFIED}</li>
+ * <li>{@link JavaElementLabels#F_POST_QUALIFIED}</li>
+ * <li>{@link JavaElementLabels#T_POST_QUALIFIED}</li>
+ * <li>{@link JavaElementLabels#TP_POST_QUALIFIED}</li>
+ * </ul>
+ * @param binding a binding to be rendered
+ * @param flags rendering flags, see above for supported values.
+ */
+ public void appendBindingLabel(IBinding binding, long flags) {
+ switch (binding.getKind()) {
+ case IBinding.METHOD:
+ appendMethodBindingLabel((IMethodBinding) binding, flags);
+ return;
+ case IBinding.TYPE:
+ appendTypeBindingLabel((ITypeBinding) binding, flags);
+ return;
+ case IBinding.VARIABLE:
+ appendVariableLabel((IVariableBinding) binding, flags);
+ return;
+ case IBinding.PACKAGE:
+ appendPackageLabel((IPackageBinding) binding, flags);
+ break;
+ case IBinding.ANNOTATION:
+ case IBinding.MEMBER_VALUE_PAIR:
+ // not used for hovers
+ }
+ }
+
+ private void appendMethodBindingLabel(IMethodBinding method, long flags) {
+ long qualificationFlags = flags & (QUALIFIER_FLAGS | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.T_CONTAINER_QUALIFIED);
+ if (getFlag(flags, JavaElementLabels.T_POST_QUALIFIED))
+ flags |= JavaElementLabels.M_POST_QUALIFIED;
+ flags &= ~JavaElementLabels.T_POST_QUALIFIED;
+ IMethodBinding origMethod= method;
+ IBinding declaringMember= method.getDeclaringMember();
+ if (declaringMember != null) {
+ if (isEnclosingElement(method.getJavaElement())) {
+ // don't render top-level as lambda
+ method= method.getMethodDeclaration(); // for the main part show the SAM instead
+ } else {
+ appendLambdaLabel(method, flags);
+ return;
+ }
+ }
+
+ if (!getFlag(flags, JavaElementLabels.USE_RESOLVED)) {
+ method= method.getMethodDeclaration();
+ }
+ if (fIsFromSource) {
+ flags &= ~JavaElementLabels.T_FULLY_QUALIFIED;
+ }
+ boolean isInitializer= method.getName().equals(INIT_NAME);
+
+ // type parameters
+ if (getFlag(flags, JavaElementLabels.M_PRE_TYPE_PARAMETERS)) {
+ ITypeBinding[] typeParameters= method.getTypeParameters();
+ if (typeParameters.length > 0) {
+ appendTypeArgumentsBindingLabel(typeParameters, null, flags);
+ fBuffer.append(' ');
+ }
+ }
+
+ // return type
+ if (getFlag(flags, JavaElementLabels.M_PRE_RETURNTYPE) && !method.isConstructor() && !isInitializer) {
+ appendTypeBindingLabel(method.getReturnType(), flags);
+ fBuffer.append(' ');
+ }
+
+ // qualification
+ if (getFlag(flags, JavaElementLabels.M_FULLY_QUALIFIED | JavaElementLabels.T_CONTAINER_QUALIFIED)) {
+ appendTypeBindingLabel(method.getDeclaringClass(), qualificationFlags);
+ fBuffer.append('.');
+ }
+
+ if (isInitializer) {
+ fBuffer.append(JavaUIMessages.JavaElementLabels_initializer);
+ } else {
+ appendNameLink(method, origMethod);
+ }
+
+ if (!isInitializer) {
+ // constructor type arguments
+ if (getFlag(flags, JavaElementLabels.T_TYPE_PARAMETERS) && method.isConstructor()) {
+ appendTypeArgumentsBindingLabel(method.getTypeArguments(), null, flags);
+ }
+
+ // parameters
+ fBuffer.append('(');
+ if (getFlag(flags, JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES)) {
+ ITypeBinding[] types= null;
+ int nParams= 0;
+ boolean renderVarargs= false;
+ boolean isPolymorphic= false;
+ IMethod iMethod= getIMethod(method);
+ if (getFlag(flags, JavaElementLabels.M_PARAMETER_TYPES)) {
+ types= method.getParameterTypes();
+ nParams= types.length;
+ renderVarargs= method.isVarargs();
+ // retrieval of flag isPolymorphic uses strategy from JavaElementLabelComposer:
+ if (getFlag(flags, JavaElementLabels.USE_RESOLVED)
+ && iMethod != null
+ && iMethod.isResolved()
+ && iMethod.getParameterTypes().length == 1
+ && JavaModelUtil.isPolymorphicSignature(iMethod)) {
+ renderVarargs= false;
+ isPolymorphic= true;
+ }
+ }
+ String[] names= null;
+ if (getFlag(flags, JavaElementLabels.M_PARAMETER_NAMES) && iMethod != null) {
+ // mostly from JavaElementLabelComposer:
+ try {
+ names= iMethod.getParameterNames();
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ if (isPolymorphic) {
+ // handled specially below
+ } else if (types == null) {
+ nParams= names.length;
+ } else { // types != null
+ if (nParams != names.length) {
+ if (types.length > names.length) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=99137
+ nParams= names.length;
+ ITypeBinding[] typesWithoutSyntheticParams= new ITypeBinding[nParams];
+ System.arraycopy(types, types.length - nParams, typesWithoutSyntheticParams, 0, nParams);
+ types= typesWithoutSyntheticParams;
+ } else {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=101029
+ // JavaPlugin.logErrorMessage("JavaElementLabels: Number of param types(" + nParams + ") != number of names(" + names.length + "): " + method.getElementName()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ names= null; // no names rendered
+ }
+ }
+ }
+ }
+ IAnnotationBinding[][] parameterAnnotations= null;
+ if (nParams > 0 && getFlag(flags, JavaElementLabels.M_PARAMETER_ANNOTATIONS)) {
+ parameterAnnotations= new IAnnotationBinding[nParams][];
+ for (int i= 0; i < nParams; i++) {
+ parameterAnnotations[i]= method.getParameterAnnotations(i);
+ }
+ }
+
+ for (int i= 0; i < nParams; i++) {
+ if (i > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ if (parameterAnnotations != null && i < parameterAnnotations.length) {
+ appendAnnotationLabels(parameterAnnotations[i], flags);
+ }
+
+ if (types != null) {
+ ITypeBinding paramSig= types[i];
+ if (renderVarargs && (i == nParams - 1)) {
+ int newDim= paramSig.getDimensions() - 1;
+ appendTypeBindingLabel(paramSig.getElementType(), flags);
+ for (int k= 0; k < newDim; k++) {
+ fBuffer.append('[').append(']');
+ }
+ fBuffer.append(JavaElementLabels.ELLIPSIS_STRING);
+ } else {
+ appendTypeBindingLabel(paramSig, flags);
+ }
+ }
+ if (names != null) {
+ if (types != null) {
+ fBuffer.append(' ');
+ }
+ if (isPolymorphic) {
+ fBuffer.append(names[0] + i);
+ } else {
+ fBuffer.append(names[i]);
+ }
+ }
+ }
+ } else {
+ if (method.getParameterTypes().length > 0) {
+ fBuffer.append(JavaElementLabels.ELLIPSIS_STRING);
+ }
+ }
+ fBuffer.append(')');
+
+
+ if (getFlag(flags, JavaElementLabels.M_EXCEPTIONS)) {
+ ITypeBinding[] types= method.getExceptionTypes();
+ if (types.length > 0) {
+ fBuffer.append(" throws "); //$NON-NLS-1$
+ for (int i= 0; i < types.length; i++) {
+ if (i > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ appendTypeBindingLabel(types[i], flags);
+ }
+ }
+ }
+
+ if (getFlag(flags, JavaElementLabels.M_APP_TYPE_PARAMETERS)) {
+ int offset= fBuffer.length();
+ ITypeBinding[] typeParameters= method.isParameterizedMethod()
+ ? method.getTypeArguments()
+ : method.getTypeParameters();
+ appendTypeArgumentsBindingLabel(typeParameters, String.valueOf(' '), flags);
+ if (getFlag(flags, JavaElementLabels.COLORIZE) && offset != fBuffer.length()) {
+ fBuffer.setStyle(offset, fBuffer.length() - offset, StyledString.DECORATIONS_STYLER);
+ }
+ }
+ }
+
+ // post qualification
+ if (getFlag(flags, JavaElementLabels.M_POST_QUALIFIED)) {
+ fBuffer.append(JavaElementLabels.CONCAT_STRING);
+ if (declaringMember != null && origMethod != method) {
+ // show lambda as qualification of a SAM
+ appendLambdaLabel(origMethod, qualificationFlags | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ fBuffer.append(' ');
+ appendTypeBindingLabel(origMethod.getMethodDeclaration().getDeclaringClass(), M_ALL_QUALIFIED | IS_POST_QUALIFICATION);
+ } else {
+ appendTypeBindingLabel(method.getDeclaringClass(), getPostQualificationFlags(flags));
+ }
+ }
+ }
+
+ private void appendVariableLabel(IVariableBinding variable, long flags) {
+ long qualificationFlags = flags & (QUALIFIER_FLAGS | JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.T_CONTAINER_QUALIFIED);
+ if (fIsFromSource) {
+ flags &= ~JavaElementLabels.T_FULLY_QUALIFIED;
+ }
+ if (getFlag(flags, JavaElementLabels.T_POST_QUALIFIED))
+ flags |= JavaElementLabels.F_POST_QUALIFIED;
+ flags &= ~JavaElementLabels.T_POST_QUALIFIED;
+
+ if (getFlag(flags, JavaElementLabels.F_PRE_TYPE_SIGNATURE) && !Flags.isEnum(variable.getModifiers())) {
+ appendTypeBindingLabel(variable.getType(), flags);
+ fBuffer.append(' ');
+ }
+
+ // qualification
+ if (getFlag(flags, JavaElementLabels.F_FULLY_QUALIFIED)) {
+ appendVariableQualification(variable, qualificationFlags);
+ fBuffer.append('.');
+ }
+ if (variable.isField()) {
+ appendNameLink(variable, variable);
+ } else {
+ fBuffer.append(variable.getName());
+ }
+
+ if (getFlag(flags, JavaElementLabels.F_POST_QUALIFIED)) {
+ fBuffer.append(JavaElementLabels.CONCAT_STRING);
+ appendVariableQualification(variable, getPostQualificationFlags(qualificationFlags));
+ }
+ }
+
+ private void appendVariableQualification(IVariableBinding variable, long flags) {
+ if (variable.isField()) {
+ appendTypeBindingLabel(variable.getDeclaringClass(), flags);
+ } else {
+ IMethodBinding declaringMethod= variable.getDeclaringMethod();
+ if (declaringMethod != null) {
+ IBinding declaringMember= declaringMethod.getDeclaringMember();
+ if (declaringMember != null) {
+ appendLambdaLabel(declaringMethod, flags);
+ fBuffer.append(' ');
+ appendMethodBindingLabel(declaringMethod.getMethodDeclaration(), (flags & QUALIFIER_FLAGS) | M_ALL_QUALIFIED);
+ } else {
+ appendMethodBindingLabel(declaringMethod, flags | M_ALL_QUALIFIED);
+ }
+ } else {
+ // workaround for: local variable inside initializer doesn't yet expose the #getDeclaringMethod();
+ IJavaElement element= variable.getJavaElement();
+ if (element != null && element.getParent() != null)
+ appendElementLabel(element.getParent(), flags);
+ else
+ fBuffer.append(MISSING_LABEL);
+ }
+ }
+ }
+
+ private void appendLambdaLabel(IMethodBinding lambdaBinding, long flags) {
+ long qualificationFlags = flags & (QUALIFIER_FLAGS | JavaElementLabels.ALL_FULLY_QUALIFIED);
+ if (fIsFromSource) {
+ flags &= ~JavaElementLabels.T_FULLY_QUALIFIED;
+ }
+ if (getFlag(flags, JavaElementLabels.M_FULLY_QUALIFIED | JavaElementLabels.T_FULLY_QUALIFIED)) {
+ appendBindingLabel(lambdaBinding.getDeclaringMember(), qualificationFlags);
+ fBuffer.append('.');
+ fBuffer.append(LAMBDA_LABEL);
+ } else {
+ IMethodBinding sam= lambdaBinding.getMethodDeclaration();
+ appendMethodBindingLabel(sam, flags & ~JavaElementLabels.ALL_POST_QUALIFIED);
+ }
+ if (getFlag(flags, JavaElementLabels.M_POST_QUALIFIED|JavaElementLabels.T_POST_QUALIFIED)) {
+ fBuffer.append(JavaElementLabels.CONCAT_STRING);
+ qualificationFlags |= JavaElementLabels.ALL_FULLY_QUALIFIED;
+ appendBindingLabel(lambdaBinding.getDeclaringMember(), qualificationFlags);
+ fBuffer.append('.');
+ fBuffer.append(LAMBDA_LABEL);
+ fBuffer.append(' ');
+ appendTypeBindingLabel(lambdaBinding.getDeclaringClass(), flags & (QUALIFIER_FLAGS | JavaElementLabels.ALL_FULLY_QUALIFIED) | IS_POST_QUALIFICATION);
+ }
+ }
+
+ private void appendTypeBindingLabel(ITypeBinding typeBinding, long flags) {
+ long typeRefFlags= flags & ~JavaElementLabels.ALL_POST_QUALIFIED;
+ if (fIsFromSource) {
+ typeRefFlags &= ~JavaElementLabels.ALL_FULLY_QUALIFIED;
+ }
+ // qualification of anonymous (class or lambda):
+ IBinding declaringMember= typeBinding.getDeclaringMember();
+ if (declaringMember != null
+ && getFlag(flags, JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.T_CONTAINER_QUALIFIED))
+ {
+ long qualificationFlags= flags;
+ if (getFlag(flags, JavaElementLabels.T_FULLY_QUALIFIED))
+ qualificationFlags |= JavaElementLabels.ALL_FULLY_QUALIFIED;
+ else if (getFlag(flags, JavaElementLabels.T_CONTAINER_QUALIFIED))
+ qualificationFlags |= (JavaElementLabels.F_FULLY_QUALIFIED | JavaElementLabels.M_FULLY_QUALIFIED);
+ appendBindingLabel(declaringMember, qualificationFlags);
+ fBuffer.append('.');
+ flags &= ~(JavaElementLabels.T_FULLY_QUALIFIED | JavaElementLabels.M_FULLY_QUALIFIED | JavaElementLabels.T_CONTAINER_QUALIFIED); // qualification is done
+ }
+ if (!typeBinding.isArray()) { // different textual order for type annotations on array types
+ appendAnnotationLabels(typeBinding.getTypeAnnotations(), typeRefFlags);
+ }
+ if (typeBinding.isPrimitive()) {
+ fBuffer.append(typeBinding.getName());
+ } else if (typeBinding.isArray()) {
+ appendTypeBindingLabel(typeBinding.getElementType(), flags);
+ IAnnotationBinding[] typeAnnotations= typeBinding.getTypeAnnotations();
+ if (typeAnnotations.length > 0) {
+ fBuffer.append(' ');
+ appendAnnotationLabels(typeAnnotations, typeRefFlags);
+ }
+ for (int dim= typeBinding.getDimensions(); dim > 0; dim--) {
+ fBuffer.append('[').append(']');
+ }
+ } else if (typeBinding.isClass() || typeBinding.isInterface() || typeBinding.isEnum()) {
+ fBuffer.append(getTypeLink(typeBinding, flags));
+ if (getFlag(flags, JavaElementLabels.T_TYPE_PARAMETERS)) {
+ ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
+ if (typeArguments.length > 0) {
+ appendTypeArgumentsBindingLabel(typeArguments, null, typeRefFlags);
+ } else {
+ ITypeBinding[] typeParameters= typeBinding.getTypeParameters();
+ appendTypeArgumentsBindingLabel(typeParameters, null, typeRefFlags);
+ }
+ }
+ } else if (typeBinding.isParameterizedType()) {
+ fBuffer.append(getTypeLink(typeBinding.getTypeDeclaration(), flags));
+ fBuffer.append(getLT());
+ ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
+ for (int i= 0; i < typeArguments.length; i++) {
+ if (i > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ appendTypeBindingLabel(typeArguments[i], typeRefFlags);
+ }
+ fBuffer.append(getGT());
+ } else if (typeBinding.isTypeVariable()) {
+ appendNameLink(typeBinding, typeBinding);
+ // heuristically include type bounds only when not composing a post-qualification
+ if (!getFlag(flags, IS_POST_QUALIFICATION)) {
+ ITypeBinding[] bounds= typeBinding.getTypeBounds();
+ if (hasRelevantBound(bounds)) {
+ fBuffer.append(" extends "); //$NON-NLS-1$
+ for (int i= 0; i < bounds.length; i++) {
+ if (i > 0)
+ fBuffer.append(" &amp; "); //$NON-NLS-1$
+ appendTypeBindingLabel(bounds[i], typeRefFlags | JavaElementLabels.T_TYPE_PARAMETERS);
+ }
+ }
+ }
+ // post qualification
+ if (getFlag(flags, JavaElementLabels.TP_POST_QUALIFIED)) {
+ fBuffer.append(JavaElementLabels.CONCAT_STRING);
+ if (typeBinding.getDeclaringClass() != null)
+ appendTypeBindingLabel(typeBinding.getDeclaringClass(), getPostQualificationFlags(flags));
+ else
+ appendMethodBindingLabel(typeBinding.getDeclaringMethod(), getPostQualificationFlags(flags));
+ }
+ return;
+ } else if (typeBinding.isAnnotation()) {
+ fBuffer.append(getTypeLink(typeBinding, flags));
+ } else if (typeBinding.isWildcardType()) {
+ ITypeBinding bound= typeBinding.getBound();
+ if (bound == null || bound.getSuperclass() == null) { // no relevant bound / only j.l.Object
+ fBuffer.append('?');
+ } else {
+ if (typeBinding.isUpperbound())
+ fBuffer.append("? extends "); //$NON-NLS-1$
+ else
+ fBuffer.append("? super "); //$NON-NLS-1$
+ appendTypeBindingLabel(bound, typeRefFlags);
+ }
+ } else if (typeBinding.isCapture()) {
+ appendTypeBindingLabel(typeBinding.getWildcard(), flags);
+ }
+ // post qualification
+ if (getFlag(flags, JavaElementLabels.T_POST_QUALIFIED)) {
+ // search the innermost declaring thing:
+ IBinding declaringBinding= typeBinding.getDeclaringMember();
+ if (declaringBinding == null) {
+ declaringBinding= typeBinding.getDeclaringMethod();
+ if (declaringBinding == null)
+ declaringBinding= typeBinding.getDeclaringClass();
+ if (declaringBinding == null)
+ declaringBinding= typeBinding.getPackage();
+ }
+ if (declaringBinding != null) {
+ fBuffer.append(JavaElementLabels.CONCAT_STRING);
+ // heuristics: JavaElementsLabelComposer does not include method parameters in post qualification of local type:
+ appendBindingLabel(declaringBinding, getPostQualificationFlags(flags) & ~JavaElementLabels.M_PARAMETER_TYPES);
+ }
+ }
+ }
+
+ private void appendTypeArgumentsBindingLabel(ITypeBinding[] parameters, String separator, long flags) {
+ if (parameters.length > 0) {
+ if (separator != null)
+ fBuffer.append(separator);
+ fBuffer.append(getLT());
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ appendTypeBindingLabel(parameters[i], flags);
+ }
+ fBuffer.append(getGT());
+ }
+ }
+
+ private void appendAnnotationLabels(IAnnotationBinding[] annotationBindings, long flags) {
+ for (int i= 0; i < annotationBindings.length; i++) {
+ appendAnnotationLabel(annotationBindings[i], flags);
+ fBuffer.append(' ');
+ }
+ }
+
+ private void appendAnnotationLabel(IAnnotationBinding annotation, long flags) {
+ fBuffer.append('@');
+ appendTypeBindingLabel(annotation.getAnnotationType(), flags);
+ IMemberValuePairBinding[] memberValuePairs= annotation.getDeclaredMemberValuePairs();
+ if (memberValuePairs.length == 0)
+ return;
+ if (fIsFromSource) {
+ flags &= ~JavaElementLabels.T_FULLY_QUALIFIED;
+ }
+ fBuffer.append('(');
+ for (int i= 0; i < memberValuePairs.length; i++) {
+ if (i > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ IMemberValuePairBinding memberValuePair= memberValuePairs[i];
+ fBuffer.append(getMemberName(fEnclosingElement, annotation.getName(), memberValuePair.getName()));
+ fBuffer.append('=');
+ long valueFlags= flags & ~(JavaElementLabels.F_PRE_TYPE_SIGNATURE|JavaElementLabels.M_PRE_RETURNTYPE|JavaElementLabels.ALL_POST_QUALIFIED);
+ appendAnnotationValue(annotation, memberValuePair.getValue(), valueFlags);
+ }
+ fBuffer.append(')');
+ }
+
+ private void appendAnnotationValue(IAnnotationBinding annotation, Object value, long flags) {
+ // Note: To be bug-compatible with Javadoc from Java 5/6/7, we currently don't escape HTML tags in String-valued annotations.
+ if (value instanceof Object[]) {
+ fBuffer.append('{');
+ Object[] values= (Object[]) value;
+ for (int j= 0; j < values.length; j++) {
+ if (j > 0)
+ fBuffer.append(JavaElementLabels.COMMA_STRING);
+ value= values[j];
+ appendAnnotationValue(annotation, value, flags);
+ }
+ fBuffer.append('}');
+ } else {
+ if (value instanceof ITypeBinding) {
+ appendTypeBindingLabel((ITypeBinding) value, flags);
+ fBuffer.append(".class"); //$NON-NLS-1$
+ } else if (value instanceof String) {
+ fBuffer.append(htmlEscape(ASTNodes.getEscapedStringLiteral((String) value)));
+ } else if (value instanceof IVariableBinding) {
+ appendVariableLabel((IVariableBinding) value, flags);
+ } else if (value instanceof IAnnotationBinding) {
+ appendAnnotationLabel((IAnnotationBinding) value, flags);
+ } else if (value instanceof Character) {
+ fBuffer.append(ASTNodes.getEscapedCharacterLiteral(((Character) value).charValue()));
+ } else { // other primitive literals
+ fBuffer.append(String.valueOf(value));
+ }
+ }
+ }
+
+ private void appendPackageLabel(IPackageBinding binding, long flags) {
+ appendAnnotationLabels(binding.getAnnotations(), flags);
+ String qualifiedName= binding.getName();
+ if (qualifiedName.length() > 0) {
+ IJavaElement packageElement= binding.getJavaElement();
+ try {
+ String uri= createURI(JAVADOC_SCHEME, packageElement);
+ fBuffer.append(createHeaderLink(uri, qualifiedName));
+ } catch (URISyntaxException e) {
+ JavaPlugin.log(e);
+ fBuffer.append(qualifiedName);
+ }
+ } else {
+ fBuffer.append("(default package)"); //$NON-NLS-1$
+ }
+ }
+
+ // consider only relevant bounds / ignore j.l.Object
+ private boolean hasRelevantBound(ITypeBinding[] bounds) {
+ if (bounds != null) {
+ for (int i= 0; i < bounds.length; i++)
+ if (bounds[i].isInterface() || bounds[i].getSuperclass() != null)
+ return true;
+ }
+ return false;
+ }
+
+ private long getPostQualificationFlags(long flags) {
+ flags |= JavaElementLabels.ALL_FULLY_QUALIFIED | JavaElementLabels.M_PARAMETER_TYPES | IS_POST_QUALIFICATION;
+ flags &= ~JavaElementLabels.ALL_POST_QUALIFIED;
+ flags &= ~(JavaElementLabels.T_TYPE_PARAMETERS |
+ JavaElementLabels.M_PRE_TYPE_PARAMETERS | JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.M_PARAMETER_NAMES);
+ return flags;
+ }
+
+ // applicable for types, methods & fields
+ private void appendNameLink(IBinding binding, IBinding origBinding) {
+ try {
+ IJavaElement javaElement= origBinding.getJavaElement();
+ if (!isEnclosingElement(javaElement)) {
+ IJavaElement element= binding.getJavaElement();
+ if (element == null) // extra safety, not seen during tests
+ element= fEnclosingElement;
+ String uri= createURI(JAVADOC_SCHEME, element);
+ String title= getLinkTitle(binding);
+ if (title != null) {
+ title= Messages.format(JavaUIMessages.JavaElementLinks_title, title);
+ } else {
+ title= ""; //$NON-NLS-1$
+ }
+ fBuffer.append(createHeaderLink(uri, binding.getName(), title));
+ return;
+ }
+ } catch (URISyntaxException e) {
+ JavaPlugin.log(e);
+ }
+ fBuffer.append(binding.getName());
+ }
+
+ private String getLinkTitle(IBinding binding) {
+ if (binding instanceof ITypeBinding) {
+ IMethodBinding declaringMethod= ((ITypeBinding) binding).getDeclaringMethod();
+ String title= null;
+ ITypeBinding declaringClass= null;
+ if (declaringMethod != null) {
+ title= '.'+declaringMethod.getName()+PARAMETER_ELLIPSIS_LABEL;
+ declaringClass= declaringMethod.getDeclaringClass();
+ } else {
+ declaringClass= ((ITypeBinding) binding).getDeclaringClass();
+ }
+ if (declaringClass != null) {
+ String typeName= getTypeName(declaringClass, JavaElementLabels.ALL_FULLY_QUALIFIED);
+ return title != null ? typeName+title : typeName;
+ }
+ } else if (binding instanceof IMethodBinding) {
+ return getTypeName(((IMethodBinding) binding).getDeclaringClass(), JavaElementLabels.ALL_FULLY_QUALIFIED);
+ } else if (binding instanceof IVariableBinding) {
+ return getTypeName(((IVariableBinding) binding).getDeclaringClass(), JavaElementLabels.ALL_FULLY_QUALIFIED);
+ }
+ return null;
+ }
+
+ private String getTypeLink(ITypeBinding typeBinding, long flags) {
+ if (isEnclosingElement(typeBinding.getJavaElement())) {
+ return getTypeName(typeBinding, flags);
+ }
+ typeBinding= typeBinding.getTypeDeclaration();
+ String typeName = getTypeName(typeBinding, flags);
+ String qualifiedName = getTypeName(typeBinding, JavaElementLabels.T_FULLY_QUALIFIED);
+ String title= ""; //$NON-NLS-1$
+ int qualifierLength= qualifiedName.length() - typeName.length() - 1;
+ if (qualifierLength > 0) {
+ if (qualifiedName.endsWith(typeName)) {
+ title= qualifiedName.substring(0, qualifierLength);
+ title= Messages.format(JavaUIMessages.JavaElementLinks_title, title);
+ } else {
+ title= qualifiedName; // Not expected. Just show the whole qualifiedName.
+ }
+ }
+
+ try {
+ String uri= createURI(JAVADOC_SCHEME, fEnclosingElement, qualifiedName, null, null);
+ return createHeaderLink(uri, typeName, title);
+ } catch (URISyntaxException e) {
+ JavaPlugin.log(e);
+ return typeName;
+ }
+ }
+
+ private String getTypeName(ITypeBinding typeBinding, long flags) {
+ if (typeBinding.isLocal()) {
+ StringBuilder buf= new StringBuilder();
+ IMethodBinding declaringMethod= typeBinding.getDeclaringMethod();
+ if (getFlag(flags, JavaElementLabels.T_FULLY_QUALIFIED|JavaElementLabels.T_CONTAINER_QUALIFIED)) {
+ if (declaringMethod != null) {
+ buf.append(getTypeName(declaringMethod.getDeclaringClass(), flags));
+ buf.append('.');
+ buf.append(declaringMethod.getName());
+ if (declaringMethod.getParameterTypes().length > 0) {
+ buf.append(PARAMETER_ELLIPSIS_LABEL);
+ } else {
+ buf.append("()"); //$NON-NLS-1$
+ }
+ } else {
+ buf.append(getTypeName(typeBinding.getDeclaringClass(), flags));
+ IBinding declaringMember= typeBinding.getDeclaringMember();
+ if (declaringMember != null) {
+ buf.append('.');
+ if (declaringMember instanceof ITypeBinding) {
+ buf.append(getTypeName((ITypeBinding) declaringMember, flags));
+ } else { // field or method
+ String name= declaringMember.getName();
+ if (name.equals(INIT_NAME))
+ buf.append(JavaUIMessages.JavaElementLabels_initializer);
+ else
+ buf.append(name);
+ }
+ }
+ }
+ buf.append('.');
+ }
+ if (typeBinding.isAnonymous()) {
+ buf.append("new "); //$NON-NLS-1$
+ ITypeBinding[] interfaces= typeBinding.getInterfaces();
+ if (interfaces.length > 0) {
+ buf.append(interfaces[0].getName());
+ } else if (typeBinding.getSuperclass() != null){
+ buf.append(typeBinding.getSuperclass().getName());
+ } else {
+ buf.append(MISSING_LABEL);
+ }
+ buf.append(ANON_TYPE_TAIL);
+ } else {
+ buf.append(typeBinding.getName());
+ }
+ return buf.toString();
+ }
+ if (getFlag(flags, JavaElementLabels.T_FULLY_QUALIFIED)) {
+ return typeBinding.getQualifiedName();
+ } else if (getFlag(flags, JavaElementLabels.T_CONTAINER_QUALIFIED)) {
+ ITypeBinding declaringClass= typeBinding.getDeclaringClass();
+ if (declaringClass != null) {
+ StringBuilder buf= new StringBuilder(getTypeName(declaringClass, flags));
+ buf.append('.');
+ buf.append(typeBinding.getName());
+ return buf.toString();
+ }
+ }
+ return typeBinding.getName();
+ }
+
+ private IMethod getIMethod(IMethodBinding method) {
+ IJavaElement element= method.getJavaElement();
+ if (element == null || element.getElementType() != IJavaElement.METHOD)
+ return null; // extra safety, not seen in tests (triggered from ctor of local class inside initializer)
+ IMethod iMethod= (IMethod) element;
+ if (isEnclosingElement(iMethod)) {
+ return (IMethod) fEnclosingElement; // benefit from better details on LambdaMethod
+ }
+ return iMethod;
+ }
+
+ private boolean isEnclosingElement(IJavaElement element) {
+ if (element == null)
+ return false;
+ if (element.equals(fEnclosingElement))
+ return true;
+ String enclosingKey= null;
+ // unify different representations of a lambda: LambdaMethod, LambdaExpression, IMethod (SAM)
+ switch (fEnclosingElement.getElementType()) {
+ case IJavaElement.TYPE:
+ if (((IType)fEnclosingElement).isLambda() && element.getElementType() == IJavaElement.METHOD) {
+ // navigate from LambdaExpression to LambdaMethod to be comparable to IMethod:
+ try {
+ IJavaElement[] children= ((IType) fEnclosingElement).getChildren();
+ if (children != null && children.length == 1) {
+ if (children[0].getElementType() == IJavaElement.METHOD) {
+ enclosingKey= ((IMethod) children[0]).getKey();
+ }
+ }
+ } catch (JavaModelException e) {
+ // continue without key
+ }
+ } else {
+ enclosingKey= ((IType) fEnclosingElement).getKey();
+ }
+ break;
+ case IJavaElement.METHOD:
+ enclosingKey= ((IMethod) fEnclosingElement).getKey();
+ break;
+ }
+ if (enclosingKey != null) {
+ switch (element.getElementType()) {
+ case IJavaElement.TYPE:
+ return enclosingKey.equals(((IType) element).getKey());
+ case IJavaElement.METHOD:
+ return enclosingKey.equals(((IMethod) element).getKey());
+ }
+ }
+ return false;
+ }
+
+ private String htmlEscape(String escaped) {
+ return escaped.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+ }
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
index 02b7554302..d38cc44e2c 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
@@ -196,7 +196,7 @@ public class JavaElementLabelComposer {
}
- private final static long QUALIFIER_FLAGS= JavaElementLabels.P_COMPRESSED | JavaElementLabels.USE_RESOLVED;
+ final static long QUALIFIER_FLAGS= JavaElementLabels.P_COMPRESSED | JavaElementLabels.USE_RESOLVED;
private static final Styler QUALIFIER_STYLE= StyledString.QUALIFIER_STYLER;
private static final Styler COUNTER_STYLE= StyledString.COUNTER_STYLER;
@@ -219,7 +219,7 @@ public class JavaElementLabelComposer {
protected final FlexibleBuffer fBuffer;
- private static final boolean getFlag(long flags, long flag) {
+ protected static final boolean getFlag(long flags, long flag) {
return (flags & flag) != 0;
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java
index 43add76fa7..c9441250a2 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLinks.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2014 IBM Corporation and others.
+ * Copyright (c) 2008, 2015 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for Bug 403917 - [1.8] Render TYPE_USE annotations in Javadoc hover/view
*******************************************************************************/
package org.eclipse.jdt.internal.ui.viewsupport;
@@ -39,6 +40,7 @@ import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
@@ -102,7 +104,7 @@ public class JavaElementLinks {
void handleTextSet();
}
- private static final class JavaElementLinkedLabelComposer extends JavaElementLabelComposer {
+ static class JavaElementLinkedLabelComposer extends JavaElementLabelComposer {
private final IJavaElement fElement;
public JavaElementLinkedLabelComposer(IJavaElement member, StringBuffer buf) {
@@ -665,7 +667,7 @@ public class JavaElementLinks {
* @return the HTML link
* @since 3.10
*/
- private static String createHeaderLink(String uri, String label, String title) {
+ public static String createHeaderLink(String uri, String label, String title) {
if (title.length() > 0) {
title= " title='" + title + "'"; //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -708,4 +710,27 @@ public class JavaElementLinks {
return label.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
}
+
+ /**
+ * Returns the label for a binding with the flags as defined by {@link JavaElementLabels}.
+ * Referenced element names in the label are rendered as header links.
+ *
+ * @param binding the binding to render
+ * @param element the corresponding Java element, used for javadoc hyperlinks
+ * @param flags the rendering flags
+ * @param haveSource true when looking at an ICompilationUnit which enables the use of short type names
+ * @return the label of the binding
+ * @since 3.11
+ */
+ public static String getBindingLabel(IBinding binding, IJavaElement element, long flags, boolean haveSource) {
+ StringBuffer buf= new StringBuffer();
+
+ if (!Strings.USE_TEXT_PROCESSOR) {
+ new BindingLinkedLabelComposer(element, buf, haveSource).appendBindingLabel(binding, flags);
+ return Strings.markJavaElementLabelLTR(buf.toString());
+ } else {
+ String label= JavaElementLabels.getElementLabel(element, flags);
+ return label.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ }
}

Back to the top