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.template.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
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.getResolvableApproximations
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
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.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
|
||||
class SpecifyTypeExplicitlyIntention :
|
||||
@@ -102,7 +102,12 @@ class SpecifyTypeExplicitlyIntention :
|
||||
|
||||
fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType {
|
||||
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) {
|
||||
return descriptor.setterType ?: ErrorUtils.createErrorType("null type")
|
||||
}
|
||||
@@ -132,6 +137,16 @@ class SpecifyTypeExplicitlyIntention :
|
||||
}
|
||||
}.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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testPropertyTypeFromGetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/propertyTypeFromGetter.kt");
|
||||
|
||||
Reference in New Issue
Block a user