KT-5099 "Remove explicit type arguments" should highlight only type arguments

#KT-5099 Fixed
This commit is contained in:
Svetlana Isakova
2014-05-30 19:15:32 +04:00
parent 1665ef7a00
commit bc2d2fc2d4
19 changed files with 37 additions and 43 deletions
@@ -17,6 +17,6 @@
package org.jetbrains.jet.plugin.inspections package org.jetbrains.jet.plugin.inspections
import org.jetbrains.jet.plugin.intentions.RemoveExplicitTypeArguments import org.jetbrains.jet.plugin.intentions.RemoveExplicitTypeArguments
import org.jetbrains.jet.lang.psi.JetCallExpression import org.jetbrains.jet.lang.psi.JetTypeArgumentList
public class RemoveExplicitTypeArgsInspection : IntentionBasedInspection<JetCallExpression>(RemoveExplicitTypeArguments()) public class RemoveExplicitTypeArgsInspection : IntentionBasedInspection<JetTypeArgumentList>(RemoveExplicitTypeArguments())
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.lang.psi.JetCallExpression import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo
import org.jetbrains.jet.lang.types.TypeUtils import org.jetbrains.jet.lang.types.TypeUtils
@@ -37,20 +36,23 @@ import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.psi.JetReturnExpression import org.jetbrains.jet.lang.psi.JetReturnExpression
import org.jetbrains.jet.lang.psi.JetDeclaration import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
import com.intellij.psi.util.PsiTreeUtil
public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpression>( public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetTypeArgumentList>(
"remove.explicit.type.arguments", javaClass()) { "remove.explicit.type.arguments", javaClass()) {
override fun isApplicableTo(element: JetCallExpression): Boolean { override fun isApplicableTo(element: JetTypeArgumentList): Boolean {
val callExpression = element.getParent()
if (callExpression !is JetCallExpression) return false
val context = AnalyzerFacadeWithCache.getContextForElement(element) val context = AnalyzerFacadeWithCache.getContextForElement(callExpression)
if (element.getTypeArguments().isEmpty()) return false if (callExpression.getTypeArguments().isEmpty()) return false
val resolveSession = element.getLazyResolveSession() val resolveSession = callExpression.getLazyResolveSession()
val injector = InjectorForMacros(element.getProject(), resolveSession.getModuleDescriptor()) val injector = InjectorForMacros(callExpression.getProject(), resolveSession.getModuleDescriptor())
val scope = context[BindingContext.RESOLUTION_SCOPE, element] val scope = context[BindingContext.RESOLUTION_SCOPE, callExpression]
val originalCall = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()]?.getCall() val originalCall = context[BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression()]?.getCall()
if (originalCall == null || scope !is JetScope) return false if (originalCall == null || scope !is JetScope) return false
val untypedCall = CallWithoutTypeArgs(originalCall) val untypedCall = CallWithoutTypeArgs(originalCall)
@@ -58,8 +60,8 @@ public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpr
// If always use expected type from trace there is a problem with nested calls: // 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), // 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 // therefore we should resolve outer call with erased type arguments for inner call
val parent = element.getParent() val parent = callExpression.getParent()
val expectedTypeIsExplicitInCode = when(parent) { val expectedTypeIsExplicitInCode = when (parent) {
is JetProperty -> parent.getInitializer() == callExpression && parent.getTypeRef() != null is JetProperty -> parent.getInitializer() == callExpression && parent.getTypeRef() != null
is JetDeclarationWithBody -> parent.getBodyExpression() == callExpression is JetDeclarationWithBody -> parent.getBodyExpression() == callExpression
is JetReturnExpression -> true is JetReturnExpression -> true
@@ -71,11 +73,11 @@ public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpr
else { else {
TypeUtils.NO_EXPECTED_TYPE TypeUtils.NO_EXPECTED_TYPE
} }
val dataFlow = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, element] ?: DataFlowInfo.EMPTY val dataFlow = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, callExpression] ?: 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)
val args = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()]?.getTypeArguments() val args = context[BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression()]?.getTypeArguments()
val newArgs = resolvedCall?.getResultingCall()?.getTypeArguments() val newArgs = resolvedCall?.getResultingCall()?.getTypeArguments()
return args == newArgs return args == newArgs
@@ -91,15 +93,7 @@ public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpr
} }
override fun applyTo(element: JetCallExpression, editor: Editor) { override fun applyTo(element: JetTypeArgumentList, editor: Editor) {
val text = element.getText() element.delete()
val typeArgs = element.getTypeArgumentList()
if (text == null || typeArgs == null) return
val base = typeArgs.getTextOffset() - element.getTextOffset()
val untypedText = "${text.substring(0, base)}${text.substring(base + typeArgs.getTextLength())}"
element.replace(JetPsiFactory.createExpression(element.getProject(), untypedText))
} }
} }
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val z = <caret>bar<String, Int, Int, String>("1", 1, 2, "x") val z = bar<caret><String, Int, Int, String>("1", 1, 2, "x")
} }
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2 fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2
@@ -1,6 +1,6 @@
// IS_APPLICABLE: false // IS_APPLICABLE: false
fun foo() { fun foo() {
<caret>bar<(Int) -> Int>({ baz(it) }) bar<caret><(Int) -> Int>({ baz(it) })
} }
fun baz(x: Int): Int = x fun baz(x: Int): Int = x
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
<caret>bar<(Int) -> Int> { (it:Int) -> it } bar<caret><(Int) -> Int> { (it: Int) -> it }
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
bar {(it: Int) -> it } bar { (it: Int) -> it }
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = <caret>Box<Any>(Any()) val x = Box<caret><Any>(Any())
} }
class Box<T>(t : T) { class Box<T>(t : T) {
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
<caret>bar<String>("x") bar<caret><String>("x")
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = <caret>Box<String>("x") val x = Box<caret><String>("x")
} }
class Box<T>(t : T) { class Box<T>(t : T) {
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = <caret>Box("x") val x = Box<caret>("x")
} }
class Box<T>(t : T) { class Box<T>(t : T) {
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = <caret>Box<Box<String>>(Box("x")) val x = Box<caret><Box<String>>(Box("x"))
} }
class Box<T>(t : T) { class Box<T>(t : T) {
@@ -1,7 +1,7 @@
// IS_APPLICABLE: false // IS_APPLICABLE: false
// ERROR: Unresolved reference: LinkedList // ERROR: Unresolved reference: LinkedList
fun foo() { fun foo() {
val x = <caret>bar<String>() val x = bar<caret><String>()
} }
fun <T> bar() : List<T> = LinkedList<T>(); fun <T> bar() : List<T> = LinkedList<T>();
@@ -1,6 +1,6 @@
// IS_APPLICABLE: false // IS_APPLICABLE: false
fun foo() { fun foo() {
val x = <caret>bar<Any>("x") val x = bar<caret><Any>("x")
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -1,6 +1,6 @@
// IS_APPLICABLE: false // IS_APPLICABLE: false
fun foo() { fun foo() {
val x = <caret>Box<Any>("x") val x = Box<caret><Any>("x")
} }
class Box<T>(t : T) { class Box<T>(t : T) {
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = <caret>bar<String, Int>("x", 0) val x = bar<caret><String, Int>("x", 0)
} }
fun bar<T, V>(t: T, v: V): Int = 1 fun bar<T, V>(t: T, v: V): Int = 1
@@ -1,7 +1,7 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo() { fun foo() {
val x = "x" val x = "x"
<caret>bar<String>(x) bar<caret><String>(x)
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -1,6 +1,6 @@
// IS_APPLICABLE: true // IS_APPLICABLE: true
fun foo(x: String) { fun foo(x: String) {
<caret>bar<String>(x) bar<caret><String>(x)
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -2,7 +2,7 @@
val x = "x" val x = "x"
fun foo() { fun foo() {
<caret>bar<String>(x) bar<caret><String>(x)
} }
fun bar<T>(t: T): Int = 1 fun bar<T>(t: T): Int = 1
@@ -2,7 +2,7 @@
fun foo() { fun foo() {
val x = "1" val x = "1"
val y = 2 val y = 2
val z = <caret>bar<String, Int, Int, String>(x, 1, y, "x") val z = bar<caret><String, Int, Int, String>(x, 1, y, "x")
} }
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2 fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2