Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-09-22 16:23:00 +03:00
33 changed files with 511 additions and 372 deletions
@@ -34,13 +34,11 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiElement;
import com.intellij.util.EventDispatcher;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.InternalIterator;
import com.sun.jdi.*;
import com.sun.jdi.Value;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -90,11 +88,7 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
new MapEntryLabelRenderer()/*createLabelRenderer(null, "\" \" + getKey() + \" -> \" + getValue()", null)*/,
createEnumerationChildrenRenderer(new String[][]{{"key", "getKey()"}, {"value", "getValue()"}})
),
createCompoundReferenceRenderer(
"List", CommonClassNames.JAVA_UTIL_LIST,
createLabelRenderer(" size = ", "size()", null),
new ListChildrenRenderer()
),
new ListObjectRenderer(this),
createCompoundReferenceRenderer(
"Collection", "java.util.Collection",
createLabelRenderer(" size = ", "size()", null),
@@ -494,33 +488,25 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
}
}
private static class ListChildrenRenderer extends ExpressionChildrenRenderer {
private static final ArrayRenderer ourChildrenRenderer = new ArrayRenderer() {
@Override
public PsiExpression getChildValueExpression(DebuggerTreeNode node, DebuggerContext context) {
try {
ArrayElementDescriptorImpl descriptor = (ArrayElementDescriptorImpl)node.getDescriptor();
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(node.getProject()).getElementFactory();
return elementFactory.createExpressionFromText("get(" + descriptor.getIndex() + ")", null);
}
catch (IncorrectOperationException e) {
// fallback to original
return super.getChildValueExpression(node, context);
}
}
};
public ListChildrenRenderer() {
setChildrenExpression(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "toArray()", "", StdFileTypes.JAVA));
setChildrenExpandable(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "!isEmpty()", "", StdFileTypes.JAVA));
private static class ListObjectRenderer extends CompoundReferenceRenderer {
public ListObjectRenderer(NodeRendererSettings rendererSettings) {
super(rendererSettings,
"List",
createLabelRenderer(" size = ", "size()", null),
createExpressionChildrenRenderer("toArray()", "!isEmpty()"));
setClassName(CommonClassNames.JAVA_UTIL_LIST);
}
@Override
public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) {
if (getLastChildrenRenderer(builder.getParentDescriptor()) == null) {
setPreferableChildrenRenderer(builder.getParentDescriptor(), ourChildrenRenderer);
public PsiElement getChildValueExpression(DebuggerTreeNode node, DebuggerContext context) throws EvaluateException {
LOG.assertTrue(node.getDescriptor() instanceof ArrayElementDescriptorImpl);
try {
return getChildValueExpression("this.get(" + ((ArrayElementDescriptorImpl)node.getDescriptor()).getIndex() + ")", node, context);
}
catch (IncorrectOperationException e) {
// fallback to original
return super.getChildValueExpression(node, context);
}
super.buildChildren(value, builder, evaluationContext);
}
}
@@ -15,16 +15,24 @@
*/
package com.intellij.debugger.ui.tree.render;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.search.GlobalSearchScope;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.Type;
import org.jetbrains.annotations.NotNull;
public class CompoundReferenceRenderer extends CompoundNodeRenderer{
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer");
protected static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer");
public CompoundReferenceRenderer(final NodeRendererSettings rendererSettings, String name, ValueLabelRenderer labelRenderer, ChildrenRenderer childrenRenderer) {
super(rendererSettings, name, labelRenderer, childrenRenderer);
@@ -109,4 +117,16 @@ public class CompoundReferenceRenderer extends CompoundNodeRenderer{
public @NotNull String getClassName() {
return myProperties.getClassName();
}
protected final PsiElement getContext(Project project, DebuggerContext context) {
DebugProcess process = context.getDebugProcess();
GlobalSearchScope scope = process != null ? process.getSearchScope() : GlobalSearchScope.allScope(project);
return DebuggerUtils.findClass(getClassName(), project, scope);
}
protected final PsiElement getChildValueExpression(String text, DebuggerTreeNode node, DebuggerContext context) {
Project project = node.getProject();
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
return elementFactory.createExpressionFromText(text, getContext(project, context));
}
}
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>testSimple.iml</file>
<file>testSimple_0.iml</file>
<problem_class>Unused library</problem_class>
<description>Unused library 'JUnit'</description>
</problem>
@@ -128,7 +128,7 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable
}
@Nullable
private static Icon computeIconNow(PsiElement element, @Iconable.IconFlags int flags) {
private static Icon computeIconNow(@NotNull PsiElement element, @Iconable.IconFlags int flags) {
final Icon providersIcon = PsiIconUtil.getProvidersIcon(element, flags);
if (providersIcon != null) {
return providersIcon instanceof RowIcon ? (RowIcon)providersIcon : createLayeredIcon(element, providersIcon, flags);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -24,6 +24,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -31,7 +32,7 @@ import javax.swing.*;
public class PsiIconUtil {
@Nullable
public static Icon getProvidersIcon(PsiElement element, @Iconable.IconFlags int flags) {
public static Icon getProvidersIcon(@NotNull PsiElement element, @Iconable.IconFlags int flags) {
final boolean dumb = DumbService.getInstance(element.getProject()).isDumb();
for (final IconProvider iconProvider : getIconProviders()) {
if (dumb && !DumbService.isDumbAware(iconProvider)) {
@@ -0,0 +1,57 @@
package com.intellij.ide.ui;
import java.awt.image.ImageFilter;
final class DaltonizationFilter extends WeightFilter {
public static final ImageFilter protanopia = forProtanopia(null);
public static final ImageFilter deuteranopia = forDeuteranopia(null);
public static final ImageFilter tritanopia = forTritanopia(null);
public static ImageFilter forProtanopia(Double weight) {
return new DaltonizationFilter(weight, 0, 2.02344, -2.52581, 0, 1, 0, 0, 0, 1);
}
public static ImageFilter forDeuteranopia(Double weight) {
return new DaltonizationFilter(weight, 1, 0, 0, 0.494207, 0, 1.24827, 0, 0, 1);
}
public static ImageFilter forTritanopia(Double weight) {
return new DaltonizationFilter(weight, 1, 0, 0, 0, 1, 0, -0.395913, 0.801109, 0);
}
private final double[] myMatrix;
private DaltonizationFilter(Double weight, double... matrix) {
super(weight);
myMatrix = matrix;
}
@Override
int toRGB(int srcR, int srcG, int srcB) {
// RGB to LMS matrix conversion
double L = (17.8824 * srcR) + (43.5161 * srcG) + (4.11935 * srcB);
double M = (3.45565 * srcR) + (27.1554 * srcG) + (3.86714 * srcB);
double S = (0.0299566 * srcR) + (0.184309 * srcG) + (1.46709 * srcB);
// Simulate color blindness
double l = L * myMatrix[0] + M * myMatrix[1] + S * myMatrix[2];
double m = L * myMatrix[3] + M * myMatrix[4] + S * myMatrix[5];
double s = L * myMatrix[6] + M * myMatrix[7] + S * myMatrix[8];
// LMS to RGB matrix conversion
double R = (0.0809444479 * l) + (-0.130504409 * m) + (0.116721066 * s);
double G = (-0.0102485335 * l) + (0.0540193266 * m) + (-0.113614708 * s);
double B = (-0.000365296938 * l) + (-0.00412161469 * m) + (0.693511405 * s);
// Isolate invisible colors to color vision deficiency (calculate error matrix)
R = srcR - R;
G = srcG - G;
B = srcB - B;
// Shift colors towards visible spectrum (apply error modifications)
// and add compensation to original values
double dstR = srcR + (0.0 * R) + (0.0 * G) + (0.0 * B);
double dstG = srcG + (0.7 * R) + (1.0 * G) + (0.0 * B);
double dstB = srcB + (0.7 * R) + (0.0 * G) + (1.0 * B);
return toRGB(srcR, srcG, srcB,
dstR < 0 ? 0 : dstR > 255 ? 255 : dstR,
dstR < 0 ? 0 : dstR > 255 ? 255 : dstG,
dstR < 0 ? 0 : dstR > 255 ? 255 : dstB);
}
}
@@ -0,0 +1,101 @@
package com.intellij.ide.ui;
import java.awt.image.ImageFilter;
final class SimulationFilter extends WeightFilter {
public static final ImageFilter protanopia = forProtanopia(null);
public static final ImageFilter deuteranopia = forDeuteranopia(null);
public static final ImageFilter tritanopia = forTritanopia(null);
public static final ImageFilter achromatopsia = forAchromatopsia(null);
public static ImageFilter forProtanopia(Double weight) {
return new SimulationFilter(weight, 0.7465, 0.2535, 1.273463, -0.073894);
}
public static ImageFilter forDeuteranopia(Double weight) {
return new SimulationFilter(weight, 1.4, -0.4, 0.968437, 0.003331);
}
public static ImageFilter forTritanopia(Double weight) {
return new SimulationFilter(weight, 0.1748, 0, 0.062921, 0.292119);
}
public static ImageFilter forAchromatopsia(Double weight) {
return new WeightFilter(weight) {
@Override
int toRGB(int srcR, int srcG, int srcB) {
double gray = 0.212656 * srcR + 0.715158 * srcG + 0.072186 * srcB;
return toRGB(srcR, srcG, srcB, gray, gray, gray);
}
};
}
private final double myConfuseX;
private final double myConfuseY;
private final double myConfuseM;
private final double myConfuseYint;
private SimulationFilter(Double weight, double x, double y, double m, double yint) {
super(weight);
myConfuseX = x;
myConfuseY = y;
myConfuseM = m;
myConfuseYint = yint;
}
@Override
int toRGB(int srcR, int srcG, int srcB) {
// Convert source color into XYZ color space
double powR = Math.pow(srcR, 2.2);
double powG = Math.pow(srcG, 2.2);
double powB = Math.pow(srcB, 2.2);
// RGB->XYZ (sRGB:D65)
double X = 0.4124240 * powR + 0.357579 * powG + 0.1804640 * powB;
double Y = 0.2126560 * powR + 0.715158 * powG + 0.0721856 * powB;
double Z = 0.0193324 * powR + 0.119193 * powG + 0.9504440 * powB;
// Convert XYZ into xyY Chromacity Coordinates (xy) and Luminance (Y)
double chroma_x = X / (X + Y + Z);
double chroma_y = Y / (X + Y + Z);
// Generate the "Confusion Line" between the source color and the Confusion Point
double m = (chroma_y - myConfuseY) / (chroma_x - myConfuseX); // slope of Confusion Line
double yint = chroma_y - chroma_x * m; // y-intercept of confusion line (x-intercept = 0.0)
// How far the xy coords deviate from the simulation
double deviate_x = (myConfuseYint - yint) / (m - myConfuseM);
double deviate_y = (m * deviate_x) + yint;
// Compute the simulated color's XYZ coords
X = deviate_x * Y / deviate_y;
Z = (1.0 - (deviate_x + deviate_y)) * Y / deviate_y;
// Neutral grey calculated from luminance (in D65)
double neutral_X = Y * 0.312713 / 0.329016;
double neutral_Z = Y * 0.358271 / 0.329016;
// Difference between simulated color and neutral grey
double diffX = neutral_X - X;
double diffZ = neutral_Z - Z;
// XYZ->RGB (sRGB:D65)
double diffR = +3.2407100 * diffX - 0.4985710 * diffZ;
double diffG = -0.9692580 * diffX + 0.0415557 * diffZ;
double diffB = +0.0556352 * diffX + 1.0570700 * diffZ;
// Convert to RGB color space
// XYZ->RGB (sRGB:D65)
double dstR = +3.2407100 * X - 1.537260 * Y - 0.4985710 * Z;
double dstG = -0.9692580 * X + 1.875990 * Y + 0.0415557 * Z;
double dstB = +0.0556352 * X - 0.203996 * Y + 1.0570700 * Z;
// Compensate simulated color towards a neutral fit in RGB space
double fitR = ((dstR < 0 ? 0 : 1) - dstR) / diffR;
double fitG = ((dstG < 0 ? 0 : 1) - dstG) / diffG;
double fitB = ((dstB < 0 ? 0 : 1) - dstB) / diffB;
double adjust = Math.max(Math.max( // highest value
(fitR < 0 || 1 < fitR) ? 0 : fitR,
(fitG < 0 || 1 < fitG) ? 0 : fitG),
(fitB < 0 || 1 < fitB) ? 0 : fitB);
// Shift proportional to the greatest shift
dstR += adjust * diffR;
dstG += adjust * diffG;
dstB += adjust * diffB;
// Apply gamma correction
dstR = Math.pow(dstR, 1 / 2.2);
dstG = Math.pow(dstG, 1 / 2.2);
dstB = Math.pow(dstB, 1 / 2.2);
return toRGB(srcR, srcG, srcB, dstR, dstG, dstB);
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.openapi.util.SystemInfo;
@@ -167,6 +168,13 @@ public class UISettings extends SimpleModificationTracker implements PersistentS
incModificationCount();
myDispatcher.getMulticaster().uiSettingsChanged(this);
ApplicationManager.getApplication().getMessageBus().syncPublisher(UISettingsListener.TOPIC).uiSettingsChanged(this);
IconLoader.setFilter(COLOR_BLINDNESS == ColorBlindness.protanopia
? DaltonizationFilter.protanopia
: COLOR_BLINDNESS == ColorBlindness.deuteranopia
? DaltonizationFilter.deuteranopia
: COLOR_BLINDNESS == ColorBlindness.tritanopia
? DaltonizationFilter.tritanopia
: null);
}
public void removeUISettingsListener(UISettingsListener listener) {
@@ -0,0 +1,37 @@
package com.intellij.ide.ui;
import java.awt.image.RGBImageFilter;
abstract class WeightFilter extends RGBImageFilter {
private final Double myWeight;
WeightFilter(Double weight) {
if (weight != null && (weight < 0 || 1 < weight)) {
throw new IllegalArgumentException("weight " + weight + " out of [0..1]");
}
myWeight = weight;
canFilterIndexColorModel = true;
}
@Override
public final int filterRGB(int x, int y, int rgb) {
return (0xFF000000 & rgb) | toRGB(0xFF & (rgb >> 16), 0xFF & (rgb >> 8), 0xFF & rgb);
}
abstract int toRGB(int srcR, int srcG, int srcB);
final int toRGB(int srcR, int srcG, int srcB, double dstR, double dstG, double dstB) {
if (Double.isNaN(dstR)) dstR = 0;
if (Double.isNaN(dstG)) dstG = 0;
if (Double.isNaN(dstB)) dstB = 0;
if (myWeight != null) {
dstR = dstR * myWeight + srcR * (1 - myWeight);
dstG = dstG * myWeight + srcG * (1 - myWeight);
dstB = dstB * myWeight + srcB * (1 - myWeight);
}
srcR = (int)dstR;
srcG = (int)dstG;
srcB = (int)dstB;
return (srcR << 16) | (srcG << 8) | srcB;
}
}
@@ -605,6 +605,17 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
return OTHER_INDENT_OPTIONS;
}
/**
* If the document has an associated PsiFile, returns options for this file. Otherwise attempts to find associated VirtualFile and
* return options for corresponding FileType. If none are found, other indent options are returned.
*
* @param project The project in which PsiFile should be searched.
* @param document The document to search indent options for.
* @return Indent options from the indent options providers or file type indent options or <code>OTHER_INDENT_OPTIONS</code>.
* @see FileIndentOptionsProvider
* @see FileTypeIndentOptionsProvider
* @see LanguageCodeStyleSettingsProvider
*/
@NotNull
public IndentOptions getIndentOptionsByDocument(@Nullable Project project, @NotNull Document document) {
PsiFile file = project != null ? PsiDocumentManager.getInstance(project).getPsiFile(document) : null;
@@ -130,7 +130,7 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
};
final DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode(treeStructure.getRootElement()));
JTree tree = new JBTreeWithHintProvider(model);
JTree tree = new MyTree(model);
tree.setRootVisible(showRootNode);
tree.setShowsRootHandles(true);
@@ -168,6 +168,17 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
}
};
}
private static class MyTree extends JBTreeWithHintProvider implements PlaceProvider<String> {
public MyTree(javax.swing.tree.TreeModel treemodel) {
super(treemodel);
}
@Override
public String getPlace() {
return ActionPlaces.STRUCTURE_VIEW_TOOLBAR;
}
}
public void showToolbar() {
setToolbar(createToolbar());
@@ -1112,7 +1112,7 @@ public class FileStructurePopup implements Disposable, TreeActionsOwner {
}
}
class FileStructureTree extends JBTreeWithHintProvider implements AlwaysExpandedTree {
class FileStructureTree extends JBTreeWithHintProvider implements AlwaysExpandedTree, PlaceProvider<String> {
private final boolean fast;
public FileStructureTree(Object rootElement, boolean fastExpand) {
@@ -1157,5 +1157,10 @@ public class FileStructurePopup implements Disposable, TreeActionsOwner {
//noinspection ConstantConditions
return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject());
}
@Override
public String getPlace() {
return ActionPlaces.STRUCTURE_VIEW_POPUP;
}
}
}
@@ -162,7 +162,7 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
@NotNull private final ComboBox myComboBox;
protected SwitchBootJdkDialog(@Nullable Project project, List<JdkBundleDescriptor> jdkBundlesList) {
protected SwitchBootJdkDialog(@Nullable Project project, final List<JdkBundleDescriptor> jdkBundlesList) {
super(project, false);
final ArrayList<JdkBundleDescriptor> pathsList = JdkUtil.findJdkPaths();
@@ -175,7 +175,9 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
DefaultComboBoxModel model = new DefaultComboBoxModel();
for (JdkBundleDescriptor jdkBundlePath : pathsList) {
if (!jdkBundlesList.isEmpty() && FileUtil.filesEqual(jdkBundlePath.getBundleAsFile(),jdkBundlesList.get(0).getBundleAsFile())) {
if (!(jdkBundlesList.isEmpty() || jdkBundlePath == null)
&& FileUtil.filesEqual(jdkBundlePath.getBundleAsFile(),jdkBundlesList.get(0).getBundleAsFile()))
{
continue;
}
model.addElement(jdkBundlePath);
@@ -185,8 +187,20 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware {
myComboBox.setRenderer(new ListCellRendererWrapper() {
@Override
public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
JdkBundleDescriptor jdkBundleDescriptor = ((JdkBundleDescriptor)value);
setText(jdkBundleDescriptor.getVisualRepresentation());
if (value != null) {
JdkBundleDescriptor jdkBundleDescriptor = ((JdkBundleDescriptor)value);
setText(jdkBundleDescriptor.getVisualRepresentation());
} else {
LOG.error("Null value has been passed to a cell renderer. Available JDKs count: " + pathsList.size());
StringBuilder jdkNames = new StringBuilder();
for (JdkBundleDescriptor jdkBundlePath : pathsList) {
if (!jdkBundlesList.isEmpty()) {
continue;
}
jdkNames.append(jdkBundlePath.getVisualRepresentation()).append("; ");
}
LOG.error("Available JDKs names: " + jdkNames.toString());
}
}
});
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -18,10 +18,8 @@ package com.intellij.ui;
import com.intellij.ide.DataManager;
import com.intellij.ide.dnd.aware.DnDAwareTree;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.psi.PsiElement;
import com.intellij.ui.popup.HintUpdateSupply;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeModel;
@@ -30,7 +28,7 @@ import javax.swing.tree.TreeNode;
/**
* @author Konstantin Bulenkov
* @deprecated
* @see com.intellij.ui.popup.HintUpdateSupply
* @see HintUpdateSupply
*/
public class JBTreeWithHintProvider extends DnDAwareTree {
{
@@ -57,19 +55,4 @@ public class JBTreeWithHintProvider extends DnDAwareTree {
protected PsiElement getPsiElementForHint(final Object selectedValue) {
return CommonDataKeys.PSI_ELEMENT.getData(DataManager.getInstance().getDataContext(this));
}
@Deprecated
public void registerHint(JBPopup hint) {
ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).registerHint(hint);
}
@Deprecated
public void hideHint() {
ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).hideHint();
}
@Deprecated
public void updateHint(PsiElement element) {
ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).updateHint(element);
}
}
@@ -1433,8 +1433,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
}
}
};
ImageProducer prod = new FilteredImageSource(image.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(prod);
return ImageUtil.filter(image, filter);
}
@Override
@@ -1705,12 +1705,6 @@
<option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="Invalid string escape">
<value>
<option name="EFFECT_COLOR" value="ff0000" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="JAVA_COMMA">
<value>
<option name="FOREGROUND" value="cc7832" deuteranopia="597cc2" protanopia="597cc2"/>
@@ -1801,11 +1795,6 @@
<option name="FOREGROUND" value="ffc66d" deuteranopia="d9af6c" protanopia="d9af6c"/>
</value>
</option>
<option name="Map key">
<value>
<option name="FOREGROUND" value="d0d0ff" />
</value>
</option>
<option name="NOT_USED_ELEMENT_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="808080" />
@@ -2118,14 +2107,6 @@
<option name="FOREGROUND" value="4e807d" />
</value>
</option>
<option name="Static field">
<value>
<option name="FOREGROUND" value="d0d0ff" />
<option name="FONT_TYPE" value="3" />
<option name="EFFECT_COLOR" value="ffffff" />
<option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="Static method access">
<value>
<option name="FOREGROUND" value="9876aa" deuteranopia="828eba" protanopia="828eba"/>
@@ -2191,11 +2172,6 @@
<option name="ERROR_STRIPE_COLOR" value="266109" />
</value>
</option>
<option name="Type parameter">
<value>
<option name="FOREGROUND" value="507874" />
</value>
</option>
<option name="UNMATCHED_BRACE_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="d1243b" deuteranopia="bd693c" protanopia="bd693c"/>
@@ -2223,11 +2199,6 @@
<option name="BACKGROUND" value="303030" />
</value>
</option>
<option name="Valid string escape">
<value>
<option name="FOREGROUND" value="cc7832" deuteranopia="597cc2" protanopia="597cc2"/>
</value>
</option>
<option name="WARNING_ATTRIBUTES">
<value>
<option name="BACKGROUND" value="52503a" deuteranopia="454122" protanopia="454122"/>
@@ -2301,54 +2272,6 @@
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="YAML_COMMENT">
<value>
<option name="FOREGROUND" value="bc9458" />
<option name="FONT_TYPE" value="2" />
</value>
</option>
<option name="YAML_SCALAR_DSTRING">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="YAML_SCALAR_KEY">
<value>
<option name="FOREGROUND" value="e8bf6a" />
</value>
</option>
<option name="YAML_SCALAR_LIST">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="YAML_SCALAR_STRING">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="YAML_SCALAR_VALUE">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="YAML_SCALAR_VALUE4">
<value>
<option name="FOREGROUND" value="e8d3d3" />
</value>
</option>
<option name="YAML_SIGN">
<value>
<option name="FOREGROUND" value="a5c261" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="YAML_TEXT">
<value>
<option name="FOREGROUND" value="a5c261" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="osmorc.attributeName">
<value>
<option name="FOREGROUND" value="d0d0ff" />
@@ -0,0 +1,58 @@
package com.intellij.ide.ui;
import junit.framework.TestCase;
import java.awt.image.ImageFilter;
import java.awt.image.RGBImageFilter;
public final class ColorBlindnessTest extends TestCase {
public void testProtanopiaDaltonization() {
testZeroFilter(DaltonizationFilter.forProtanopia(0.0));
compareFilters(DaltonizationFilter.forProtanopia(1.0), DaltonizationFilter.protanopia);
}
public void testDeuteranopiaDaltonization() {
testZeroFilter(DaltonizationFilter.forDeuteranopia(0.0));
compareFilters(DaltonizationFilter.forDeuteranopia(1.0), DaltonizationFilter.deuteranopia);
}
public void testTritanopiaDaltonization() {
testZeroFilter(DaltonizationFilter.forTritanopia(0.0));
compareFilters(DaltonizationFilter.forTritanopia(1.0), DaltonizationFilter.tritanopia);
}
public void testProtanopiaSimulation() {
testZeroFilter(SimulationFilter.forProtanopia(0.0));
compareFilters(SimulationFilter.forProtanopia(1.0), SimulationFilter.protanopia);
}
public void testDeuteranopiaSimulation() {
testZeroFilter(SimulationFilter.forDeuteranopia(0.0));
compareFilters(SimulationFilter.forDeuteranopia(1.0), SimulationFilter.deuteranopia);
}
public void testTritanopiaSimulation() {
testZeroFilter(SimulationFilter.forTritanopia(0.0));
compareFilters(SimulationFilter.forTritanopia(1.0), SimulationFilter.tritanopia);
}
public void testAchromatopsiaSimulation() {
testZeroFilter(SimulationFilter.forAchromatopsia(0.0));
compareFilters(SimulationFilter.forAchromatopsia(1.0), SimulationFilter.achromatopsia);
}
private static void testZeroFilter(ImageFilter filter) {
RGBImageFilter rgb = (RGBImageFilter)filter;
for (int i = 0; i < 0x01000000; i++) {
assertEquals(i, rgb.filterRGB(0, 0, i));
}
}
private static void compareFilters(ImageFilter one, ImageFilter two) {
RGBImageFilter rgb1 = (RGBImageFilter)one;
RGBImageFilter rgb2 = (RGBImageFilter)two;
for (int i = 0; i < 0x01000000; i++) {
assertEquals(rgb1.filterRGB(0, 0, i), rgb2.filterRGB(0, 0, i));
}
}
}
@@ -54,7 +54,6 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl;
@@ -192,7 +191,6 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
@Override
protected void setUp() throws Exception {
super.setUp();
myFilesToDelete.add(new File(FileUtilRt.getTempDirectory()));
if (ourTestCase != null) {
String message = "Previous test " + ourTestCase + " hasn't called tearDown(). Probably overridden without super call.";
ourTestCase = null;
@@ -264,22 +262,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
@NotNull
public static Project createProject(@NotNull String path, String creationPlace) {
return createProject(path, creationPlace, false);
}
@NotNull
public static Project createProject(@NotNull String path, String creationPlace, boolean clearVfs) {
String fileName = PathUtilRt.getFileName(path);
if (clearVfs) {
VirtualFile projectBase = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(fileName.endsWith(
ProjectFileType.DOT_DEFAULT_EXTENSION) ? PathUtilRt.getParentPath(path) : path));
if (projectBase != null) {
// must be leftovers from the previous test run
for (VirtualFile file : ((NewVirtualFile)projectBase).iterInDbChildren()) {
delete(file);
}
}
}
try {
String projectName = FileUtilRt.getNameWithoutExtension(fileName);
@@ -324,7 +307,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
protected File getIprFile() throws IOException {
File tempFile = FileUtil.createTempFile(getName(), ProjectFileType.DOT_DEFAULT_EXTENSION);
File tempFile = FileUtil.createTempFile(getName() + "_", ProjectFileType.DOT_DEFAULT_EXTENSION);
myFilesToDelete.add(tempFile);
return tempFile;
}
@@ -139,8 +139,7 @@ public abstract class UsefulTestCase extends TestCase {
String testName = FileUtil.sanitizeFileName(getTestName(true));
if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
testName = new File(testName).getName(); // in case the test name contains file separators
File tempDirectory = FileUtil.createTempDirectory(new File(ORIGINAL_TEMP_DIR), TEMP_DIR_MARKER + testName, "");
myTempDir = tempDirectory.getPath();
myTempDir = FileUtil.toSystemDependentName(ORIGINAL_TEMP_DIR + "/" + TEMP_DIR_MARKER + testName + "_"+ RNG.nextInt(1000));
FileUtil.resetCanonicalTempPathCache(myTempDir);
}
ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest());
@@ -72,7 +72,7 @@ public class ProjectRule() : ExternalResource() {
val buffer = ByteArrayOutputStream()
java.lang.Throwable(projectPath).printStackTrace(PrintStream(buffer))
val project = PlatformTestCase.createProject(projectPath, "Light project: $buffer", false) as ProjectEx
val project = PlatformTestCase.createProject(projectPath, "Light project: $buffer") as ProjectEx
Disposer.register(ApplicationManager.getApplication(), Disposable {
try {
disposeProject()
@@ -97,9 +97,7 @@ public class FileUtilRt {
ourPathToFileMethod = pathClass.getMethod("toFile");
ourFilesWalkMethod = filesClass.getMethod("walkFileTree", pathClass, visitorClass);
ourFilesDeleteIfExistsMethod = filesClass.getMethod("deleteIfExists", pathClass);
final Class<?> fileVisitResultClass = Class.forName("java.nio.file.FileVisitResult");
final Object Result_Continue = fileVisitResultClass.getDeclaredField("CONTINUE").get(null);
final Object Result_Terminate = fileVisitResultClass.getDeclaredField("TERMINATE").get(null);
final Object Result_Continue = Class.forName("java.nio.file.FileVisitResult").getDeclaredField("CONTINUE").get(null);
ourDeletionVisitor = Proxy.newProxyInstance(FileUtilRt.class.getClassLoader(), new Class[]{visitorClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@@ -111,7 +109,13 @@ public class FileUtilRt {
final String methodName = method.getName();
if ("visitFile".equals(methodName) || "postVisitDirectory".equals(methodName)) {
if (!performDelete(args[0])) {
return Result_Terminate;
throw new IOException("Failed to delete " + args[0]) {
// optimization: the stacktrace is not needed: the exception is used to terminate tree walkup and to pass the result
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
};
}
}
}
@@ -385,14 +389,12 @@ public class FileUtilRt {
if (suffix == null) {
suffix = ".tmp";
}
// normalize and use only the file name from the prefix
prefix = new File(prefix).getName();
int exceptionsCount = 0;
int i = 0;
while (true) {
try {
final File temp = callCreate(dir, prefix, suffix, isDirectory, i);
// If there was an IOException, there's no reason to do sequential search - fallback to random
final File temp = createTemp(prefix, suffix, dir, isDirectory, exceptionsCount > 0);
return normalizeFile(temp);
}
catch (IOException e) { // Win32 createFileExclusively access denied
@@ -400,28 +402,41 @@ public class FileUtilRt {
throw e;
}
}
i++; // for some reason the file1 can't be created (previous file1 was deleted but got locked by anti-virus?). try file2.
if (i > 2) {
i = 2 + (int)(System.nanoTime() % 998); // generate random suffix if too many failures
}
}
}
@NotNull
private static File callCreate(@NotNull File directory,
@NotNull String prefix,
private static File createTemp(@NotNull String prefix,
@NotNull String suffix,
@NotNull File directory,
boolean isDirectory,
int i) throws IOException {
prefix += i == 0 ? "" : i;
if (prefix.endsWith(".") && suffix.startsWith(".")) {
prefix = prefix.substring(0, prefix.length() - 1);
boolean randomName) throws IOException {
// Fallback to the original File.createTempFile
if (randomName) {
@SuppressWarnings("SSBasedInspection")
File res = File.createTempFile(prefix, suffix, directory);
if (isDirectory) {
if (!res.delete() || !res.mkdir()) {
throw new IOException("Cannot create directory: " + res);
}
}
return res;
}
String name = prefix + suffix;
File f = new File(directory, name);
if (!name.equals(f.getName())) {
throw new IOException("Unable to create temporary file " + f + " for name " + name);
// normalize and use only the file name from the prefix
prefix = new File(prefix).getName();
File f;
int i = 0;
do {
String name = prefix + i + suffix;
f = new File(directory, name);
if (!name.equals(f.getName())) {
throw new IOException("Unable to create temporary file " + f + " for name " + name);
}
i++;
}
while (f.exists());
boolean success = isDirectory ? f.mkdir() : f.createNewFile();
if (!success) {
@@ -701,7 +716,7 @@ public class FileUtilRt {
logger().info(e);
return false;
}
return !file.exists();
return true;
}
private static boolean deleteRecursively(@NotNull File file) {
@@ -42,6 +42,8 @@ actionSystem.assertFocusAccessFromEdt=true
actionSystem.enableAbbreviations=true
actionSystem.extendedKeyCode.disabled=false
color.blindness.icon.filter=false
ide.firstStartup=true
ide.debugMode=false
ide.debugger.inline=true
@@ -16,6 +16,7 @@
package com.intellij.openapi.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.ConcurrencyUtil;
@@ -36,8 +37,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.awt.image.ImageFilter;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.net.URL;
@@ -51,6 +51,7 @@ public final class IconLoader {
public static boolean STRICT = false;
private static boolean USE_DARK_ICONS = UIUtil.isUnderDarcula();
private static float SCALE = JBUI.scale(1f);
private static ImageFilter IMAGE_FILTER;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private static final ConcurrentMap<URL, CachedImageIcon> ourIconsCache = ContainerUtil.newConcurrentMap(100, 0.9f, 2);
@@ -117,6 +118,16 @@ public final class IconLoader {
}
}
public static void setFilter(ImageFilter filter) {
if (!Registry.is("color.blindness.icon.filter")) {
filter = null;
}
if (IMAGE_FILTER != filter) {
IMAGE_FILTER = filter;
clearCache();
}
}
private static void clearCache() {
ourIconsCache.clear();
ourIcon2DisabledIcon.clear();
@@ -286,7 +297,7 @@ public final class IconLoader {
graphics.dispose();
Image img = createDisabled(image);
Image img = ImageUtil.filter(image, UIUtil.getGrayFilter());
if (UIUtil.isRetina()) img = RetinaImage.createFrom(img, 2, ImageLoader.ourComponent);
disabledIcon = new JBImageIcon(img);
@@ -295,12 +306,6 @@ public final class IconLoader {
return disabledIcon;
}
private static Image createDisabled(BufferedImage image) {
final GrayFilter filter = UIUtil.getGrayFilter();
final ImageProducer prod = new FilteredImageSource(image.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(prod);
}
public static Icon getTransparentIcon(@NotNull final Icon icon) {
return getTransparentIcon(icon, 0.5f);
}
@@ -334,22 +339,25 @@ public final class IconLoader {
private final URL myUrl;
private boolean dark;
private float scale;
private ImageFilter filter;
private HashMap<Float, Icon> scaledIcons;
public CachedImageIcon(@NotNull URL url) {
myUrl = url;
dark = USE_DARK_ICONS;
scale = SCALE;
filter = IMAGE_FILTER;
}
@NotNull
private synchronized Icon getRealIcon() {
if (isLoaderDisabled() && (myRealIcon == null || dark != USE_DARK_ICONS || scale != SCALE)) return EMPTY_ICON;
if (isLoaderDisabled() && (myRealIcon == null || dark != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER)) return EMPTY_ICON;
if (dark != USE_DARK_ICONS || scale != SCALE) {
if (dark != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER) {
myRealIcon = null;
dark = USE_DARK_ICONS;
scale = SCALE;
filter = IMAGE_FILTER;
}
Object realIcon = myRealIcon;
if (realIcon instanceof Icon) return (Icon)realIcon;
@@ -360,7 +368,7 @@ public final class IconLoader {
if (icon != null) return icon;
}
Image image = ImageLoader.loadFromUrl(myUrl);
Image image = ImageUtil.filter(ImageLoader.loadFromUrl(myUrl), filter);
icon = checkIcon(image, myUrl);
if (icon != null) {
@@ -410,7 +418,7 @@ public final class IconLoader {
return result;
}
final Image image = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), scaleFactor >= 1.5f);
final Image image = ImageUtil.filter(ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), scaleFactor >= 1.5f), filter);
if (image != null) {
int width = (int)(getIconWidth() * scaleFactor);
int height = (int)(getIconHeight() * scaleFactor);
@@ -429,6 +437,7 @@ public final class IconLoader {
private Icon myIcon;
private boolean isDarkVariant = USE_DARK_ICONS;
private float scale = SCALE;
private ImageFilter filter = IMAGE_FILTER;
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
@@ -451,9 +460,10 @@ public final class IconLoader {
}
protected final synchronized Icon getOrComputeIcon() {
if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || scale != SCALE) {
if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER) {
isDarkVariant = USE_DARK_ICONS;
scale = SCALE;
filter = IMAGE_FILTER;
myWasComputed = true;
myIcon = compute();
}
@@ -18,7 +18,7 @@ package com.intellij.util.ui;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.*;
/**
* @author Konstantin Bulenkov
@@ -36,4 +36,10 @@ public class ImageUtil {
g.dispose();
return bufferedImage;
}
public static Image filter(Image image, ImageFilter filter) {
if (image == null || filter == null) return image;
return Toolkit.getDefaultToolkit().createImage(
new FilteredImageSource(image.getSource(), filter));
}
}
@@ -31,7 +31,7 @@ public class UIVcsUtil {
@NotNull
public static String spaceAndThinSpace() {
return " " + FontUtil.canDisplay(UIUtil.getLabelFont(), '\u2009', "");
return " " + FontUtil.canDisplay(UIUtil.getLabelFont(), '\u2009', " ");
}
public static JPanel errorPanel(final String text, boolean isError) {
@@ -31,7 +31,6 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.CollectionUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import com.siyeh.ig.psiutils.WeakestTypeFinder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,8 +92,7 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
return new DeclareCollectionAsInterfaceFix((String)infos[0]);
}
private static class DeclareCollectionAsInterfaceFix
extends InspectionGadgetsFix {
private static class DeclareCollectionAsInterfaceFix extends InspectionGadgetsFix {
private final String typeString;
@@ -124,42 +122,18 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
return;
}
final StringBuilder newElementText = new StringBuilder(typeString);
final PsiJavaCodeReferenceElement referenceElement =
(PsiJavaCodeReferenceElement)parent;
final PsiReferenceParameterList parameterList =
referenceElement.getParameterList();
final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)parent;
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
if (parameterList != null) {
final PsiTypeElement[] typeParameterElements =
parameterList.getTypeParameterElements();
if (typeParameterElements.length > 0) {
newElementText.append('<');
final PsiTypeElement typeParameterElement1 =
typeParameterElements[0];
newElementText.append(typeParameterElement1.getText());
for (int i = 1; i < typeParameterElements.length; i++) {
newElementText.append(',');
final PsiTypeElement typeParameterElement =
typeParameterElements[i];
newElementText.append(typeParameterElement.getText());
}
newElementText.append('>');
}
newElementText.append(parameterList.getText());
}
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiTypeElement)) {
return;
}
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = facade.getElementFactory();
final PsiType type = factory.createTypeFromText(
newElementText.toString(), element);
final PsiTypeElement newTypeElement = factory.createTypeElement(
type);
final PsiElement insertedElement =
grandParent.replace(newTypeElement);
final JavaCodeStyleManager styleManager =
JavaCodeStyleManager.getInstance(project);
styleManager.shortenClassReferences(insertedElement);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiTypeElement newTypeElement = factory.createTypeElementFromText(newElementText.toString(), element);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(grandParent.replace(newTypeElement));
}
}
@@ -168,8 +142,7 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
return new DeclareCollectionAsInterfaceVisitor();
}
private class DeclareCollectionAsInterfaceVisitor
extends BaseInspectionVisitor {
private class DeclareCollectionAsInterfaceVisitor extends BaseInspectionVisitor {
@Override
public void visitVariable(@NotNull PsiVariable variable) {
@@ -205,40 +178,8 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
if (!CollectionUtils.isConcreteCollectionClass(type) || LibraryUtil.isOverrideOfLibraryMethodParameter(variable)) {
return;
}
final PsiTypeElement typeElement = variable.getTypeElement();
if (typeElement == null) {
return;
}
final PsiJavaCodeReferenceElement reference =
typeElement.getInnermostComponentReferenceElement();
if (reference == null) {
return;
}
final PsiElement nameElement = reference.getReferenceNameElement();
if (nameElement == null) {
return;
}
final Collection<PsiClass> weaklings =
WeakestTypeFinder.calculateWeakestClassesNecessary(variable,
false, true);
if (weaklings.isEmpty()) {
return;
}
final List<PsiClass> weaklingList = new ArrayList(weaklings);
final PsiClassType javaLangObject = TypeUtils.getObjectType(variable);
final PsiClass objectClass = javaLangObject.resolve();
weaklingList.remove(objectClass);
if (weaklingList.isEmpty()) {
final String typeText = type.getCanonicalText();
final String interfaceText =
CollectionUtils.getInterfaceForClass(typeText);
registerError(nameElement, interfaceText);
}
else {
final PsiClass weakling = weaklingList.get(0);
final String qualifiedName = weakling.getQualifiedName();
registerError(nameElement, qualifiedName);
}
registerWeakenError(type, variable.getTypeElement(), variable);
}
@Override
@@ -252,34 +193,31 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
return;
}
final PsiType type = method.getReturnType();
if (!CollectionUtils.isConcreteCollectionClass(type)) {
if (!CollectionUtils.isConcreteCollectionClass(type) || LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
final PsiTypeElement typeElement = method.getReturnTypeElement();
registerWeakenError(type, method.getReturnTypeElement(), method);
}
private void registerWeakenError(PsiType type, PsiTypeElement typeElement, PsiElement variable) {
if (typeElement == null) {
return;
}
final PsiJavaCodeReferenceElement referenceElement =
typeElement.getInnermostComponentReferenceElement();
if (referenceElement == null) {
final PsiJavaCodeReferenceElement reference = typeElement.getInnermostComponentReferenceElement();
if (reference == null) {
return;
}
final PsiElement nameElement =
referenceElement.getReferenceNameElement();
final PsiElement nameElement = reference.getReferenceNameElement();
if (nameElement == null) {
return;
}
final Collection<PsiClass> weaklings =
WeakestTypeFinder.calculateWeakestClassesNecessary(method,
false, true);
final Collection<PsiClass> weaklings = WeakestTypeFinder.calculateWeakestClassesNecessary(variable, false, true);
if (weaklings.isEmpty()) {
return;
}
final List<PsiClass> weaklingList = new ArrayList(weaklings);
final PsiClassType javaLangObject = TypeUtils.getObjectType(method);
final PsiClassType javaLangObject = PsiType.getJavaLangObject(nameElement.getManager(), nameElement.getResolveScope());
final List<PsiClass> weaklingList = new ArrayList<PsiClass>(weaklings);
final PsiClass objectClass = javaLangObject.resolve();
weaklingList.remove(objectClass);
if (weaklingList.isEmpty()) {
@@ -292,7 +230,8 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
}
else {
final PsiClass weakling = weaklingList.get(0);
registerError(nameElement, weakling.getQualifiedName());
final String qualifiedName = weakling.getQualifiedName();
registerError(nameElement, qualifiedName);
}
}
@@ -126,7 +126,8 @@ public class WeakestTypeFinder {
}
else if (referenceGrandParent instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)referenceGrandParent;
if (!findWeakestType(methodCallExpression, weakestTypeClasses)) {
if (PsiUtil.skipParenthesizedExprUp(methodCallExpression.getParent()) instanceof PsiTypeCastExpression ||
!findWeakestType(methodCallExpression, weakestTypeClasses)) {
return Collections.emptyList();
}
}
@@ -408,7 +409,7 @@ public class WeakestTypeFinder {
}
private static List<PsiMethod> findAllSuperMethods(PsiMethod method) {
final List<PsiMethod> result = new ArrayList();
final List<PsiMethod> result = new ArrayList<PsiMethod>();
SuperMethodsSearch.search(method, null, true, false).forEach(new Processor<MethodSignatureBackedByPsiMethod>() {
@Override
@@ -32,15 +32,13 @@ public class ClassEscapesItsScopeInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"class.escapes.defined.scope.display.name");
return InspectionGadgetsBundle.message("class.escapes.defined.scope.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"class.escapes.defined.scope.problem.descriptor");
return InspectionGadgetsBundle.message("class.escapes.defined.scope.problem.descriptor");
}
@Override
@@ -48,8 +46,7 @@ public class ClassEscapesItsScopeInspection extends BaseInspection {
return new ClassEscapesItsScopeVisitor();
}
private static class ClassEscapesItsScopeVisitor
extends BaseInspectionVisitor {
private static class ClassEscapesItsScopeVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
@@ -60,31 +57,7 @@ public class ClassEscapesItsScopeInspection extends BaseInspection {
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
return;
}
final PsiType returnType = method.getReturnType();
if (returnType == null) {
return;
}
final PsiType componentType = returnType.getDeepComponentType();
if (!(componentType instanceof PsiClassType)) {
return;
}
final PsiClass returnClass = ((PsiClassType)componentType).resolve();
if (returnClass == null || returnClass instanceof PsiTypeParameter) {
return;
}
if (!isLessRestrictiveScope(method, returnClass)) {
return;
}
final PsiTypeElement typeElement = method.getReturnTypeElement();
if (typeElement == null) {
return;
}
final PsiJavaCodeReferenceElement baseTypeElement =
typeElement.getInnermostComponentReferenceElement();
if (baseTypeElement == null) {
return;
}
registerError(baseTypeElement);
registerError(method, method.getReturnType(), method.getReturnTypeElement());
}
@Override
@@ -100,7 +73,13 @@ public class ClassEscapesItsScopeInspection extends BaseInspection {
if (containingClass.hasModifierProperty(PsiModifier.PRIVATE)) {
return;
}
final PsiType type = field.getType();
registerError(field, field.getType(), field.getTypeElement());
}
private void registerError(PsiMember member, PsiType type, PsiTypeElement typeElement) {
if (type == null || typeElement == null) {
return;
}
final PsiType componentType = type.getDeepComponentType();
if (!(componentType instanceof PsiClassType)) {
return;
@@ -109,52 +88,31 @@ public class ClassEscapesItsScopeInspection extends BaseInspection {
if (fieldClass == null || fieldClass instanceof PsiTypeParameter) {
return;
}
if (!fieldHasLessRestrictiveScope(field, fieldClass)) {
if (!isLessRestrictiveScope(member, fieldClass)) {
return;
}
final PsiTypeElement typeElement = field.getTypeElement();
if (typeElement == null) {
return;
}
final PsiJavaCodeReferenceElement baseTypeElement =
typeElement.getInnermostComponentReferenceElement();
final PsiJavaCodeReferenceElement baseTypeElement = typeElement.getInnermostComponentReferenceElement();
if (baseTypeElement == null) {
return;
}
registerError(baseTypeElement);
}
private static boolean isLessRestrictiveScope(PsiMethod method,
PsiClass aClass) {
private static boolean isLessRestrictiveScope(PsiMember method, PsiClass aClass) {
final int methodScopeOrder = getScopeOrder(method);
final int classScopeOrder = getScopeOrder(aClass);
final PsiClass containingClass = method.getContainingClass();
final int containingClassScopeOrder =
getScopeOrder(containingClass);
if (methodScopeOrder <= classScopeOrder ||
containingClassScopeOrder <= classScopeOrder) {
if (containingClass != null && containingClass.getQualifiedName() == null) {
return false;
}
final PsiMethod[] superMethods = method.findSuperMethods();
for (PsiMethod superMethod : superMethods) {
if (!isLessRestrictiveScope(superMethod, aClass)) {
return false;
}
final int containingClassScopeOrder = getScopeOrder(containingClass);
if (methodScopeOrder <= classScopeOrder || containingClassScopeOrder <= classScopeOrder) {
return false;
}
return true;
}
private static boolean fieldHasLessRestrictiveScope(PsiField field,
PsiClass aClass) {
final int fieldScopeOrder = getScopeOrder(field);
final PsiClass containingClass = field.getContainingClass();
final int containingClassScopeOrder = getScopeOrder(containingClass);
final int classScopeOrder = getScopeOrder(aClass);
return fieldScopeOrder > classScopeOrder &&
containingClassScopeOrder > classScopeOrder;
}
private static int getScopeOrder(PsiModifierListOwner element) {
if (element.hasModifierProperty(PsiModifier.PUBLIC)) {
return 4;
@@ -70,4 +70,13 @@ public class DeclareCollectionAsInterface
<error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">String s = stringToProperties2("");</error>
<error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">s = stringToProperties3("")</error>;
}
private Properties properties;
public void setProperties(Properties properties) {
if (properties == null) {
this.properties = new Properties();
} else {
this.properties = (Properties) properties.clone();
}
}
}
@@ -6,4 +6,27 @@ public class ClassEscapesItsScope<T> {
return new A();
}
private class A {}
}
class BarInside {
private static class Bar {}
void foo() {
class LocalClass implements F<String, Bar> {
public Bar bar;
public Bar apply(String s) {
throw new UnsupportedOperationException();
}
}
}
class InnerClass implements F<String, Bar> {
public <warning descr="Class 'Bar' is made visible outside its defined scope">Bar</warning> bar;
public <warning descr="Class 'Bar' is made visible outside its defined scope">Bar</warning> apply(String s) {
throw new UnsupportedOperationException();
}
}
interface F<T, R> {
R apply(T t);
}
}
@@ -1,7 +1,9 @@
package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.testFramework.LightProjectDescriptor;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.NotNull;
public class DeclareCollectionAsInterfaceInspectionTest extends LightInspectionTestCase {
@@ -1,30 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<list>
<option name="GROOVY_KEYWORD">
<value>
<option name="FOREGROUND" value="cc7832"/>
</value>
</option>
<option name="GString">
<value>
<option name="FOREGROUND" value="6a8759"/>
</value>
</option>
<option name="Groovy method declaration">
<value/>
</option>
<option name="Groovydoc comment">
<value>
<option name="FOREGROUND" value="629755"/>
<option name="FONT_TYPE" value="2"/>
</value>
</option>
<option name="Groovydoc tag">
<value>
<option name="FOREGROUND" value="7cb36f"/>
<option name="EFFECT_TYPE" value="1"/>
</value>
</option>
<option name="Unresolved reference access">
<value>
<option name="FOREGROUND" value="808080"/>
+1 -1
View File
@@ -126,7 +126,7 @@
<action id="MarkSourceRoot" class="com.intellij.ide.projectView.actions.MarkJavaSourceRootAction">
<add-to-group group-id="MarkRootGroup"/>
</action>
<action id="MarkExcludeRoot" class="com.intellij.ide.projectView.actions.MarkExcludeRootAction">
<action id="MarkExcludeRoot" class="com.intellij.ide.projectView.actions.MarkExcludeRootAction" icon="AllIcons.Modules.ExcludeRoot">
<add-to-group group-id="MarkRootGroup"/>
</action>
<action id="UnmarkRoot" class="com.intellij.ide.projectView.actions.UnmarkRootAction">