KT-5028 "remove explicit type arguments" intention shouldn't be applicable
#KT-5028 Fixed
This commit is contained in:
@@ -31,6 +31,12 @@ import java.util.ArrayList
|
|||||||
import org.jetbrains.jet.di.InjectorForMacros
|
import org.jetbrains.jet.di.InjectorForMacros
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext
|
import org.jetbrains.jet.lang.resolve.BindingTraceContext
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||||
|
import org.jetbrains.jet.lang.psi.JetProperty
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeArgumentList
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReturnExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||||
|
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
||||||
|
|
||||||
public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpression>(
|
public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpression>(
|
||||||
"remove.explicit.type.arguments", javaClass()) {
|
"remove.explicit.type.arguments", javaClass()) {
|
||||||
@@ -48,7 +54,23 @@ public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpr
|
|||||||
if (originalCall == null || scope !is JetScope) return false
|
if (originalCall == null || scope !is JetScope) return false
|
||||||
val untypedCall = CallWithoutTypeArgs(originalCall)
|
val untypedCall = CallWithoutTypeArgs(originalCall)
|
||||||
|
|
||||||
val jType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ?: TypeUtils.NO_EXPECTED_TYPE
|
// todo Check with expected type for other expressions
|
||||||
|
// If always use expected type from trace there is a problem with nested calls:
|
||||||
|
// the expression type for them can depend on their explicit type arguments (via outer call),
|
||||||
|
// therefore we should resolve outer call with erased type arguments for inner call
|
||||||
|
val parent = element.getParent()
|
||||||
|
val expectedTypeIsExplicitInCode = when(parent) {
|
||||||
|
is JetProperty -> parent.getInitializer() == callExpression && parent.getTypeRef() != null
|
||||||
|
is JetDeclarationWithBody -> parent.getBodyExpression() == callExpression
|
||||||
|
is JetReturnExpression -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
val jType = if (expectedTypeIsExplicitInCode) {
|
||||||
|
context[BindingContext.EXPECTED_EXPRESSION_TYPE, callExpression] ?: TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
}
|
||||||
val dataFlow = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, element] ?: DataFlowInfo.EMPTY
|
val dataFlow = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, element] ?: DataFlowInfo.EMPTY
|
||||||
val resolvedCall = injector.getExpressionTypingServices()?.getCallResolver()?.resolveFunctionCall(
|
val resolvedCall = injector.getExpressionTypingServices()?.getCallResolver()?.resolveFunctionCall(
|
||||||
BindingTraceContext(), scope, untypedCall, jType, dataFlow, false)
|
BindingTraceContext(), scope, untypedCall, jType, dataFlow, false)
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar(): Foo<Int> = foo<caret><Int>()
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar(): Foo<Int> = foo<caret>()
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
@@ -98,4 +98,30 @@
|
|||||||
<description>Remove explicit type arguments</description>
|
<description>Remove explicit type arguments</description>
|
||||||
</problem>
|
</problem>
|
||||||
|
|
||||||
|
<problem>
|
||||||
|
<file>returnCallWithUnnecessaryTypeArgs.kt</file>
|
||||||
|
<line>4</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/returnCallWithUnnecessaryTypeArgs.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Type arguments are unnecessary</problem_class>
|
||||||
|
<description>Remove explicit type arguments</description>
|
||||||
|
</problem>
|
||||||
|
|
||||||
|
<problem>
|
||||||
|
<file>propertyInitializerIsCallWithUnnecessaryTypeArgs.kt</file>
|
||||||
|
<line>4</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/propertyInitializerIsCallWithUnnecessaryTypeArgs.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Type arguments are unnecessary</problem_class>
|
||||||
|
<description>Remove explicit type arguments</description>
|
||||||
|
</problem>
|
||||||
|
|
||||||
|
<problem>
|
||||||
|
<file>functionBodyIsCallWithUnnecessaryTypeArgs.kt</file>
|
||||||
|
<line>3</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/functionBodyIsCallWithUnnecessaryTypeArgs.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Type arguments are unnecessary</problem_class>
|
||||||
|
<description>Remove explicit type arguments</description>
|
||||||
|
</problem>
|
||||||
</problems>
|
</problems>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
class Some<T>
|
||||||
|
fun <T> foo(c: Some<T>) {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(Some<caret><String>())
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
val l: Foo<Int> = foo<caret><Int>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
val l: Foo<Int> = foo<caret>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar(): Foo<Int> {
|
||||||
|
return foo<caret><Int>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// IS_APPLICABLE: true
|
||||||
|
|
||||||
|
fun bar(): Foo<Int> {
|
||||||
|
return foo<caret>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
fun <T> foo(): Foo<T> = Foo()
|
||||||
@@ -4092,6 +4092,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/fourLiterals.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/fourLiterals.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("functionBodyIsCallWithUnnecessaryTypeArgs.kt")
|
||||||
|
public void testFunctionBodyIsCallWithUnnecessaryTypeArgs() throws Exception {
|
||||||
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/functionBodyIsCallWithUnnecessaryTypeArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inapplicableTypeThatIsAFunItCannotBeInferred.kt")
|
@TestMetadata("inapplicableTypeThatIsAFunItCannotBeInferred.kt")
|
||||||
public void testInapplicableTypeThatIsAFunItCannotBeInferred() throws Exception {
|
public void testInapplicableTypeThatIsAFunItCannotBeInferred() throws Exception {
|
||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/inapplicableTypeThatIsAFunItCannotBeInferred.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/inapplicableTypeThatIsAFunItCannotBeInferred.kt");
|
||||||
@@ -4122,6 +4127,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalsWhenTypeArgHasTypeArg.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalsWhenTypeArgHasTypeArg.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedCall-KT-5028.kt")
|
||||||
|
public void testNestedCall_KT_5028() throws Exception {
|
||||||
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/nestedCall-KT-5028.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("notApplicableNotEnoughtInfo.kt")
|
@TestMetadata("notApplicableNotEnoughtInfo.kt")
|
||||||
public void testNotApplicableNotEnoughtInfo() throws Exception {
|
public void testNotApplicableNotEnoughtInfo() throws Exception {
|
||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableNotEnoughtInfo.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableNotEnoughtInfo.kt");
|
||||||
@@ -4137,6 +4147,16 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableSupertypeOfInferredClass.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableSupertypeOfInferredClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyInitializerIsCallWithUnnecessaryTypeArgs.kt")
|
||||||
|
public void testPropertyInitializerIsCallWithUnnecessaryTypeArgs() throws Exception {
|
||||||
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/propertyInitializerIsCallWithUnnecessaryTypeArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("returnCallWithUnnecessaryTypeArgs.kt")
|
||||||
|
public void testReturnCallWithUnnecessaryTypeArgs() throws Exception {
|
||||||
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/returnCallWithUnnecessaryTypeArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("twoLiteralValues.kt")
|
@TestMetadata("twoLiteralValues.kt")
|
||||||
public void testTwoLiteralValues() throws Exception {
|
public void testTwoLiteralValues() throws Exception {
|
||||||
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/twoLiteralValues.kt");
|
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/twoLiteralValues.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user