Merge pull request #406 from wutalman/explicit_type_arguments

KT-4583 Intention for removing explicit type arguments at function calls
This commit is contained in:
Svetlana Isakova
2014-04-15 12:09:15 +04:00
35 changed files with 379 additions and 2 deletions
@@ -391,6 +391,7 @@ fun main(args: Array<String>) {
model("intentions/replaceWithTraditionalAssignment", testMethod = "doTestReplaceWithTraditionalAssignment")
model("intentions/simplifyBooleanWithConstants", testMethod = "doTestSimplifyBooleanWithConstants")
model("intentions/insertExplicitTypeArguments", testMethod = "doTestInsertExplicitTypeArguments")
model("intentions/removeExplicitTypeArguments", testMethod = "doTestRemoveExplicitTypeArguments")
}
testClass(javaClass<AbstractJetInspectionTest>()) {
@@ -0,0 +1,3 @@
fun foo() {
val x = <spot>X("x")</spot>
}
@@ -0,0 +1,3 @@
fun foo() {
val x = <spot>X<String>("x")</spot>
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention removes type arguments from function calls when they can be implicitly inferred
</body>
</html>
+5
View File
@@ -553,6 +553,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.RemoveExplicitTypeArguments</className>
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.RemoveCurlyBracesFromTemplateIntention</className>
<category>Kotlin</category>
@@ -295,7 +295,8 @@ simplify.boolean.with.constants=Simplify boolean expression
simplify.boolean.with.constants.family=Simplify boolean expression
insert.explicit.type.arguments=Add explicit type arguments
insert.explicit.type.arguments.family=Add explicit type arguments
>>>>>>> Intention for adding explicit type arguments at function calls
remove.explicit.type.arguments=Remove explicit type arguments
remove.explicit.type.arguments.family=Remove explicit type arguments
property.is.implemented.too.many=Has implementations
property.is.overridden.too.many=Is overridden in subclasses
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo
import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.psi.JetTypeProjection
import org.jetbrains.jet.lang.psi.Call
import java.util.ArrayList
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.di.InjectorForMacros
import org.jetbrains.jet.lang.resolve.BindingTraceContext
public class RemoveExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpression>(
"remove.explicit.type.arguments", javaClass()) {
override fun isApplicableTo(element: JetCallExpression): Boolean {
val context = AnalyzerFacadeWithCache.getContextForElement(element)
if (element.getTypeArguments().isEmpty()) return false
val resolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile((element.getContainingFile() as JetFile))
val injector = InjectorForMacros(element.getProject(), resolveSession.getModuleDescriptor())
val scope = context[BindingContext.RESOLUTION_SCOPE, element]
val originalCall = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()]?.getCall()
if (originalCall == null || scope !is JetScope) return false
val untypedCall = CallWithoutTypeArgs(originalCall)
val jType = context[BindingContext.EXPECTED_EXPRESSION_TYPE, element] ?: TypeUtils.NO_EXPECTED_TYPE
val dataFlow = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, element] ?: DataFlowInfo.EMPTY
val resolvedCall = injector.getExpressionTypingServices()?.getCallResolver()?.resolveFunctionCall(
BindingTraceContext(), scope, untypedCall, jType, dataFlow, false)
val args = context[BindingContext.RESOLVED_CALL, element.getCalleeExpression()]?.getTypeArguments()
val newArgs = resolvedCall?.getResultingCall()?.getTypeArguments()
return args == newArgs
}
class CallWithoutTypeArgs(call: Call) : DelegatingCall(call) {
override fun getTypeArguments(): MutableList<JetTypeProjection> {
return ArrayList<JetTypeProjection>()
}
override fun getTypeArgumentList() = null
}
override fun applyTo(element: JetCallExpression, editor: Editor) {
val text = element.getText()
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))
}
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
val z = <caret>bar<String, Int, Int, String>("1", 1, 2, "x")
}
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
val z = bar("1", 1, 2, "x")
}
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
fun foo() {
<caret>bar<(Int) -> Int>({ baz(it) })
}
fun baz(x: Int): Int = x
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
<caret>bar<(Int) -> Int> { (it:Int) -> it }
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
bar {(it: Int) -> it }
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = <caret>Box<Any>(Any())
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = Box(Any())
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
<caret>bar<String>("x")
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
bar("x")
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = <caret>Box<String>("x")
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = <caret>Box("x")
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = <caret>Box<Box<String>>(Box("x"))
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = Box(Box("x"))
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,7 @@
// IS_APPLICABLE: false
// ERROR: Unresolved reference: LinkedList
fun foo() {
val x = <caret>bar<String>()
}
fun <T> bar() : List<T> = LinkedList<T>();
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun foo() {
val x = <caret>bar<Any>("x")
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
fun foo() {
val x = <caret>Box<Any>("x")
}
class Box<T>(t : T) {
var value = t
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
val x = <caret>bar<String, Int>("x", 0)
}
fun bar<T, V>(t: T, v: V): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo() {
val x = bar("x", 0)
}
fun bar<T, V>(t: T, v: V): Int = 1
@@ -0,0 +1,7 @@
// IS_APPLICABLE: true
fun foo() {
val x = "x"
<caret>bar<String>(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,7 @@
// IS_APPLICABLE: true
fun foo() {
val x = "x"
bar(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo(x: String) {
<caret>bar<String>(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,6 @@
// IS_APPLICABLE: true
fun foo(x: String) {
bar(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
val x = "x"
fun foo() {
<caret>bar<String>(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
val x = "x"
fun foo() {
bar(x)
}
fun bar<T>(t: T): Int = 1
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = "1"
val y = 2
val z = <caret>bar<String, Int, Int, String>(x, 1, y, "x")
}
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2
@@ -0,0 +1,8 @@
// IS_APPLICABLE: true
fun foo() {
val x = "1"
val y = 2
val z = bar(x, 1, y, "x")
}
fun bar<T, V, R, K>(t: T, v: V, r: R, k: K): Int = 2
@@ -148,9 +148,15 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes
public void doTestMoveLambdaOutsideParentheses(@NotNull String path) throws Exception {
doTestIntention(path, new MoveLambdaOutsideParenthesesIntention());
}
public void doTestSwapBinaryExpression(@NotNull String path) throws Exception {
doTestIntention(path, new SwapBinaryExpression());
}
public void doTestRemoveExplicitTypeArguments(@NotNull String path) throws Exception {
doTestIntention(path, new RemoveExplicitTypeArguments());
}
public void doTestConvertMemberToExtension(@NotNull String path) throws Exception {
doTestIntention(path, new ConvertMemberToExtension());
}
@@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.intentions.AbstractCodeTransformationTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@InnerTestClasses({CodeTransformationTestGenerated.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class, CodeTransformationTestGenerated.ReplaceWithDotQualifiedMethodCall.class, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class, CodeTransformationTestGenerated.ReplaceWithTraditionalAssignment.class, CodeTransformationTestGenerated.SimplifyBooleanWithConstants.class, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class})
@InnerTestClasses({CodeTransformationTestGenerated.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class, CodeTransformationTestGenerated.ReplaceWithDotQualifiedMethodCall.class, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class, CodeTransformationTestGenerated.ReplaceWithTraditionalAssignment.class, CodeTransformationTestGenerated.SimplifyBooleanWithConstants.class, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class, CodeTransformationTestGenerated.RemoveExplicitTypeArguments.class})
public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest {
@TestMetadata("idea/testData/intentions/branched/elvisToIfThen")
public static class ElvisToIfThen extends AbstractCodeTransformationTest {
@@ -3427,6 +3427,89 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
}
@TestMetadata("idea/testData/intentions/removeExplicitTypeArguments")
public static class RemoveExplicitTypeArguments extends AbstractCodeTransformationTest {
public void testAllFilesPresentInRemoveExplicitTypeArguments() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/removeExplicitTypeArguments"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("fourLiterals.kt")
public void testFourLiterals() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/fourLiterals.kt");
}
@TestMetadata("inapplicableTypeThatIsAFunItCannotBeInferred.kt")
public void testInapplicableTypeThatIsAFunItCannotBeInferred() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/inapplicableTypeThatIsAFunItCannotBeInferred.kt");
}
@TestMetadata("lambdaType.kt")
public void testLambdaType() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/lambdaType.kt");
}
@TestMetadata("literalAny.kt")
public void testLiteralAny() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalAny.kt");
}
@TestMetadata("literalString.kt")
public void testLiteralString() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalString.kt");
}
@TestMetadata("literalStringWithClass.kt")
public void testLiteralStringWithClass() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalStringWithClass.kt");
}
@TestMetadata("literalsWhenTypeArgHasTypeArg.kt")
public void testLiteralsWhenTypeArgHasTypeArg() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/literalsWhenTypeArgHasTypeArg.kt");
}
@TestMetadata("notApplicableNotEnoughtInfo.kt")
public void testNotApplicableNotEnoughtInfo() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableNotEnoughtInfo.kt");
}
@TestMetadata("notApplicableSupertypeOfInferred.kt")
public void testNotApplicableSupertypeOfInferred() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableSupertypeOfInferred.kt");
}
@TestMetadata("notApplicableSupertypeOfInferredClass.kt")
public void testNotApplicableSupertypeOfInferredClass() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/notApplicableSupertypeOfInferredClass.kt");
}
@TestMetadata("twoLiteralValues.kt")
public void testTwoLiteralValues() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/twoLiteralValues.kt");
}
@TestMetadata("variableString.kt")
public void testVariableString() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/variableString.kt");
}
@TestMetadata("variableString2.kt")
public void testVariableString2() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/variableString2.kt");
}
@TestMetadata("variableStringFartherScope.kt")
public void testVariableStringFartherScope() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/variableStringFartherScope.kt");
}
@TestMetadata("variablesAndLiterals.kt")
public void testVariablesAndLiterals() throws Exception {
doTestRemoveExplicitTypeArguments("idea/testData/intentions/removeExplicitTypeArguments/variablesAndLiterals.kt");
}
}
public static Test suite() {
TestSuite suite = new TestSuite("CodeTransformationTestGenerated");
suite.addTestSuite(ElvisToIfThen.class);
@@ -3478,6 +3561,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
suite.addTestSuite(ReplaceWithTraditionalAssignment.class);
suite.addTestSuite(SimplifyBooleanWithConstants.class);
suite.addTestSuite(InsertExplicitTypeArguments.class);
suite.addTestSuite(RemoveExplicitTypeArguments.class);
return suite;
}
}