parameter info generics: check resulted html

This commit is contained in:
Anna Kozlova
2013-09-02 18:01:13 +04:00
parent bfb3a8b3a9
commit c6e41b5df6
11 changed files with 186 additions and 37 deletions

View File

@@ -33,6 +33,7 @@ import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -352,12 +353,12 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
}
}
public static void updateMethodPresentation(PsiMethod method, @Nullable PsiSubstitutor substitutor, ParameterInfoUIContext context) {
public static String updateMethodPresentation(PsiMethod method, @Nullable PsiSubstitutor substitutor, ParameterInfoUIContext context) {
CodeInsightSettings settings = CodeInsightSettings.getInstance();
if (!method.isValid() || substitutor != null && !substitutor.isValid()) {
context.setUIComponentEnabled(false);
return;
return null;
}
StringBuilder buffer = new StringBuilder();
@@ -397,7 +398,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
paramType = substitutor.substitute(paramType);
}
appendModifierList(buffer, param);
buffer.append(StringUtil.escapeXml(paramType.getPresentableText()));
buffer.append(paramType.getPresentableText());
String name = param.getName();
if (name != null) {
buffer.append(" ");
@@ -405,7 +406,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
}
}
int endOffset = buffer.length();
int endOffset = XmlStringUtil.escapeString(buffer.toString()).length();
if (j < numParams - 1) {
buffer.append(", ");
@@ -426,7 +427,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
buffer.append(")");
}
context.setupUIComponentPresentation(
return context.setupUIComponentPresentation(
buffer.toString(),
highlightStartOffset,
highlightEndOffset,

View File

@@ -0,0 +1,9 @@
import java.util.*;
class First {
private void doFirst(List<String> param) {
}
}
private void doSecond() {
doFirst(<caret>);
}
}

View File

@@ -0,0 +1,9 @@
import java.util.*;
class First {
private void doFirst(List<String> param) {
}
}
private void doSecond() {
do<caret>First();
}
}

View File

@@ -0,0 +1,6 @@
class First {
private void doSecond() {
doFirst(<caret>);
}
private void doFirst(){}
}

View File

@@ -0,0 +1,10 @@
class First {
private void doFirst(int param) {
}
}
class Second {
private void doSecond(First first) {
first.doFirst(<caret>);
}
}

View File

@@ -0,0 +1,15 @@
public abstract class Base {
public abstract void func();
public static class Impl extends Base {
@Override
public void func() {
foo(<caret>);
}
}
private static boolean foo(String param) {
return true;
}
}

View File

@@ -0,0 +1,77 @@
package com.intellij.codeInsight;
import com.intellij.codeInsight.hint.ParameterInfoComponent;
import com.intellij.codeInsight.hint.api.impls.MethodParameterInfoHandler;
import com.intellij.lang.parameterInfo.CreateParameterInfoContext;
import com.intellij.lang.parameterInfo.ParameterInfoUIContextEx;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.utils.parameterInfo.MockCreateParameterInfoContext;
import com.intellij.util.Function;
import junit.framework.Assert;
public class ParameterInfoTest extends LightCodeInsightTestCase {
private static final String BASE_PATH = "/codeInsight/parameterInfo/";
private Object[] doTest(String paramsList) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
final MethodParameterInfoHandler handler = new MethodParameterInfoHandler();
final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile);
final PsiExpressionList list = handler.findElementForParameterInfo(context);
assertNotNull(list);
assertNotNull(context.getItemsToShow());
assertTrue(context.getItemsToShow().length > 0);
Object[] params = handler.getParametersForDocumentation(context.getItemsToShow()[0], context);
assertNotNull(params);
String joined = StringUtil.join(params, new Function<Object, String>() {
@Override
public String fun(Object o) {
return ((PsiParameter)o).getName();
}
}, ",");
assertEquals(paramsList, joined);
return params;
}
public void testPrivateMethodOfEnclosingClass() throws Exception {
doTest("param");
}
public void testNotAccessible() throws Exception {
doTest("param");
}
public void testNoParams() throws Exception {
doTestPresentation("<html>&lt;no parameters&gt;</html>");
}
public void testGenericsInsideCall() throws Exception {
doTestPresentation("<html>List&lt;String&gt; param</html>");
}
public void testGenericsOutsideCall() throws Exception {
doTestPresentation("<html>List&lt;String&gt; param</html>");
}
private void doTestPresentation(String expectedString) {
configureByFile(BASE_PATH + getTestName(false) + ".java");
final MethodParameterInfoHandler handler = new MethodParameterInfoHandler();
final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile);
final PsiExpressionList list = handler.findElementForParameterInfo(context);
assertNotNull(list);
final Object[] itemsToShow = context.getItemsToShow();
assertNotNull(itemsToShow);
assertTrue(itemsToShow.length == 1);
assertTrue(itemsToShow[0] instanceof MethodCandidateInfo);
final PsiMethod method = ((MethodCandidateInfo)itemsToShow[0]).getElement();
final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler);
Assert.assertEquals(expectedString,
MethodParameterInfoHandler
.updateMethodPresentation(method, ((MethodCandidateInfo)itemsToShow[0]).getSubstitutor(), parameterContext));
}
}

