mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-69167 Groovy 1.8: support implicit (G)String to Enum coercion
This commit is contained in:
@@ -350,4 +350,6 @@ duplicated.named.parameter=Duplicated named parameter ''{0}'' found
|
||||
cannot.find.method.call=No signature of method: {0}.call() is applicable for {1}
|
||||
no.super.classes.found=No super classes found
|
||||
no.super.method.found=No super methods found
|
||||
wrong.package.name=Package name ''{0}'' does not corresponding to the file path ''{1}''
|
||||
wrong.package.name=Package name ''{0}'' does not corresponding to the file path ''{1}''
|
||||
cannot.assign.string.to.enum.0=Cannot assign string to enum ''{0}''
|
||||
cannot.find.enum.constant.0.in.enum.1=Cannot find enum constant ''{0}'' in enum ''{1}''
|
||||
+17
-10
@@ -90,7 +90,7 @@ public abstract class BaseInspectionVisitor extends GroovyRecursiveElementVisito
|
||||
}
|
||||
final LocalQuickFix[] fix = createFixes(location);
|
||||
final String description = inspection.buildErrorString(location);
|
||||
registerError(location, description, fix);
|
||||
registerError(location, description, fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
protected void registerMethodError(GrMethod method, Object... args) {
|
||||
@@ -99,7 +99,7 @@ public abstract class BaseInspectionVisitor extends GroovyRecursiveElementVisito
|
||||
}
|
||||
final LocalQuickFix[] fix = createFixes(method);
|
||||
final String description = inspection.buildErrorString(args);
|
||||
registerError(method.getNameIdentifierGroovy(), description, fix);
|
||||
registerError(method.getNameIdentifierGroovy(), description, fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
protected void registerVariableError(GrVariable variable, Object... args) {
|
||||
@@ -108,7 +108,7 @@ public abstract class BaseInspectionVisitor extends GroovyRecursiveElementVisito
|
||||
}
|
||||
final LocalQuickFix[] fix = createFixes(variable);
|
||||
final String description = inspection.buildErrorString(args);
|
||||
registerError(variable.getNameIdentifierGroovy(), description, fix);
|
||||
registerError(variable.getNameIdentifierGroovy(), description, fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
protected void registerMethodCallError(GrMethodCallExpression method, Object... args) {
|
||||
@@ -117,20 +117,27 @@ public abstract class BaseInspectionVisitor extends GroovyRecursiveElementVisito
|
||||
}
|
||||
final LocalQuickFix[] fix = createFixes(method);
|
||||
final String description = inspection.buildErrorString(args);
|
||||
registerError(((GrReferenceExpression) method.getInvokedExpression()).getReferenceNameElement(), description, fix);
|
||||
registerError(((GrReferenceExpression) method.getInvokedExpression()).getReferenceNameElement(), description, fix,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
|
||||
private void registerError(@NotNull PsiElement location, String description,
|
||||
LocalQuickFix[] fixes) {
|
||||
problemsHolder.registerProblem(location,
|
||||
description,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes);
|
||||
private void registerError(@NotNull PsiElement location,
|
||||
String description,
|
||||
LocalQuickFix[] fixes,
|
||||
ProblemHighlightType highlightType) {
|
||||
problemsHolder.registerProblem(location, description, highlightType, fixes);
|
||||
}
|
||||
|
||||
protected void registerError(@NotNull PsiElement location, Object... args) {
|
||||
registerError(location, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, args);
|
||||
}
|
||||
|
||||
protected void registerError(@NotNull PsiElement location,
|
||||
ProblemHighlightType highlightType,
|
||||
Object... args) {
|
||||
final LocalQuickFix[] fix = createFixes(location);
|
||||
final String description = inspection.buildErrorString(args);
|
||||
registerError(location, description, fix);
|
||||
registerError(location, description, fix, highlightType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+33
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.codeInspection.assignment;
|
||||
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -27,6 +28,7 @@ import org.jetbrains.plugins.groovy.annotator.GroovyAnnotator;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.extensions.GroovyNamedArgumentProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
@@ -51,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyConstantExpressionEvaluator;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -93,6 +96,7 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
private static class MyVisitor extends BaseInspectionVisitor {
|
||||
private void checkAssignability(@NotNull PsiType expectedType, @NotNull GrExpression expression, GroovyPsiElement element) {
|
||||
if (PsiUtil.isRawClassMemberAccess(expression)) return; //GRVY-2197
|
||||
if (checkForImplicitEnumAssigning(expectedType, expression, element)) return;
|
||||
final PsiType rType = expression.getType();
|
||||
if (rType == null || rType == PsiType.VOID) return;
|
||||
if (!TypesUtil.isAssignable(expectedType, rType, element)) {
|
||||
@@ -100,6 +104,35 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkForImplicitEnumAssigning(PsiType expectedType, GrExpression expression, GroovyPsiElement element) {
|
||||
if (!(expectedType instanceof PsiClassType)) return false;
|
||||
|
||||
if (!GroovyConfigUtils.getInstance().isVersionAtLeast(element, GroovyConfigUtils.GROOVY1_8)) return false;
|
||||
|
||||
final PsiClass resolved = ((PsiClassType)expectedType).resolve();
|
||||
if (resolved == null || !resolved.isEnum()) return false;
|
||||
|
||||
final PsiType type = expression.getType();
|
||||
if (type == null) return false;
|
||||
|
||||
if (!type.equalsToText(GroovyCommonClassNames.GROOVY_LANG_GSTRING) && !type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Object result = GroovyConstantExpressionEvaluator.evaluate(expression);
|
||||
if (result == null || !(result instanceof String)) {
|
||||
registerError(element, ProblemHighlightType.WEAK_WARNING,
|
||||
GroovyBundle.message("cannot.assign.string.to.enum.0", expectedType.getPresentableText()));
|
||||
}
|
||||
else {
|
||||
final PsiField field = resolved.findFieldByName((String)result, true);
|
||||
if (!(field instanceof PsiEnumConstant)) {
|
||||
registerError(element, GroovyBundle.message("cannot.find.enum.constant.0.in.enum.1", result, expectedType.getPresentableText()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//isApplicable last expression on method body
|
||||
@Override
|
||||
public void visitOpenBlock(GrOpenBlock block) {
|
||||
|
||||
@@ -191,25 +191,24 @@ public class PsiImplUtil {
|
||||
@Nullable
|
||||
public static GrExpression getRuntimeQualifier(GrReferenceExpression refExpr) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
GrClosableBlock closure = PsiTreeUtil.getParentOfType(refExpr, GrClosableBlock.class);
|
||||
while (closure != null) {
|
||||
PsiElement parent = closure.getParent();
|
||||
if (parent instanceof GrArgumentList) parent = parent.getParent();
|
||||
if (parent instanceof GrMethodCall) {
|
||||
GrExpression funExpr = ((GrMethodCall)parent).getInvokedExpression();
|
||||
if (funExpr instanceof GrReferenceExpression && ((GrReferenceExpression)funExpr).resolve() instanceof PsiMethod) {
|
||||
qualifier = ((GrReferenceExpression) funExpr).getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
return qualifier;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return funExpr;
|
||||
if (qualifier != null) return qualifier;
|
||||
|
||||
for (GrClosableBlock closure = PsiTreeUtil.getParentOfType(refExpr, GrClosableBlock.class);
|
||||
closure != null;
|
||||
closure = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class)) {
|
||||
PsiElement parent = closure.getParent();
|
||||
if (parent instanceof GrArgumentList) parent = parent.getParent();
|
||||
if (parent instanceof GrMethodCall) {
|
||||
GrExpression funExpr = ((GrMethodCall)parent).getInvokedExpression();
|
||||
if (funExpr instanceof GrReferenceExpression && ((GrReferenceExpression)funExpr).resolve() instanceof PsiMethod) {
|
||||
qualifier = ((GrReferenceExpression)funExpr).getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
return qualifier;
|
||||
}
|
||||
}
|
||||
|
||||
closure = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class);
|
||||
else {
|
||||
return funExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils;
|
||||
|
||||
/**
|
||||
@@ -29,7 +30,7 @@ public class Groovy16HighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
return TestUtils.getTestDataPath() + "highlighting/";
|
||||
}
|
||||
|
||||
private void doTest(LocalInspectionTool... tools) throws Exception {
|
||||
private void doTest(LocalInspectionTool... tools) {
|
||||
myFixture.enableInspections(tools);
|
||||
myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy");
|
||||
}
|
||||
@@ -37,4 +38,7 @@ public class Groovy16HighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testInnerEnum() throws Exception {doTest();}
|
||||
public void testSuperWithNotEnclosingClass() throws Throwable {doTest();}
|
||||
public void testThisWithWrongQualifier() throws Throwable {doTest();}
|
||||
|
||||
public void testImplicitEnumCoercion1_6() {
|
||||
doTest(new GroovyAssignabilityCheckInspection());}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ import java.io.IOException;
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
public static final DefaultLightProjectDescriptor GROOVY_17_PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() {
|
||||
public static final DefaultLightProjectDescriptor GROOVY_18_PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() {
|
||||
@Override
|
||||
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
|
||||
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel();
|
||||
@@ -59,7 +59,7 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return GROOVY_17_PROJECT_DESCRIPTOR;
|
||||
return GROOVY_18_PROJECT_DESCRIPTOR;
|
||||
}
|
||||
|
||||
public void testDuplicateClosurePrivateVariable() throws Throwable {
|
||||
@@ -444,4 +444,8 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testUnknownVarInArgList() {
|
||||
doTest(new GroovyAssignabilityCheckInspection());
|
||||
}
|
||||
|
||||
public void testImplicitEnumCoercion() {
|
||||
doTest(new GroovyAssignabilityCheckInspection());
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return GroovyHighlightingTest.GROOVY_17_PROJECT_DESCRIPTOR;
|
||||
return GroovyHighlightingTest.GROOVY_18_PROJECT_DESCRIPTOR;
|
||||
}
|
||||
|
||||
public void testMissingReturnWithLastLoop() throws Throwable { doTest(); }
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
enum My {
|
||||
foo, bar
|
||||
}
|
||||
|
||||
My var = 'foo'
|
||||
var = <warning descr="Cannot find enum constant 'fail' in enum 'My'">'fail'</warning>
|
||||
|
||||
var = "fo"+"o"
|
||||
var="fo${'o'}"
|
||||
@@ -0,0 +1,5 @@
|
||||
enum My {
|
||||
foo, bar
|
||||
}
|
||||
|
||||
My var = <warning descr="Cannot assign 'String' to 'My'">'foo'</warning>
|
||||
Reference in New Issue
Block a user