Specify type: do not suggest nullable type if not null is overridden
So #KT-12814 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
50eaca1ac4
commit
817dadc120
@@ -18,8 +18,10 @@ package org.jetbrains.kotlin.idea.intentions
|
|||||||
|
|
||||||
import com.intellij.codeInsight.intention.LowPriorityAction
|
import com.intellij.codeInsight.intention.LowPriorityAction
|
||||||
import com.intellij.codeInsight.template.*
|
import com.intellij.codeInsight.template.*
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
@@ -35,12 +37,10 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
|||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.idea.util.getResolvableApproximations
|
import org.jetbrains.kotlin.idea.util.getResolvableApproximations
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.utils.ifEmpty
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
|
|
||||||
class SpecifyTypeExplicitlyIntention :
|
class SpecifyTypeExplicitlyIntention :
|
||||||
@@ -102,7 +102,12 @@ class SpecifyTypeExplicitlyIntention :
|
|||||||
|
|
||||||
fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType {
|
fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType {
|
||||||
val descriptor = declaration.resolveToDescriptorIfAny()
|
val descriptor = declaration.resolveToDescriptorIfAny()
|
||||||
val type = (descriptor as? CallableDescriptor)?.returnType
|
val type = (descriptor as? CallableDescriptor)?.let {
|
||||||
|
if (it.overriddenDescriptors.firstOrNull()?.returnType?.isMarkedNullable == false)
|
||||||
|
it.returnType?.makeNotNullable()
|
||||||
|
else
|
||||||
|
it.returnType
|
||||||
|
}
|
||||||
if (type != null && type.isError && descriptor is PropertyDescriptor) {
|
if (type != null && type.isError && descriptor is PropertyDescriptor) {
|
||||||
return descriptor.setterType ?: ErrorUtils.createErrorType("null type")
|
return descriptor.setterType ?: ErrorUtils.createErrorType("null type")
|
||||||
}
|
}
|
||||||
@@ -132,6 +137,16 @@ class SpecifyTypeExplicitlyIntention :
|
|||||||
}
|
}
|
||||||
}.ifEmpty { return null }
|
}.ifEmpty { return null }
|
||||||
|
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
|
// This helps to be sure no nullable types are suggested
|
||||||
|
if (contextElement.containingKtFile.findDescendantOfType<PsiComment>()?.takeIf {
|
||||||
|
it.text == "// CHOOSE_NULLABLE_TYPE_IF_EXISTS"
|
||||||
|
} != null) {
|
||||||
|
val targetType = types.firstOrNull { it.isMarkedNullable } ?: types.first()
|
||||||
|
return TypeChooseValueExpression(listOf(targetType), targetType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TypeChooseValueExpression(types, types.first())
|
return TypeChooseValueExpression(types, types.first())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
fun notNullFun(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override fun notNullFun()<caret> = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
fun notNullFun(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override fun notNullFun(): String = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
val notNull: String
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override val notNull<caret> = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
val notNull: String
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override val notNull: String = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
fun nullableFun(): String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override fun nullableFun()<caret> = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
fun nullableFun(): String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override fun nullableFun(): String? = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
val nullable: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override val nullable<caret> = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// CHOOSE_NULLABLE_TYPE_IF_EXISTS
|
||||||
|
// WITH_RUNTIME
|
||||||
|
interface Base {
|
||||||
|
val nullable: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tesst : Base {
|
||||||
|
override val nullable: String? = java.lang.String.valueOf("")
|
||||||
|
}
|
||||||
@@ -14663,6 +14663,30 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideNotNullFunction.kt")
|
||||||
|
public void testOverrideNotNullFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/overrideNotNullFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideNotNullProperty.kt")
|
||||||
|
public void testOverrideNotNullProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/overrideNotNullProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideNullableFunction.kt")
|
||||||
|
public void testOverrideNullableFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/overrideNullableFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideNullableProperty.kt")
|
||||||
|
public void testOverrideNullableProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/overrideNullableProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyTypeFromGetter.kt")
|
@TestMetadata("propertyTypeFromGetter.kt")
|
||||||
public void testPropertyTypeFromGetter() throws Exception {
|
public void testPropertyTypeFromGetter() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/propertyTypeFromGetter.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/propertyTypeFromGetter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user