View File

@@ -21,8 +21,8 @@ import com.intellij.psi.PsiElement;
import java.awt.*;
public interface ParameterInfoUIContext {
void setupUIComponentPresentation(String text, int highlightStartOffset, int highlightEndOffset, boolean isDisabled, boolean strikeout,
boolean isDisabledBeforeHighlight, Color background);
String setupUIComponentPresentation(String text, int highlightStartOffset, int highlightEndOffset, boolean isDisabled, boolean strikeout,
boolean isDisabledBeforeHighlight, Color background);
boolean isUIComponentEnabled();
void setUIComponentEnabled(boolean enabled);

View File

@@ -32,7 +32,7 @@ public interface ParameterInfoUIContextEx extends ParameterInfoUIContext {
* @param flags a set of Flags; flags[i] describes formatting of texts[i].
* @param background background color of the hint.
*/
void setupUIComponentPresentation(String[] texts, EnumSet<Flag>[] flags, Color background);
String setupUIComponentPresentation(String[] texts, EnumSet<Flag>[] flags, Color background);
enum Flag {
HIGHLIGHT, DISABLE, STRIKEOUT // more to come

View File

@@ -19,6 +19,7 @@ package com.intellij.codeInsight.hint;
import com.google.common.collect.ImmutableMap;
import com.intellij.lang.parameterInfo.ParameterInfoHandler;
import com.intellij.lang.parameterInfo.ParameterInfoUIContextEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
@@ -30,13 +31,14 @@ import com.intellij.ui.SideBorder;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.util.*;
class ParameterInfoComponent extends JPanel {
public class ParameterInfoComponent extends JPanel {
private final Object[] myObjects;
private int myCurrentParameterIndex;
@@ -53,7 +55,7 @@ class ParameterInfoComponent extends JPanel {
private static final Border BACKGROUND_BORDER = BorderFactory.createLineBorder(BACKGROUND_COLOR);
protected int myWidthLimit;
protected int myWidthLimit = 500;
private static final Map<ParameterInfoUIContextEx.Flag, String> FLAG_TO_TAG =
ImmutableMap.of(ParameterInfoUIContextEx.Flag.HIGHLIGHT, "b", ParameterInfoUIContextEx.Flag.DISABLE, "font color=gray",
@@ -71,12 +73,19 @@ class ParameterInfoComponent extends JPanel {
}
};
public ParameterInfoComponent(Object[] objects, Editor editor, @NotNull ParameterInfoHandler handler) {
@TestOnly
public static ParameterInfoUIContextEx createContext(Object[] objects, Editor editor, @NotNull ParameterInfoHandler handler) {
return new ParameterInfoComponent(objects, editor, handler).new MyParameterContext();
}
ParameterInfoComponent(Object[] objects, Editor editor, @NotNull ParameterInfoHandler handler) {
super(new BorderLayout());
JComponent editorComponent = editor.getComponent();
JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();
myWidthLimit = layeredPane.getWidth();
if (!ApplicationManager.getApplication().isUnitTestMode()) {
JComponent editorComponent = editor.getComponent();
JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();
myWidthLimit = layeredPane.getWidth();
}
NORMAL_FONT = UIUtil.getLabelFont();
BOLD_FONT = NORMAL_FONT.deriveFont(Font.BOLD);
@@ -123,21 +132,24 @@ class ParameterInfoComponent extends JPanel {
private int i;
@Override
public void setupUIComponentPresentation(String text,
int highlightStartOffset,
int highlightEndOffset,
boolean isDisabled,
boolean strikeout,
boolean isDisabledBeforeHighlight,
Color background) {
myPanels[i].setup(text, highlightStartOffset, highlightEndOffset, isDisabled, strikeout, isDisabledBeforeHighlight, background);
public String setupUIComponentPresentation(String text,
int highlightStartOffset,
int highlightEndOffset,
boolean isDisabled,
boolean strikeout,
boolean isDisabledBeforeHighlight,
Color background) {
final String resultedText =
myPanels[i].setup(text, highlightStartOffset, highlightEndOffset, isDisabled, strikeout, isDisabledBeforeHighlight, background);
myPanels[i].setBorder(isLastParameterOwner() ? BACKGROUND_BORDER : new SideBorder(new JBColor(JBColor.LIGHT_GRAY, Gray._90), SideBorder.BOTTOM));
return resultedText;
}
@Override
public void setupUIComponentPresentation(final String[] texts, final EnumSet<Flag>[] flags, final Color background) {
myPanels[i].setup(texts, flags, background);
public String setupUIComponentPresentation(final String[] texts, final EnumSet<Flag>[] flags, final Color background) {
final String resultedText = myPanels[i].setup(texts, flags, background);
myPanels[i].setBorder(isLastParameterOwner() ? BACKGROUND_BORDER : new SideBorder(new JBColor(JBColor.LIGHT_GRAY, Gray._90), SideBorder.BOTTOM));
return resultedText;
}
@Override
@@ -226,7 +238,8 @@ class ParameterInfoComponent extends JPanel {
myOneLineComponents = new OneLineComponent[0]; //TODO ???
}
private void setup(String text, int highlightStartOffset, int highlightEndOffset, boolean isDisabled, boolean strikeout, boolean isDisabledBeforeHighlight, Color background) {
private String setup(String text, int highlightStartOffset, int highlightEndOffset, boolean isDisabled, boolean strikeout, boolean isDisabledBeforeHighlight, Color background) {
StringBuilder buf = new StringBuilder();
removeAll();
String[] lines = UIUtil.splitText(text, getFontMetrics(BOLD_FONT), myWidthLimit, ',');
@@ -236,7 +249,7 @@ class ParameterInfoComponent extends JPanel {
int lineOffset = 0;
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
String line = escapeString(lines[i]);
myOneLineComponents[i] = new OneLineComponent();
@@ -247,7 +260,7 @@ class ParameterInfoComponent extends JPanel {
endOffset = Math.min(highlightEndOffset - lineOffset, line.length());
}
myOneLineComponents[i].setup(line, startOffset, endOffset, isDisabled, strikeout, background);
buf.append(myOneLineComponents[i].setup(line, startOffset, endOffset, isDisabled, strikeout, background));
if (isDisabledBeforeHighlight) {
if (highlightStartOffset < 0 || highlightEndOffset > lineOffset) {
@@ -259,9 +272,15 @@ class ParameterInfoComponent extends JPanel {
lineOffset += line.length();
}
return buf.toString();
}
public void setup(final String[] texts, final EnumSet<ParameterInfoUIContextEx.Flag>[] flags, final Color background) {
private String escapeString(String line) {
return XmlStringUtil.escapeString(line);
}
public String setup(final String[] texts, final EnumSet<ParameterInfoUIContextEx.Flag>[] flags, final Color background) {
StringBuilder buf = new StringBuilder();
removeAll();
final String[] lines = UIUtil.splitText(StringUtil.join(texts), getFontMetrics(BOLD_FONT), myWidthLimit, ',');
@@ -274,7 +293,7 @@ class ParameterInfoComponent extends JPanel {
int added = 0;
for (int i = 0; i < texts.length; i++) {
String line = texts[i];
String line = escapeString(texts[i]);
if (lines.length <= index) break;
String text = lines[index];
final int paramCount = StringUtil.split(text, ", ").size();
@@ -295,7 +314,7 @@ class ParameterInfoComponent extends JPanel {
if (i == paramCount + added - 1) {
myOneLineComponents[index] = new OneLineComponent();
setBackground(background);
myOneLineComponents[index].setup(text, flagsMap, background);
buf.append(myOneLineComponents[index].setup(text, flagsMap, background));
add(myOneLineComponents[index], new GridBagConstraints(0, index, 1, 1, 1, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
index += 1;
@@ -304,6 +323,7 @@ class ParameterInfoComponent extends JPanel {
added += paramCount;
}
}
return buf.toString();
}
}
@@ -321,7 +341,7 @@ class ParameterInfoComponent extends JPanel {
new Insets(0, 0, 0, 0), 0, 0));
}
private void setup(String text, int startOffset, int endOffset, boolean isDisabled, boolean isStrikeout, Color background) {
private String setup(String text, int startOffset, int endOffset, boolean isDisabled, boolean isStrikeout, Color background) {
Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap = new TreeMap<TextRange, ParameterInfoUIContextEx.Flag>(TEXT_RANGE_COMPARATOR);
final TextRange highlight = TextRange.create(startOffset, endOffset);
if (!highlight.isEmpty())
@@ -330,17 +350,17 @@ class ParameterInfoComponent extends JPanel {
flagsMap.put(TextRange.create(0, text.length()), ParameterInfoUIContextEx.Flag.DISABLE);
if (isStrikeout)
flagsMap.put(TextRange.create(0, text.length()), ParameterInfoUIContextEx.Flag.STRIKEOUT);
setup(text, flagsMap, background);
return setup(text, flagsMap, background);
}
private void setup(@NotNull String text, @NotNull Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap, @NotNull Color background) {
private String setup(@NotNull String text, @NotNull Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap, @NotNull Color background) {
myLabel.setBackground(background);
setBackground(background);
myLabel.setForeground(JBColor.foreground());
if (flagsMap.isEmpty()) {
myLabel.setText(XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(text)));
myLabel.setText(XmlStringUtil.wrapInHtml(text));
}
else {
String labelText = buildLabelText(text, flagsMap);
@@ -351,6 +371,7 @@ class ParameterInfoComponent extends JPanel {
if (UIUtil.isUnderDarcula()) {
myLabel.setText(myLabel.getText().replace("<b>", "<b color=ffC800>"));
}
return myLabel.getText();
}
private String buildLabelText(@NotNull final String text, @NotNull final Map<TextRange, ParameterInfoUIContextEx.Flag> flagsMap) {
final StringBuilder labelText = new StringBuilder(text);

View File

@@ -35,11 +35,12 @@ public class MockParameterInfoUIContext<T extends PsiElement> implements Paramet
}
@Override
public void setupUIComponentPresentation(final String _text, final int highlightStartOffset, final int highlightEndOffset,
final boolean isDisabled, final boolean strikeout, final boolean isDisabledBeforeHighlight,
final Color background) {
public String setupUIComponentPresentation(final String _text, final int highlightStartOffset, final int highlightEndOffset,
final boolean isDisabled, final boolean strikeout, final boolean isDisabledBeforeHighlight,
final Color background) {
text = _text;
highlightStart = highlightStartOffset;
return _text;
}
@Override