show parameter's JavaDoc in completion parameter info popup

This commit is contained in:
Dmitry Batrak
2017-09-18 19:10:54 +03:00
parent 37c636bcc4
commit 3038cf1532
7 changed files with 97 additions and 25 deletions
@@ -596,6 +596,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
assert substitutor.isValid();
paramType = substitutor.substitute(paramType);
}
if (context.isSingleParameterInfo()) buffer.append("<b>");
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("</b>");
}
if (!context.isSingleParameterInfo()) {
if (context.isSingleParameterInfo()) {
String javaDoc = new JavaDocInfoGenerator(param.getProject(), param).generateMethodParameterJavaDoc();
if (javaDoc != null) {
buffer.append("&nbsp;&nbsp;<i>").append(javaDoc).append("</i>");
}
}
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) {
@@ -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);
@@ -554,11 +554,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
complete("getProperty(String key, String def)");
waitForAllAsyncStuff();
checkResultWithInlays("class C { void m() { System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>) } }");
checkHintContents("<html>@NotNull String</html>");
checkHintContents("<html><b>@NotNull String</b>&nbsp;&nbsp;<i>the name of the system property. </i></html>");
next();
waitForAllAsyncStuff();
checkResultWithInlays("class C { void m() { System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>) } }");
checkHintContents("<html>String</html>");
checkHintContents("<html><b>String</b>&nbsp;&nbsp;<i>a default value. </i></html>");
showParameterInfo();
waitForAllAsyncStuff();
checkHintContents("<html><font color=gray>@NotNull String key</font color=gray></html>\n" +
@@ -570,11 +570,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
complete("setProperty");
waitForAllAsyncStuff();
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
checkHintContents("<html>@NotNull String</html>");
checkHintContents("<html><b>@NotNull String</b>&nbsp;&nbsp;<i>the name of the system property. </i></html>");
next();
waitForAllAsyncStuff();
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <HINT text=\"value:\"/><caret>) } }");
checkHintContents("<html>String</html>");
checkHintContents("<html><b>String</b>&nbsp;&nbsp;<i>the value of the system property. </i></html>");
showParameterInfo();
waitForAllAsyncStuff();
checkHintContents("<html>@NotNull String key, <b>String value</b></html>");
@@ -584,7 +584,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
configureJava("class C { void m() { System.getPro<caret> } }");
complete("getProperty(String key, String def)");
waitForAllAsyncStuff();
checkHintContents("<html>@NotNull String</html>");
checkHintContents("<html><b>@NotNull String</b>&nbsp;&nbsp;<i>the name of the system property. </i></html>");
showParameterInfo();
waitForAllAsyncStuff();
checkHintContents("<html><b>@NotNull String key</b></html>\n" +
@@ -599,7 +599,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
configureJava("class C { void m() { System.getPro<caret> } }");
complete("getProperty(String key, String def)");
waitForAllAsyncStuff();
checkHintContents("<html>@NotNull String</html>");
checkHintContents("<html><b>@NotNull String</b>&nbsp;&nbsp;<i>the name of the system property. </i></html>");
showParameterInfo();
waitForAllAsyncStuff();
checkHintContents("<html><b>@NotNull String key</b></html>\n" +
@@ -614,7 +614,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
configureJava("class C { void m() { System.getPro<caret> } }");
complete("getProperty(String key, String def)");
waitForAllAsyncStuff();
checkHintContents("<html>@NotNull String</html>");
checkHintContents("<html><b>@NotNull String</b>&nbsp;&nbsp;<i>the name of the system property. </i></html>");
left();
left();
left();
@@ -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);
@@ -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<Flag>[] 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<String, String> escapeFunction,
int highlightStartOffset,
@@ -447,18 +463,22 @@ public class ParameterInfoComponent extends JPanel {
}
private String setup(@NotNull String text, @NotNull Map<TextRange, ParameterInfoUIContextEx.Flag> 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<TextRange, ParameterInfoUIContextEx.Flag> 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) {
@@ -45,6 +45,11 @@ public class MockParameterInfoUIContext<T extends PsiElement> implements Paramet
return _text;
}
@Override
public void setupRawUIComponentPresentation(String htmlText) {
throw new UnsupportedOperationException();
}
@Override
public boolean isUIComponentEnabled() {
return enabled;
@@ -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;