From 3038cf1532da561e51daa01b9318921e33bf0e6f Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 18 Sep 2017 19:07:26 +0300 Subject: [PATCH] show parameter's JavaDoc in completion parameter info popup --- .../api/impls/MethodParameterInfoHandler.java | 35 +++++++++++++----- .../javadoc/JavaDocInfoGenerator.java | 25 +++++++++++++ .../completion/CompletionHintsTest.java | 14 +++---- .../parameterInfo/ParameterInfoUIContext.java | 1 + .../hint/ParameterInfoComponent.java | 37 +++++++++++++++---- .../MockParameterInfoUIContext.java | 5 +++ .../jetbrains/python/PyParameterInfoTest.java | 5 +++ 7 files changed, 97 insertions(+), 25 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java index 62135ecb3d38..cd21f5792fd9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java @@ -596,6 +596,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc assert substitutor.isValid(); paramType = substitutor.substitute(paramType); } + if (context.isSingleParameterInfo()) buffer.append(""); appendModifierList(buffer, param); buffer.append(paramType.getPresentableText(true)); String name = param.getName(); @@ -603,9 +604,16 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc buffer.append(" "); buffer.append(name); } + if (context.isSingleParameterInfo()) buffer.append(""); } - if (!context.isSingleParameterInfo()) { + if (context.isSingleParameterInfo()) { + String javaDoc = new JavaDocInfoGenerator(param.getProject(), param).generateMethodParameterJavaDoc(); + if (javaDoc != null) { + buffer.append("  ").append(javaDoc).append(""); + } + } + else { int endOffset = buffer.length(); if (j < numParams - 1) { @@ -628,15 +636,22 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc buffer.append(")"); } - return context.setupUIComponentPresentation( - buffer.toString(), - highlightStartOffset, - highlightEndOffset, - !context.isUIComponentEnabled(), - method.isDeprecated() && !context.isSingleParameterInfo() && !context.isSingleOverload(), - false, - context.getDefaultParameterColor() - ); + String text = buffer.toString(); + if (context.isSingleParameterInfo()) { + context.setupRawUIComponentPresentation(text); + return text; + } + else { + return context.setupUIComponentPresentation( + text, + highlightStartOffset, + highlightEndOffset, + !context.isUIComponentEnabled(), + method.isDeprecated() && !context.isSingleParameterInfo() && !context.isSingleOverload(), + false, + context.getDefaultParameterColor() + ); + } } private static void appendModifierList(@NotNull StringBuilder buffer, @NotNull PsiModifierListOwner owner) { diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index a16f19815bd1..dd25f394a780 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -943,6 +943,31 @@ public class JavaDocInfoGenerator { if (generatePrologueAndEpilogue) generateEpilogue(buffer); } + public String generateMethodParameterJavaDoc() { + if (!(myElement instanceof PsiParameter)) return null; + PsiParameter parameter = (PsiParameter)myElement; + PsiMethod method = PsiTreeUtil.getParentOfType(parameter, PsiMethod.class); + if (method == null) return null; + PsiParameterList parameterList = method.getParameterList(); + if (parameter.getParent() != parameterList) return null; + final PsiDocComment docComment = getDocComment(method); + final PsiDocTag[] localTags = docComment != null ? docComment.getTags() : PsiDocTag.EMPTY_ARRAY; + int parameterIndex = parameterList.getParameterIndex(parameter); + final ParamInfo tagInfoProvider = findDocTag(localTags, parameter.getName(), method, parameterLocator(parameterIndex)); + if (tagInfoProvider == null) return null; + StringBuilder buffer = new StringBuilder(); + PsiElement[] elements = tagInfoProvider.docTag.getDataElements(); + if (elements.length == 0) return null; + String text = elements[0].getText(); + int spaceIndex = text.indexOf(' '); + if (spaceIndex < 0) { + spaceIndex = text.length(); + } + buffer.append(text.substring(spaceIndex)); + generateValue(buffer, elements, 1, mapProvider(tagInfoProvider.inheritDocTagProvider, true)); + return buffer.toString(); + } + private void generateMethodJavaDoc(StringBuilder buffer, PsiMethod method, boolean generatePrologueAndEpilogue) { if (generatePrologueAndEpilogue) generatePrologue(buffer); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionHintsTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionHintsTest.java index 51637736e17f..188beb9a2126 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionHintsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionHintsTest.java @@ -554,11 +554,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase { complete("getProperty(String key, String def)"); waitForAllAsyncStuff(); checkResultWithInlays("class C { void m() { System.getProperty(, ) } }"); - checkHintContents("@NotNull String"); + checkHintContents("@NotNull String  the name of the system property. "); next(); waitForAllAsyncStuff(); checkResultWithInlays("class C { void m() { System.getProperty(, ) } }"); - checkHintContents("String"); + checkHintContents("String  a default value. "); showParameterInfo(); waitForAllAsyncStuff(); checkHintContents("@NotNull String key\n" + @@ -570,11 +570,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase { complete("setProperty"); waitForAllAsyncStuff(); checkResultWithInlays("class C { void m() { System.setProperty(, ) } }"); - checkHintContents("@NotNull String"); + checkHintContents("@NotNull String  the name of the system property. "); next(); waitForAllAsyncStuff(); checkResultWithInlays("class C { void m() { System.setProperty(, ) } }"); - checkHintContents("String"); + checkHintContents("String  the value of the system property. "); showParameterInfo(); waitForAllAsyncStuff(); checkHintContents("@NotNull String key, String value"); @@ -584,7 +584,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase { configureJava("class C { void m() { System.getPro } }"); complete("getProperty(String key, String def)"); waitForAllAsyncStuff(); - checkHintContents("@NotNull String"); + checkHintContents("@NotNull String  the name of the system property. "); showParameterInfo(); waitForAllAsyncStuff(); checkHintContents("@NotNull String key\n" + @@ -599,7 +599,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase { configureJava("class C { void m() { System.getPro } }"); complete("getProperty(String key, String def)"); waitForAllAsyncStuff(); - checkHintContents("@NotNull String"); + checkHintContents("@NotNull String  the name of the system property. "); showParameterInfo(); waitForAllAsyncStuff(); checkHintContents("@NotNull String key\n" + @@ -614,7 +614,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase { configureJava("class C { void m() { System.getPro } }"); complete("getProperty(String key, String def)"); waitForAllAsyncStuff(); - checkHintContents("@NotNull String"); + checkHintContents("@NotNull String  the name of the system property. "); left(); left(); left(); diff --git a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUIContext.java b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUIContext.java index de719e5b3fbd..30fa4d3df70a 100644 --- a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUIContext.java +++ b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUIContext.java @@ -23,6 +23,7 @@ import java.awt.*; public interface ParameterInfoUIContext { String setupUIComponentPresentation(String text, int highlightStartOffset, int highlightEndOffset, boolean isDisabled, boolean strikeout, boolean isDisabledBeforeHighlight, Color background); + void setupRawUIComponentPresentation(String htmlText); boolean isUIComponentEnabled(); void setUIComponentEnabled(boolean enabled); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java index c7b955e56437..cfdfe4786132 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java @@ -174,6 +174,12 @@ public class ParameterInfoComponent extends JPanel { return resultedText; } + @Override + public void setupRawUIComponentPresentation(String htmlText) { + myPanels[i].setup(htmlText, getDefaultParameterColor()); + myPanels[i].setBorder(isLastParameterOwner() ? LAST_ITEM_BORDER : BOTTOM_BORDER); + } + @Override public String setupUIComponentPresentation(final String[] texts, final EnumSet[] flags, final Color background) { final String resultedText = myPanels[i].setup(texts, myEscapeFunction, flags, background); @@ -303,6 +309,16 @@ public class ParameterInfoComponent extends JPanel { return Stream.of(myOneLineComponents).filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining()); } + private void setup(String htmlText, Color background) { + removeAll(); + myOneLineComponents = new OneLineComponent[1]; + myOneLineComponents[0] = new OneLineComponent(); + myOneLineComponents[0].doSetup(htmlText, background); + add(myOneLineComponents[0], new GridBagConstraints(0,0,1,1,1,0, + GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0,0,0,0),0,0)); + } + private String setup(String text, Function escapeFunction, int highlightStartOffset, @@ -447,18 +463,22 @@ public class ParameterInfoComponent extends JPanel { } private String setup(@NotNull String text, @NotNull Map flagsMap, @NotNull Color background) { + if (flagsMap.isEmpty()) { + return doSetup(text, background); + } + else { + String labelText = buildLabelText(text, flagsMap); + return doSetup(labelText, background); + } + } + + private String doSetup(@NotNull String text, @NotNull Color background) { myLabel.setBackground(background); setBackground(background); myLabel.setForeground(JBColor.foreground()); - if (flagsMap.isEmpty()) { - myLabel.setText(XmlStringUtil.wrapInHtml(text)); - } - else { - String labelText = buildLabelText(text, flagsMap); - myLabel.setText(labelText); - } + myLabel.setText(XmlStringUtil.wrapInHtml(text)); //IDEA-95904 Darcula parameter info pop-up colors hard to read if (UIUtil.isUnderDarcula()) { @@ -466,6 +486,7 @@ public class ParameterInfoComponent extends JPanel { } return myLabel.getText(); } + private String buildLabelText(@NotNull final String text, @NotNull final Map flagsMap) { final StringBuilder labelText = new StringBuilder(text); final String disabledTag = FLAG_TO_TAG.get(ParameterInfoUIContextEx.Flag.DISABLE); @@ -510,7 +531,7 @@ public class ParameterInfoComponent extends JPanel { faultMap.put(highlightRange.getEndOffset(), endTag.length()); } - return XmlStringUtil.wrapInHtml(labelText); + return labelText.toString(); } private String getTag(@NotNull final String tagValue) { diff --git a/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockParameterInfoUIContext.java b/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockParameterInfoUIContext.java index 6dc50c5cb48a..c7566a4f28d9 100644 --- a/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockParameterInfoUIContext.java +++ b/platform/testFramework/src/com/intellij/testFramework/utils/parameterInfo/MockParameterInfoUIContext.java @@ -45,6 +45,11 @@ public class MockParameterInfoUIContext implements Paramet return _text; } + @Override + public void setupRawUIComponentPresentation(String htmlText) { + throw new UnsupportedOperationException(); + } + @Override public boolean isUIComponentEnabled() { return enabled; diff --git a/python/testSrc/com/jetbrains/python/PyParameterInfoTest.java b/python/testSrc/com/jetbrains/python/PyParameterInfoTest.java index 834431625c35..074203fc5912 100644 --- a/python/testSrc/com/jetbrains/python/PyParameterInfoTest.java +++ b/python/testSrc/com/jetbrains/python/PyParameterInfoTest.java @@ -783,6 +783,11 @@ public class PyParameterInfoTest extends LightMarkedTestCase { return text; } + @Override + public void setupRawUIComponentPresentation(String htmlText) { + throw new UnsupportedOperationException(); + } + @Override public boolean isUIComponentEnabled() { return true;