Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-06-09 15:36:58 +03:00
22 changed files with 156 additions and 276 deletions
@@ -41,6 +41,10 @@ public class GutterIconTooltipHelper {
}
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, String start, final String pattern) {
return composeText(elements, start, pattern, "");
}
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, String start, final String pattern, String postfix) {
@NonNls StringBuilder result = new StringBuilder();
result.append("<html><body>");
result.append(start);
@@ -69,7 +73,7 @@ public class GutterIconTooltipHelper {
sep = "<br>";
result.append(name);
}
result.append(postfix);
result.append("</body></html>");
return result.toString();
}
@@ -24,7 +24,11 @@ import com.intellij.codeInsight.daemon.DaemonBundle;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask;
import com.intellij.ide.util.*;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
@@ -37,7 +41,10 @@ import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -109,7 +116,16 @@ public class MarkerType {
else{
key = sameSignature ? "method.overrides" : "method.overrides.in";
}
return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key));
return composeText(superMethods, "", DaemonBundle.message(key), "GotoSuperMethod");
}
private static String composeText(PsiElement[] methods, String start, String pattern, String actionId) {
Shortcut[] shortcuts = ActionManager.getInstance().getAction(actionId).getShortcutSet().getShortcuts();
Shortcut shortcut = ArrayUtil.getFirstElement(shortcuts);
String postfix = "<br><div style='margin-top: 5px'><font size='2'>Click";
if (shortcut != null) postfix += " or press " + KeymapUtil.getShortcutText(shortcut);
postfix += " to navigate</font></div>";
return GutterIconTooltipHelper.composeText(Arrays.asList(methods), start, pattern, postfix);
}
public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method, boolean acceptSelf) {
@@ -182,7 +198,7 @@ public class MarkerType {
String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header");
@NonNls String pattern = "&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"#javaClass/{1}\">{1}</a>";
return GutterIconTooltipHelper.composeText(overridings, start, pattern);
return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION);
}
public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) {
@@ -274,7 +290,7 @@ public class MarkerType {
? DaemonBundle.message("interface.is.implemented.by.header")
: DaemonBundle.message("class.is.subclassed.by.header");
@NonNls String pattern = "&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"#javaClass/{0}\">{0}</a>";
return GutterIconTooltipHelper.composeText(subclasses, start, pattern);
return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION);
}
public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) {
@@ -1,210 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: spleaner
* Date: Aug 22, 2007
* Time: 3:44:10 PM
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PsiExpressionPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.patterns.PsiMethodPattern;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.ColorChooser;
import com.intellij.ui.JBColor;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
/**
* @author spleaner
* @author Konstantin Bulenkov
*/
public class ColorChooserIntentionAction extends BaseColorIntentionAction {
private static final PsiMethodPattern DECODE_METHOD = PsiJavaPatterns.psiMethod()
.definedInClass(JAVA_AWT_COLOR)
.withName("decode");
private static final PsiExpressionPattern.Capture<PsiExpression> DECODE_METHOD_CALL_PARAMETER =
PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD);
private static final PsiMethodPattern GET_COLOR_METHOD = PsiJavaPatterns.psiMethod()
.definedInClass(JAVA_AWT_COLOR)
.withName("getColor");
private static final PsiExpressionPattern.Capture<PsiExpression> GET_METHOD_CALL_PARAMETER =
PsiJavaPatterns.psiExpression().methodCallParameter(0, GET_COLOR_METHOD);
public ColorChooserIntentionAction() {
setText(CodeInsightBundle.message("intention.color.chooser.dialog"));
}
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
return super.isAvailable(project, editor, element) || isInsideDecodeOrGetColorMethod(element);
}
public static boolean isInsideDecodeOrGetColorMethod(PsiElement element) {
if (element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == JavaTokenType.STRING_LITERAL) {
element = element.getParent();
}
return DECODE_METHOD_CALL_PARAMETER.accepts(element) ||
GET_METHOD_CALL_PARAMETER.accepts(element);
}
@Override
@NotNull
public String getFamilyName() {
return getText();
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final JComponent editorComponent = editor.getComponent();
if (isInsideDecodeOrGetColorMethod(element)) {
invokeForMethodParam(editorComponent, element);
}
else {
invokeForConstructor(editorComponent, element);
}
}
private void invokeForMethodParam(JComponent editorComponent, PsiElement element) {
final PsiLiteralExpression literal = PsiTreeUtil.getParentOfType(element, PsiLiteralExpression.class);
if (literal == null) return;
final String text = StringUtil.unquoteString(literal.getText());
final int radix = text.startsWith("0x") || text.startsWith("0X") || text.startsWith("#") ? 16 : text.startsWith("0") ? 8 : 10;
final String hexPrefix = radix == 16 ? text.startsWith("#") ? "#" : text.substring(0, 2) : null;
Color oldColor;
try {
oldColor = Color.decode(text);
}
catch (NumberFormatException e) {
oldColor = JBColor.GRAY;
}
Color color = ColorChooser.chooseColor(editorComponent, getText(), oldColor, true);
if (color == null) return;
final int rgb = color.getRGB() - ((255 & 0xFF) << 24);
if (color != null && rgb != oldColor.getRGB()) {
final String newText = radix == 16 ? hexPrefix + String.format("%6s", Integer.toHexString(rgb)).replace(' ', '0')
: radix == 8 ? "0" + Integer.toOctalString(rgb)
: Integer.toString(rgb);
final PsiManager manager = literal.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiExpression newLiteral = factory.createExpressionFromText("\"" + newText + "\"", literal);
literal.replace(newLiteral);
}
}
private void invokeForConstructor(JComponent editorComponent, PsiElement element) {
final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class);
if (expression == null) return;
Color c = null;
final PsiExpressionList argumentList = expression.getArgumentList();
if (argumentList != null) {
final PsiExpression[] expressions = argumentList.getExpressions();
int[] values = new int[expressions.length];
float[] values2 = new float[expressions.length];
int i = 0;
int j = 0;
for (final PsiExpression each : expressions) {
if (each instanceof PsiLiteralExpression) {
final Object o = ((PsiLiteralExpression)each).getValue();
if (o instanceof Integer) {
values[i] = ((Integer)o).intValue();
i++;
}
else if (o instanceof Float) {
values2[j] = ((Float)o).floatValue();
j++;
}
}
}
try {
if (i == expressions.length) {
switch (values.length) {
case 1:
c = new Color(values[0]);
break;
case 3:
c = new Color(values[0], values[1], values[2]);
break;
case 4:
c = new Color(values[0], values[1], values[2], values[3]);
break;
default:
break;
}
}
else if (j == expressions.length) {
switch (values2.length) {
case 3:
c = new Color(values2[0], values2[1], values2[2]);
break;
case 4:
c = new Color(values2[0], values2[1], values2[2], values2[3]);
break;
default:
break;
}
}
}
catch (Exception e) {
c = JBColor.GRAY;
}
}
c = (c == null) ? JBColor.GRAY : c;
replaceColor(editorComponent, expression, c);
}
private void replaceColor(JComponent editorComponent, PsiNewExpression expression, Color oldColor) {
final Color color = ColorChooser.chooseColor(editorComponent, getText(), oldColor, true);
if (color != null) {
final PsiManager manager = expression.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiExpression newCall = factory.createExpressionFromText(
"new " + getFqn(expression.getClassOrAnonymousClassReference()) + "("
+ color.getRed() + ", "
+ color.getGreen() + ", "
+ color.getBlue()
+ (color.getAlpha() < 255 ? ", " + color.getAlpha() : "")
+ ")", expression);
final PsiElement insertedElement = expression.replace(newCall);
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
codeStyleManager.reformat(insertedElement);
}
}
}
@@ -15,9 +15,11 @@
*/
package com.intellij.codeInsight.preview;
import com.intellij.codeInsight.intention.impl.ColorChooserIntentionAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.PsiExpressionPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.patterns.PsiMethodPattern;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
@@ -31,6 +33,27 @@ import java.awt.*;
* @author yole
*/
public class JavaPreviewHintProvider implements PreviewHintProvider {
private static final PsiMethodPattern DECODE_METHOD = PsiJavaPatterns.psiMethod()
.definedInClass(Color.class.getName())
.withName("decode");
private static final PsiExpressionPattern.Capture<PsiExpression> DECODE_METHOD_CALL_PARAMETER =
PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD);
private static final PsiMethodPattern GET_COLOR_METHOD = PsiJavaPatterns.psiMethod()
.definedInClass(Color.class.getName())
.withName("getColor");
private static final PsiExpressionPattern.Capture<PsiExpression> GET_METHOD_CALL_PARAMETER =
PsiJavaPatterns.psiExpression().methodCallParameter(0, GET_COLOR_METHOD);
private static boolean isInsideDecodeOrGetColorMethod(PsiElement element) {
if (element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == JavaTokenType.STRING_LITERAL) {
element = element.getParent();
}
return DECODE_METHOD_CALL_PARAMETER.accepts(element) ||
GET_METHOD_CALL_PARAMETER.accepts(element);
}
@Override
public boolean isSupportedFile(PsiFile file) {
return file instanceof PsiJavaFile;
@@ -120,7 +143,7 @@ public class JavaPreviewHintProvider implements PreviewHintProvider {
}
}
if (ColorChooserIntentionAction.isInsideDecodeOrGetColorMethod(element)) {
if (isInsideDecodeOrGetColorMethod(element)) {
final String color = StringUtil.unquoteString(element.getText());
try {
return new ColorPreviewComponent(Color.decode(color));
@@ -36,7 +36,9 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
List<LineMarkerInfo> markers = DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject());
for (LineMarkerInfo info : markers) {
if (info.endOffset >= offset && info.startOffset <= offset) {
assertEquals("<html><body>Overrides method in <a href=\"#javaClass/I\">I</a></body></html>", info.getLineMarkerTooltip());
assertEquals(
"<html><body>Overrides method in <a href=\"#javaClass/I\">I</a><br><div style='margin-top: 5px'><font size='2'>Click or press Ctrl+U to navigate</font></div></body></html>",
info.getLineMarkerTooltip());
return;
}
}