Create from Usage: Support array access expressions/binary expressions with type mismatch errors

#KT-14501 Fixed
This commit is contained in:
Alexey Sedunov
2016-11-02 15:34:20 +03:00
parent 0159ddbc49
commit e8b5387384
12 changed files with 134 additions and 12 deletions
+1
View File
@@ -223,6 +223,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
#### Intention actions, inspections and quickfixes
- [`KT-14569`](https://youtrack.jetbrains.com/issue/KT-14569) Convert Property to Function Intention: Search occurrences using progress dialog
- [`KT-14501`](https://youtrack.jetbrains.com/issue/KT-14501) Create from Usage: Support array access expressions/binary expressions with type mismatch errors
#### Refactorings
@@ -296,6 +296,7 @@ class QuickFixRegistrar : QuickFixContributor {
NONE_APPLICABLE.registerFactory(CreateBinaryOperationActionFactory)
NO_VALUE_FOR_PARAMETER.registerFactory(CreateBinaryOperationActionFactory)
TOO_MANY_ARGUMENTS.registerFactory(CreateBinaryOperationActionFactory)
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateBinaryOperationActionFactory) }
UNRESOLVED_REFERENCE_WRONG_RECEIVER.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
UNRESOLVED_REFERENCE.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
@@ -340,7 +341,9 @@ class QuickFixRegistrar : QuickFixContributor {
MANY_CLASSES_IN_SUPERTYPE_LIST.registerFactory(RemoveSupertypeFix)
NO_GET_METHOD.registerFactory(CreateGetFunctionActionFactory)
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateGetFunctionActionFactory) }
NO_SET_METHOD.registerFactory(CreateSetFunctionActionFactory)
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateSetFunctionActionFactory) }
HAS_NEXT_MISSING.registerFactory(CreateHasNextFunctionActionFactory)
HAS_NEXT_FUNCTION_NONE_APPLICABLE.registerFactory(CreateHasNextFunctionActionFactory)
NEXT_MISSING.registerFactory(CreateNextFunctionActionFactory)
@@ -17,20 +17,15 @@
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.FunctionInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.types.Variance
import java.util.Collections
object CreateGetFunctionActionFactory : CreateCallableMemberFromUsageFactory<KtArrayAccessExpression>() {
override fun getElementOfInterest(diagnostic: Diagnostic): KtArrayAccessExpression? {
return QuickFixUtil.getParentElementOfType(diagnostic, KtArrayAccessExpression::class.java)
}
import java.util.*
object CreateGetFunctionActionFactory : CreateGetSetFunctionActionFactory(isGet = true) {
override fun createCallableInfo(element: KtArrayAccessExpression, diagnostic: Diagnostic): CallableInfo? {
val arrayExpr = element.arrayExpression ?: return null
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2016 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.kotlin.idea.quickfix.createFromUsage.createCallable
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtContainerNode
import org.jetbrains.kotlin.psi.KtPsiUtil
abstract class CreateGetSetFunctionActionFactory(private val isGet: Boolean) : CreateCallableMemberFromUsageFactory<KtArrayAccessExpression>() {
override fun getElementOfInterest(diagnostic: Diagnostic): KtArrayAccessExpression? {
return when (diagnostic.factory) {
Errors.NO_GET_METHOD -> if (isGet) Errors.NO_GET_METHOD.cast(diagnostic).psiElement else null
Errors.NO_SET_METHOD -> if (!isGet) Errors.NO_SET_METHOD.cast(diagnostic).psiElement else null
in Errors.TYPE_MISMATCH_ERRORS -> {
val indicesNode = diagnostic.psiElement.parent as? KtContainerNode ?: return null
if (indicesNode.node.elementType != KtNodeTypes.INDICES) return null
val arrayAccess = indicesNode.parent as? KtArrayAccessExpression ?: return null
val parent = arrayAccess.parent
val isAssignmentLHS = KtPsiUtil.isAssignment(parent) && (parent as KtBinaryExpression).left == arrayAccess
if (isAssignmentLHS == isGet) return null
arrayAccess
}
else -> throw IllegalArgumentException("Unexpected diagnostic: ${diagnostic.factory.name}")
}
}
}
@@ -34,11 +34,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import java.util.*
object CreateSetFunctionActionFactory : CreateCallableMemberFromUsageFactory<KtArrayAccessExpression>() {
override fun getElementOfInterest(diagnostic: Diagnostic): KtArrayAccessExpression? {
return QuickFixUtil.getParentElementOfType(diagnostic, KtArrayAccessExpression::class.java)
}
object CreateSetFunctionActionFactory : CreateGetSetFunctionActionFactory(isGet = false) {
override fun createCallableInfo(element: KtArrayAccessExpression, diagnostic: Diagnostic): CallableInfo? {
val arrayExpr = element.arrayExpression ?: return null
val arrayType = TypeInfo(arrayExpr, Variance.IN_VARIANCE)
@@ -0,0 +1,8 @@
// "Create extension function 'A.times'" "true"
class A
operator fun A.times(i: Int) = this
fun test() {
A() * <caret>"1"
}
@@ -0,0 +1,12 @@
// "Create extension function 'A.times'" "true"
class A
operator fun A.times(i: Int) = this
fun test() {
A() * "1"
}
private infix operator fun A.times(s: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,8 @@
// "Create extension function 'A.get'" "true"
class A
fun A.get(i: Int) = this
fun test() {
A()[<caret>"1"]
}
@@ -0,0 +1,12 @@
// "Create extension function 'A.get'" "true"
class A
fun A.get(i: Int) = this
fun test() {
A()["1"]
}
private operator fun A.get(s: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,10 @@
// "Create extension function 'A.set'" "true"
class A
fun A.set(i: Int, j: Int) {
}
fun test() {
A()[<caret>"1"] = 2
}
@@ -0,0 +1,14 @@
// "Create extension function 'A.set'" "true"
class A
fun A.set(i: Int, j: Int) {
}
fun test() {
A()["1"] = 2
}
private operator fun A.set(s: String, value: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -2074,6 +2074,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName);
}
@TestMetadata("typeMismatch.kt")
public void testTypeMismatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/binaryOperations/typeMismatch.kt");
doTest(fileName);
}
@TestMetadata("whenInOnUserType.kt")
public void testWhenInOnUserType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/binaryOperations/whenInOnUserType.kt");
@@ -2769,6 +2775,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/get/createGetFromUsage9.kt");
doTest(fileName);
}
@TestMetadata("typeMismatch.kt")
public void testTypeMismatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/get/typeMismatch.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/hasNext")
@@ -2898,6 +2910,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/set/setterForIncrement.kt");
doTest(fileName);
}
@TestMetadata("typeMismatch.kt")
public void testTypeMismatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/set/typeMismatch.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/unaryOperations")