mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-203683 Refactor GroovyTypeCheckVisitor, extract highlighting and fixes logic to own hierarchy
GitOrigin-RevId: fd60d700a90766311fbeec35d983c4e19e205d38
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6484b4ed62
commit
8a03bfbb6f
@@ -265,6 +265,7 @@ invoke.completion.second.time.to.show.skipped.methods=Invoke completion second t
|
||||
groovy.file.extension.is.not.mapped.to.groovy.file.type=*.groovy files are mapped to ''{0}''.\nYou can map them to Groovy in Settings | File types
|
||||
class.is.not.annotation=''{0}'' is not an annotation
|
||||
method.call.is.ambiguous=Method call is ambiguous
|
||||
operator.call.is.ambiguous=Operator call is ambiguous
|
||||
duplicated.named.parameter=Duplicated named parameter ''{0}'' found
|
||||
no.super.classes.found=No super classes found
|
||||
no.super.method.found=No super methods found
|
||||
|
||||
+17
-42
@@ -15,6 +15,10 @@ import org.jetbrains.plugins.groovy.annotator.GrHighlightUtil;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.*;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.highlighting.BinaryExpressionHighlighter;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.highlighting.GrConstructorInvocationHighlighter;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.highlighting.GrEnumConstantHighlighter;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.highlighting.GrNewExpressionHighlighter;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.extensions.GroovyNamedArgumentProvider;
|
||||
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
|
||||
@@ -64,7 +68,6 @@ import java.util.Objects;
|
||||
|
||||
import static com.intellij.psi.util.PsiUtil.extractIterableTypeParameter;
|
||||
import static org.jetbrains.plugins.groovy.codeInspection.type.GroovyTypeCheckVisitorHelper.*;
|
||||
import static org.jetbrains.plugins.groovy.codeInspection.type.ImplKt.processConstructor;
|
||||
import static org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils.isImplicitReturnStatement;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyExpressionUtil.isFake;
|
||||
|
||||
@@ -389,7 +392,10 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
}
|
||||
|
||||
private void checkNamedArgumentsType(@NotNull CallInfo<?> info) {
|
||||
GroovyPsiElement rawCall = info.getCall();
|
||||
checkNamedArgumentsType(info.getCall());
|
||||
}
|
||||
|
||||
private void checkNamedArgumentsType(@NotNull GroovyPsiElement rawCall) {
|
||||
if (!(rawCall instanceof GrCall)) return;
|
||||
GrCall call = (GrCall)rawCall;
|
||||
|
||||
@@ -432,32 +438,6 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOperator(@NotNull CallInfo<? extends GrBinaryExpression> info) {
|
||||
if (hasErrorElements(info.getCall())) return;
|
||||
|
||||
GroovyResolveResult[] results = info.multiResolve();
|
||||
GroovyResolveResult resolveResult = info.advancedResolve();
|
||||
|
||||
if (isOperatorWithSimpleTypes(info.getCall(), resolveResult)) return;
|
||||
|
||||
if (!checkCannotInferArgumentTypes(info)) return;
|
||||
|
||||
if (resolveResult.getElement() != null) {
|
||||
checkMethodApplicability(resolveResult, true, info);
|
||||
}
|
||||
else if (results.length > 0) {
|
||||
for (GroovyResolveResult result : results) {
|
||||
if (!checkMethodApplicability(result, false, info)) return;
|
||||
}
|
||||
|
||||
registerError(
|
||||
info.getElementToHighlight(),
|
||||
ProblemHighlightType.GENERIC_ERROR,
|
||||
GroovyBundle.message("method.call.is.ambiguous")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void highlightInapplicableMethodUsage(@NotNull GroovyResolveResult methodResolveResult,
|
||||
@NotNull CallInfo info,
|
||||
@NotNull PsiMethod method) {
|
||||
@@ -719,13 +699,11 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
|
||||
final GroovyCallReference reference = newExpression.getConstructorReference();
|
||||
if (reference == null) return;
|
||||
|
||||
final GrNewExpressionInfo info = new GrNewExpressionInfo(newExpression);
|
||||
if (processConstructor(reference, newExpression.getArgumentList(), info.getElementToHighlight(), myHighlightSink)) {
|
||||
if (new GrNewExpressionHighlighter(newExpression, reference, myHighlightSink).highlight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkNamedArgumentsType(info);
|
||||
checkNamedArgumentsType(newExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -733,13 +711,11 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
super.visitEnumConstant(enumConstant);
|
||||
if (hasErrorElements(enumConstant) || hasErrorElements(enumConstant.getArgumentList())) return;
|
||||
|
||||
final GrEnumConstantInfo info = new GrEnumConstantInfo(enumConstant);
|
||||
final GroovyCallReference reference = enumConstant.getConstructorReference();
|
||||
if (processConstructor(reference, enumConstant.getArgumentList(), info.getElementToHighlight(), myHighlightSink)) {
|
||||
if (new GrEnumConstantHighlighter(enumConstant, myHighlightSink).highlight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkNamedArgumentsType(info);
|
||||
checkNamedArgumentsType(enumConstant);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -747,12 +723,10 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
super.visitConstructorInvocation(invocation);
|
||||
if (hasErrorElements(invocation) || hasErrorElements(invocation.getArgumentList())) return;
|
||||
|
||||
final GrConstructorInvocationInfo info = new GrConstructorInvocationInfo(invocation);
|
||||
final GroovyCallReference reference = invocation.getConstructorReference();
|
||||
if (processConstructor(reference, invocation.getArgumentList(), info.getElementToHighlight(), myHighlightSink)) {
|
||||
if (new GrConstructorInvocationHighlighter(invocation, myHighlightSink).highlight()) {
|
||||
return;
|
||||
}
|
||||
checkNamedArgumentsType(info);
|
||||
checkNamedArgumentsType(invocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -794,8 +768,9 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor {
|
||||
@Override
|
||||
public void visitBinaryExpression(@NotNull GrBinaryExpression binary) {
|
||||
super.visitBinaryExpression(binary);
|
||||
if (isFake(binary)) return;
|
||||
checkOperator(new GrBinaryExprInfo(binary));
|
||||
GroovyCallReference reference = binary.getReference();
|
||||
if (reference == null) return;
|
||||
new BinaryExpressionHighlighter(binary, reference, myHighlightSink).highlight();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.util.containers.toArray
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle.message
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil.createSignature
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.DefaultConstructor
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.Argument
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.Arguments
|
||||
|
||||
fun HighlightSink.highlightUnknownArgs(highlightElement: PsiElement) {
|
||||
registerProblem(highlightElement, ProblemHighlightType.WEAK_WARNING, message("cannot.infer.argument.types"))
|
||||
}
|
||||
|
||||
fun HighlightSink.highlightCannotApplyError(invokedText: String, typesString: String, highlightElement: PsiElement) {
|
||||
registerError(highlightElement, message("cannot.apply.method.or.closure", invokedText, typesString))
|
||||
}
|
||||
|
||||
fun HighlightSink.highlightAmbiguousMethod(highlightElement: PsiElement) {
|
||||
registerError(highlightElement, message("constructor.call.is.ambiguous"))
|
||||
}
|
||||
|
||||
fun HighlightSink.highlightInapplicableMethod(result: GroovyMethodResult,
|
||||
arguments: List<Argument>,
|
||||
argumentList: GrArgumentList?,
|
||||
highlightElement: PsiElement) {
|
||||
val method = result.element
|
||||
val containingClass = if (method is GrGdkMethod) method.staticMethod.containingClass else method.containingClass
|
||||
|
||||
val argumentString = argumentsString(arguments)
|
||||
val methodName = method.name
|
||||
if (containingClass == null) {
|
||||
highlightCannotApplyError(methodName, argumentString, highlightElement)
|
||||
return
|
||||
}
|
||||
|
||||
val message: String
|
||||
if (method is DefaultConstructor) {
|
||||
message = message("cannot.apply.default.constructor", methodName)
|
||||
}
|
||||
else {
|
||||
val factory = JavaPsiFacade.getElementFactory(method.project)
|
||||
val containingType = factory.createType(containingClass, result.substitutor)
|
||||
val canonicalText = containingType.internalCanonicalText
|
||||
if (method.isConstructor) {
|
||||
message = message("cannot.apply.constructor", methodName, canonicalText, argumentString)
|
||||
}
|
||||
else {
|
||||
message = message("cannot.apply.method1", methodName, canonicalText, argumentString)
|
||||
}
|
||||
}
|
||||
val fixes = generateCastFixes(result, arguments, argumentList)
|
||||
registerProblem(highlightElement, ProblemHighlightType.GENERIC_ERROR, message, *fixes)
|
||||
}
|
||||
|
||||
private fun argumentsString(arguments: List<Argument>): String {
|
||||
return arguments.joinToString(", ", "(", ")") {
|
||||
it.type?.internalCanonicalText ?: "?"
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateCastFixes(result: GroovyMethodResult, arguments: Arguments, argumentList: GrArgumentList?): Array<out LocalQuickFix> {
|
||||
val signature = createSignature(result.element, result.substitutor)
|
||||
return GroovyTypeCheckVisitorHelper.genCastFixes(signature, arguments.map(Argument::type).toArray(PsiType.EMPTY_ARRAY), argumentList)
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiType
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GrCastFix
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.GroovyTypeCheckVisitorHelper.hasErrorElements
|
||||
import org.jetbrains.plugins.groovy.codeInspection.type.GroovyTypeCheckVisitorHelper.isOperatorWithSimpleTypes
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.isFake
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.*
|
||||
|
||||
class BinaryExpressionHighlighter(val expression: GrBinaryExpression,
|
||||
reference: GroovyCallReference,
|
||||
sink: HighlightSink) : CallReferenceHighlighter(reference, sink) {
|
||||
|
||||
override val unknownArgsMessage: String
|
||||
get() = GroovyBundle.message("cannot.infer.argument.types")
|
||||
override val ambiguousMethodMessage: String
|
||||
get() = GroovyBundle.message("operator.call.is.ambiguous")
|
||||
|
||||
override fun getInapplicableMethodMessage(result: GroovyMethodResult, containingType: PsiType, arguments: Arguments): String {
|
||||
val typeText = containingType.internalCanonicalText
|
||||
val argumentsString = argumentsString(arguments)
|
||||
return GroovyBundle.message("cannot.apply.method1", result.element.name, typeText, argumentsString)
|
||||
}
|
||||
|
||||
override fun getHighlightElement(): PsiElement = expression.operationToken
|
||||
|
||||
override fun buildFix(argument: Argument, applicabilityData: ApplicabilityData): GrCastFix? {
|
||||
if (argument !is ExpressionArgument || applicabilityData.applicability != Applicability.inapplicable) return null
|
||||
val arguments = reference.arguments ?: return null
|
||||
if (argument !in arguments) return null
|
||||
val type = applicabilityData.type ?: return null
|
||||
|
||||
val name = "Cast operand to " + type.presentableText
|
||||
return GrCastFix(type, argument.expression, true, name)
|
||||
}
|
||||
|
||||
fun highlight() {
|
||||
if (expression.isFake()) return
|
||||
if (hasErrorElements(expression)) return
|
||||
|
||||
val reference = expression.reference ?: return
|
||||
val resolveResult = reference.advancedResolve()
|
||||
|
||||
if (isOperatorWithSimpleTypes(expression, resolveResult)) return
|
||||
|
||||
highlightMethod()
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiType
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.*
|
||||
|
||||
abstract class CallReferenceHighlighter(val reference: GroovyCallReference, val sink: HighlightSink) {
|
||||
|
||||
abstract val unknownArgsMessage: String
|
||||
|
||||
abstract val ambiguousMethodMessage: String
|
||||
|
||||
abstract fun getInapplicableMethodMessage(result: GroovyMethodResult, containingType: PsiType, arguments: Arguments): String
|
||||
|
||||
abstract fun getHighlightElement(): PsiElement
|
||||
|
||||
abstract fun buildFix(argument: Argument, applicabilityData: ApplicabilityData): LocalQuickFix?
|
||||
|
||||
fun highlightCannotApplyError(invokedText: String, typesString: String) {
|
||||
sink.registerError(getHighlightElement(), GroovyBundle.message("cannot.apply.method.or.closure", invokedText, typesString))
|
||||
}
|
||||
|
||||
fun highlightUnknownArgs() {
|
||||
sink.registerProblem(getHighlightElement(), ProblemHighlightType.WEAK_WARNING, unknownArgsMessage)
|
||||
}
|
||||
|
||||
fun highlightAmbiguousMethod() {
|
||||
sink.registerError(getHighlightElement(), ambiguousMethodMessage)
|
||||
}
|
||||
|
||||
fun highlightInapplicableMethod(result: GroovyMethodResult, arguments: Arguments) {
|
||||
val method = result.element
|
||||
val containingClass = if (method is GrGdkMethod) method.staticMethod.containingClass else method.containingClass
|
||||
|
||||
val methodName = method.name
|
||||
val highlightElement = getHighlightElement()
|
||||
val argumentsString = argumentsString(arguments)
|
||||
if (containingClass == null) {
|
||||
highlightCannotApplyError(methodName, argumentsString)
|
||||
return
|
||||
}
|
||||
val factory = JavaPsiFacade.getElementFactory(method.project)
|
||||
val containingType = factory.createType(containingClass, result.substitutor)
|
||||
|
||||
val fixes = generateFixes(result)
|
||||
val message = getInapplicableMethodMessage(result, containingType, arguments)
|
||||
sink.registerProblem(highlightElement, ProblemHighlightType.GENERIC_ERROR, message, *fixes)
|
||||
}
|
||||
|
||||
fun highlightMethod(): Boolean {
|
||||
val userArguments = reference.arguments ?: run {
|
||||
highlightUnknownArgs()
|
||||
return true
|
||||
}
|
||||
|
||||
val results = reference.resolve(false)
|
||||
var hasUnknownResults = false
|
||||
for (result in results) {
|
||||
if (result !is GroovyMethodResult) continue
|
||||
val candidate = result.candidate ?: continue
|
||||
val mapping = candidate.argumentMapping
|
||||
if (mapping == null) {
|
||||
highlightInapplicableMethod(result, userArguments)
|
||||
return true
|
||||
}
|
||||
val applicability = mapping.applicability(result.substitutor, false)
|
||||
when (applicability) {
|
||||
Applicability.inapplicable -> {
|
||||
highlightInapplicableMethod(result, userArguments)
|
||||
return true
|
||||
}
|
||||
Applicability.canBeApplicable -> hasUnknownResults = true
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
if (results.size > 1) {
|
||||
if (hasUnknownResults) {
|
||||
highlightUnknownArgs()
|
||||
return true
|
||||
}
|
||||
else {
|
||||
highlightAmbiguousMethod()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun generateFixes(result: GroovyMethodResult): Array<LocalQuickFix> {
|
||||
val applicabilities = result.candidate?.argumentMapping?.highlightApplicabilities(result.substitutor)
|
||||
?: return emptyArray()
|
||||
return applicabilities.entries
|
||||
.mapNotNull { (argument, applicabilities) -> buildFix(argument, applicabilities) }
|
||||
.toTypedArray()
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.psi.PsiType
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.ParameterCastFix
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.DefaultConstructor
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.*
|
||||
|
||||
abstract class ConstructorCallHighlighter(reference: GroovyCallReference,
|
||||
sink: HighlightSink) : CallReferenceHighlighter(reference, sink) {
|
||||
|
||||
abstract fun getArgumentList(): GrArgumentList?
|
||||
|
||||
override val unknownArgsMessage: String
|
||||
get() = GroovyBundle.message("cannot.infer.argument.types")
|
||||
override val ambiguousMethodMessage: String
|
||||
get() = GroovyBundle.message("method.call.is.ambiguous")
|
||||
|
||||
override fun getInapplicableMethodMessage(result: GroovyMethodResult, containingType: PsiType, arguments: Arguments): String {
|
||||
val method = result.element
|
||||
val methodName = method.name
|
||||
if (method is DefaultConstructor) {
|
||||
return GroovyBundle.message("cannot.apply.default.constructor", methodName)
|
||||
}
|
||||
else {
|
||||
val canonicalText = containingType.internalCanonicalText
|
||||
return GroovyBundle.message("cannot.apply.constructor", methodName, canonicalText,
|
||||
argumentsString(arguments))
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildFix(argument: Argument, applicabilityData: ApplicabilityData): ParameterCastFix? {
|
||||
if (argument !is ExpressionArgument || applicabilityData.applicability != Applicability.inapplicable) return null
|
||||
val arguments = reference.arguments ?: return null
|
||||
val list = getArgumentList() ?: return null
|
||||
if (argument !in arguments) return null
|
||||
val type = applicabilityData.type ?: return null
|
||||
|
||||
val position = list.getExpressionArgumentIndex(argument.expression)
|
||||
return ParameterCastFix(position, type)
|
||||
}
|
||||
|
||||
fun highlight(): Boolean = highlightMethod()
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
|
||||
class GrConstructorInvocationHighlighter(val invocation: GrConstructorInvocation,
|
||||
sink: HighlightSink) : ConstructorCallHighlighter(invocation.constructorReference, sink) {
|
||||
|
||||
override fun getArgumentList(): GrArgumentList = invocation.argumentList
|
||||
|
||||
override fun getHighlightElement(): PsiElement = getArgumentList()
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant
|
||||
|
||||
class GrEnumConstantHighlighter(val enumConstant: GrEnumConstant,
|
||||
sink: HighlightSink) : ConstructorCallHighlighter(enumConstant.constructorReference, sink) {
|
||||
|
||||
override fun getArgumentList(): GrArgumentList? = enumConstant.argumentList
|
||||
|
||||
override fun getHighlightElement(): PsiElement = getArgumentList() ?: enumConstant.nameIdentifierGroovy
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.GroovyCallReference
|
||||
|
||||
class GrNewExpressionHighlighter(val newExpression: GrNewExpression,
|
||||
reference: GroovyCallReference,
|
||||
sink: HighlightSink) : ConstructorCallHighlighter(reference, sink) {
|
||||
|
||||
override fun getArgumentList(): GrArgumentList? = newExpression.argumentList
|
||||
|
||||
override fun getHighlightElement(): PsiElement {
|
||||
val element = getArgumentList() ?: newExpression.referenceElement
|
||||
if (element != null) return element
|
||||
throw IncorrectOperationException("reference of new expression should exist if it is a constructor call")
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type.highlighting
|
||||
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.Arguments
|
||||
|
||||
fun argumentsString(arguments: Arguments): String {
|
||||
return arguments.joinToString(", ", "(", ")") {
|
||||
it.type?.internalCanonicalText ?: "?"
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.codeInspection.type
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.plugins.groovy.highlighting.HighlightSink
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.Applicability
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.api.GroovyCallReference
|
||||
|
||||
fun processConstructor(reference: GroovyCallReference,
|
||||
argumentList: GrArgumentList?,
|
||||
highlightElement: PsiElement,
|
||||
sink: HighlightSink): Boolean {
|
||||
val userArguments = reference.arguments ?: run {
|
||||
sink.highlightUnknownArgs(highlightElement)
|
||||
return true
|
||||
}
|
||||
|
||||
val results = reference.resolve(false)
|
||||
var hasUnknownResults = false
|
||||
for (result in results) {
|
||||
if (result !is GroovyMethodResult) continue
|
||||
val candidate = result.candidate ?: continue
|
||||
val mapping = candidate.argumentMapping
|
||||
if (mapping == null) {
|
||||
sink.highlightInapplicableMethod(result, userArguments, argumentList, highlightElement)
|
||||
return true
|
||||
}
|
||||
val applicability = mapping.applicability(result.substitutor, false)
|
||||
when (applicability) {
|
||||
Applicability.inapplicable -> {
|
||||
sink.highlightInapplicableMethod(result, mapping.arguments, argumentList, highlightElement)
|
||||
return true
|
||||
}
|
||||
Applicability.canBeApplicable -> hasUnknownResults = true
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
if (results.size > 1) {
|
||||
if (hasUnknownResults) {
|
||||
sink.highlightUnknownArgs(highlightElement)
|
||||
return true
|
||||
}
|
||||
else {
|
||||
sink.highlightAmbiguousMethod(highlightElement)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -7,4 +7,4 @@ typealias Arguments = List<Argument>
|
||||
|
||||
typealias Applicabilities = Map<Argument, ApplicabilityData>
|
||||
|
||||
data class ApplicabilityData(val psiType: PsiType?, val applicability: Applicability)
|
||||
data class ApplicabilityData(val type: PsiType?, val applicability: Applicability)
|
||||
@@ -17,14 +17,19 @@ package org.jetbrains.plugins.groovy.inspections
|
||||
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
class CastToTypeTest extends LightCodeInsightFixtureTestCase {
|
||||
class CastToTypeTest extends LightGroovyTestCase {
|
||||
|
||||
final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return TestUtils.testDataPath + 'groovy/inspections/castToType'
|
||||
@@ -42,4 +47,6 @@ class CastToTypeTest extends LightCodeInsightFixtureTestCase {
|
||||
void testSimple() {doTest('Cast to List<? extends Abc>')}
|
||||
void testInReturnType() {doTest('Cast to int')}
|
||||
void testInForCycle() {doTest('Cast to List<Integer>')}
|
||||
|
||||
void testInBinaryExpression() {doTest('Cast operand to String')}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
class C {
|
||||
def plus(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@CompileStatic
|
||||
def foo() {
|
||||
new C() +<caret> 1
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
class C {
|
||||
def plus(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
@CompileStatic
|
||||
def foo() {
|
||||
new C() + (1 as String)
|
||||
}
|
||||
@@ -3,13 +3,13 @@ class A {
|
||||
Inner() {}
|
||||
def foo() {
|
||||
new Inner() // correct
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A)'">(new A())</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A)'">(new A())</warning> // incorrect
|
||||
}
|
||||
}
|
||||
|
||||
def foo() {
|
||||
new Inner() //correct
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A)'">(new A())</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A)'">(new A())</warning> // incorrect
|
||||
}
|
||||
|
||||
static def bar() {
|
||||
|
||||
+3
-3
@@ -4,10 +4,10 @@ class A {
|
||||
}
|
||||
|
||||
def foo() {
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A)'">()</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A)'">(new A())</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '()'">()</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A)'">(new A())</warning> // incorrect
|
||||
new Inner("") // correct
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A, java.lang.String)'">(new A(), "")</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, java.lang.String)'">(new A(), "")</warning> // incorrect
|
||||
}
|
||||
|
||||
static def bar() {
|
||||
|
||||
@@ -4,9 +4,9 @@ class A {
|
||||
}
|
||||
|
||||
def foo() {
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A)'">()</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '()'">()</warning> // incorrect
|
||||
new Inner(new A()) // correct
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A, A)'">(new A(), new A())</warning> // incorrect
|
||||
new Inner<warning descr="Constructor 'Inner' in 'A.Inner' cannot be applied to '(A, A)'">(new A(), new A())</warning> // incorrect
|
||||
}
|
||||
|
||||
static def bar() {
|
||||
|
||||
Reference in New Issue
Block a user