mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-189985 - UseGrayInspection - rewrite to UAST
GitOrigin-RevId: c0b766b88a34cfccf4a349ffb0ae8cdd0d986ae8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
900f0bea95
commit
eee32437ec
@@ -104,7 +104,7 @@
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection"
|
||||
key="inspection.inspection.description.not.found.inspection.display.name"/>
|
||||
<localInspection language="JAVA" shortName="InspectionUsingGrayColors"
|
||||
<localInspection language="UAST" shortName="InspectionUsingGrayColors"
|
||||
groupPathKey="inspections.group.path" groupKey="inspections.group.code"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.UseGrayInspection"
|
||||
|
||||
@@ -3,78 +3,85 @@ package org.jetbrains.idea.devkit.inspections;
|
||||
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
|
||||
import com.intellij.uast.UastHintedVisitorAdapter;
|
||||
import com.intellij.ui.Gray;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.devkit.DevKitBundle;
|
||||
import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToGrayQuickFix;
|
||||
import org.jetbrains.uast.UCallExpression;
|
||||
import org.jetbrains.uast.UElement;
|
||||
import org.jetbrains.uast.UExpression;
|
||||
import org.jetbrains.uast.UastCallKind;
|
||||
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class UseGrayInspection extends DevKitInspectionBase {
|
||||
public class UseGrayInspection extends DevKitUastInspectionBase {
|
||||
|
||||
private static final String AWT_COLOR_CLASS_NAME = Color.class.getName();
|
||||
private static final String GRAY_CLASS_NAME = Gray.class.getName();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final Class<? extends UElement>[] HINTS = new Class[]{UCallExpression.class};
|
||||
|
||||
@Override
|
||||
protected PsiElementVisitor buildInternalVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@NotNull
|
||||
public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return UastHintedVisitorAdapter.create(holder.getFile().getLanguage(), new AbstractUastNonRecursiveVisitor() {
|
||||
@Override
|
||||
public void visitNewExpression(@NotNull PsiNewExpression expression) {
|
||||
if (isAwtRgbColorConstructor(expression)) {
|
||||
Integer grayValue = getGrayValue(getConstructorParams(expression));
|
||||
if (grayValue != null && grayClassAccessible(expression)) {
|
||||
holder.registerProblem(expression,
|
||||
DevKitBundle.message("inspections.use.gray.awt.color.used.name"),
|
||||
new ConvertToGrayQuickFix(grayValue));
|
||||
public boolean visitCallExpression(@NotNull UCallExpression expression) {
|
||||
if (expression.getKind() == UastCallKind.CONSTRUCTOR_CALL) {
|
||||
if (isAwtRgbColorConstructor(expression)) {
|
||||
Integer grayValue = getGrayValue(expression);
|
||||
if (grayValue != null) {
|
||||
PsiElement sourcePsi = expression.getSourcePsi();
|
||||
if (sourcePsi != null && grayClassAccessible(sourcePsi)) {
|
||||
holder.registerProblem(sourcePsi,
|
||||
DevKitBundle.message("inspections.use.gray.awt.color.used.name"),
|
||||
new ConvertToGrayQuickFix(grayValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visitCallExpression(expression);
|
||||
}
|
||||
};
|
||||
}, HINTS);
|
||||
}
|
||||
|
||||
private static boolean isAwtRgbColorConstructor(PsiNewExpression expression) {
|
||||
PsiExpression[] constructorParams = getConstructorParams(expression);
|
||||
if (constructorParams == null) return false;
|
||||
PsiType type = expression.getType();
|
||||
if (type == null) return false;
|
||||
return constructorParams.length == 3 && AWT_COLOR_CLASS_NAME.equals(type.getCanonicalText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiExpression @Nullable [] getConstructorParams(@NotNull PsiNewExpression expression) {
|
||||
PsiExpressionList arguments = expression.getArgumentList();
|
||||
if (arguments == null) return null;
|
||||
return arguments.getExpressions();
|
||||
private static boolean isAwtRgbColorConstructor(@NotNull UCallExpression constructorCall) {
|
||||
List<UExpression> constructorParams = constructorCall.getValueArguments();
|
||||
if (constructorParams.size() != 3) return false;
|
||||
PsiMethod constructor = constructorCall.resolve();
|
||||
if (constructor != null) {
|
||||
PsiClass constructorClass = constructor.getContainingClass();
|
||||
if (constructorClass != null) {
|
||||
return AWT_COLOR_CLASS_NAME.equals(constructorClass.getQualifiedName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer getGrayValue(@NotNull PsiExpression @Nullable [] constructorParams) {
|
||||
if (constructorParams == null) return null;
|
||||
PsiExpression redParam = constructorParams[0];
|
||||
private static Integer getGrayValue(@NotNull UCallExpression constructorCall) {
|
||||
List<UExpression> constructorParams = constructorCall.getValueArguments();
|
||||
UExpression redParam = constructorParams.get(0);
|
||||
Integer red = evaluateColorValue(redParam);
|
||||
if (red == null) return null;
|
||||
PsiExpression greenParam = constructorParams[1];
|
||||
PsiExpression blueParam = constructorParams[2];
|
||||
UExpression greenParam = constructorParams.get(1);
|
||||
UExpression blueParam = constructorParams.get(2);
|
||||
return 0 <= red && red < 256 && red.equals(evaluateColorValue(greenParam)) && red.equals(evaluateColorValue(blueParam)) ? red : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer evaluateColorValue(@NotNull PsiExpression expression) {
|
||||
if (expression instanceof PsiLiteralExpression) {
|
||||
Object evaluatedColorValue = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false);
|
||||
if (evaluatedColorValue != null) {
|
||||
try {
|
||||
return Integer.parseInt(evaluatedColorValue.toString());
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
private static Integer evaluateColorValue(@NotNull UExpression expression) {
|
||||
Object evaluatedExpression = expression.evaluate();
|
||||
if (evaluatedExpression instanceof Integer value) {
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+4
-1
@@ -7,10 +7,13 @@ class UseGrayConstantWhenAwtColorUsed {
|
||||
private static final Color GRAY_CONSTANT = <warning descr="'java.awt.Color' used for gray">new Color(125, 125, 125)</warning>;
|
||||
private static final Color NOT_GRAY_CONSTANT = new Color(12, 13, 14);
|
||||
|
||||
private static final int GRAY_VALUE = 125;
|
||||
|
||||
void any() {
|
||||
Color myGray1 = <warning descr="'java.awt.Color' used for gray">new Color(25, 25, 25)</warning>;
|
||||
Color myGray2 = <warning descr="'java.awt.Color' used for gray">new Color(GRAY_VALUE, 125, GRAY_VALUE)</warning>;
|
||||
takeColor(<warning descr="'java.awt.Color' used for gray">new Color(125, 125, 125)</warning>);
|
||||
Color myGray2 = new JBColor(<warning descr="'java.awt.Color' used for gray">new Color(25, 25, 25)</warning>, <warning descr="'java.awt.Color' used for gray">new Color(125, 125, 125)</warning>);
|
||||
Color myGray3 = new JBColor(<warning descr="'java.awt.Color' used for gray">new Color(25, 25, 25)</warning>, <warning descr="'java.awt.Color' used for gray">new Color(125, 125, 125)</warning>);
|
||||
takeColor(new JBColor(<warning descr="'java.awt.Color' used for gray">new Color(25, 25, 25)</warning>, <warning descr="'java.awt.Color' used for gray">new Color(125, 125, 125)</warning>));
|
||||
|
||||
// correct cases:
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.awt.Color;
|
||||
|
||||
class UseGrayConstantFixWhenNumberConstantsReferenced {
|
||||
|
||||
private static final int GRAY_VALUE = 125;
|
||||
|
||||
void any() {
|
||||
Color gray = <warning descr="'java.awt.Color' used for gray">new Col<caret>or(GRAY_VALUE, 125, GRAY_VALUE)</warning>;
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import com.intellij.ui.Gray;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
class UseGrayConstantFixWhenNumberConstantsReferenced {
|
||||
|
||||
private static final int GRAY_VALUE = 125;
|
||||
|
||||
void any() {
|
||||
Color gray = Gray._125;
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -33,4 +33,8 @@ public class ConvertToGrayQuickFixTest extends ConvertToGrayQuickFixTestBase {
|
||||
public void testUseGrayConstantFixInJBColorParam() {
|
||||
doTest(CONVERT_TO_GRAY_FIX_NAME_PATTERN.formatted(25));
|
||||
}
|
||||
|
||||
public void testUseGrayConstantFixWhenNumberConstantsReferenced() {
|
||||
doTest(CONVERT_TO_GRAY_FIX_NAME_PATTERN.formatted(125));
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import com.intellij.ui.JBColor
|
||||
import java.awt.Color
|
||||
|
||||
class UseGrayConstantWhenAwtColorUsed {
|
||||
|
||||
companion object {
|
||||
private val GRAY_CONSTANT = <warning descr="'java.awt.Color' used for gray">Color(125, 125, 125)</warning>
|
||||
private val NOT_GRAY_CONSTANT = Color(12, 13, 14)
|
||||
private const val GRAY_VALUE = 125
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
fun any() {
|
||||
val myGray1 = <warning descr="'java.awt.Color' used for gray">Color(25, 25, 25)</warning>
|
||||
val myGray2 = <warning descr="'java.awt.Color' used for gray">Color(GRAY_VALUE, 125, GRAY_VALUE)</warning>
|
||||
takeColor(<warning descr="'java.awt.Color' used for gray">Color(125, 125, 125)</warning>)
|
||||
val myGray3: Color = JBColor(<warning descr="'java.awt.Color' used for gray">Color(25, 25, 25)</warning>, <warning descr="'java.awt.Color' used for gray">Color(125, 125, 125)</warning>)
|
||||
takeColor(JBColor(<warning descr="'java.awt.Color' used for gray">Color(25, 25, 25)</warning>, <warning descr="'java.awt.Color' used for gray">Color(125, 125, 125)</warning>))
|
||||
|
||||
// correct cases:
|
||||
val notGray1 = Color(15, 15, 1)
|
||||
val notGray2 = Color(15, 1, 15)
|
||||
val notGray3 = Color(1, 15, 15)
|
||||
val grayWithAlpha1 = Color(15, 16, 17, 100)
|
||||
val unsupportedGray = Color(0x000000)
|
||||
val invalidGrayValue1 = Color(-15, -15, -15)
|
||||
val invalidGrayValue2 = Color(2500, 2500, 2500)
|
||||
val constantGray1 = Color.LIGHT_GRAY
|
||||
val constantGray2 = Color.GRAY
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun takeColor(color: Color?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.kotlin.inspections;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.devkit.inspections.UseGrayInspectionTestBase;
|
||||
import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil;
|
||||
|
||||
@TestDataPath("$CONTENT_ROOT/testData/inspections/useGray")
|
||||
public class KtUseGrayInspectionTest extends UseGrayInspectionTestBase {
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/useGray";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull String getFileExtension() {
|
||||
return "kt";
|
||||
}
|
||||
|
||||
public void testUseGrayConstantWhenAwtColorUsed() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user