Smart completion to use super type for override if no explicit type specified
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
abstract class Base {
|
||||
abstract fun foo(): Int
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
override fun foo() = <caret>
|
||||
}
|
||||
|
||||
fun getInt(): Int = 0
|
||||
fun getString(): String = ""
|
||||
|
||||
// EXIST: getInt
|
||||
// ABSENT: getString
|
||||
@@ -0,0 +1,13 @@
|
||||
abstract class Base {
|
||||
abstract val foo: Int
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
override val foo = <caret>
|
||||
}
|
||||
|
||||
fun getInt(): Int = 0
|
||||
fun getString(): String = ""
|
||||
|
||||
// EXIST: getInt
|
||||
// ABSENT: getString
|
||||
+12
@@ -185,6 +185,18 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplicitlyTypedOverrideFunBody.kt")
|
||||
public void testImplicitlyTypedOverrideFunBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ImplicitlyTypedOverrideFunBody.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplicitlyTypedOverrideValInitializer.kt")
|
||||
public void testImplicitlyTypedOverrideValInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ImplicitlyTypedOverrideValInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplicitlyTypedValInitializer1.kt")
|
||||
public void testImplicitlyTypedValInitializer1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ImplicitlyTypedValInitializer1.kt");
|
||||
|
||||
@@ -527,10 +527,11 @@ class ExpectedInfos(
|
||||
if (expressionWithType != property.initializer) return null
|
||||
val propertyDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptor ?: return null
|
||||
val expectedName = propertyDescriptor.name.asString()
|
||||
val expectedInfo = if (property.typeReference != null)
|
||||
ExpectedInfo(propertyDescriptor.type, expectedName, null)
|
||||
val returnTypeToUse = returnTypeToUse(propertyDescriptor, hasExplicitReturnType = property.typeReference != null)
|
||||
val expectedInfo = if (returnTypeToUse != null)
|
||||
ExpectedInfo(returnTypeToUse, expectedName, null)
|
||||
else
|
||||
ExpectedInfo(ByTypeFilter.All, expectedName, null) // no explicit type - only expected name known
|
||||
ExpectedInfo(ByTypeFilter.All, expectedName, null) // no explicit type or type from base - only expected name known
|
||||
return listOf(expectedInfo)
|
||||
}
|
||||
|
||||
@@ -538,33 +539,38 @@ class ExpectedInfos(
|
||||
val declaration = expressionWithType.parent as? KtDeclarationWithBody ?: return null
|
||||
if (expressionWithType != declaration.bodyExpression || declaration.hasBlockBody()) return null
|
||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] as? FunctionDescriptor ?: return null
|
||||
return functionReturnValueExpectedInfo(descriptor, expectType = declaration.hasDeclaredReturnType()).singletonOrEmptyList()
|
||||
return functionReturnValueExpectedInfo(descriptor, hasExplicitReturnType = declaration.hasDeclaredReturnType()).singletonOrEmptyList()
|
||||
}
|
||||
|
||||
private fun calculateForReturn(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val returnExpression = expressionWithType.parent as? KtReturnExpression ?: return null
|
||||
val descriptor = returnExpression.getTargetFunctionDescriptor(bindingContext) ?: return null
|
||||
return functionReturnValueExpectedInfo(descriptor, expectType = true).singletonOrEmptyList()
|
||||
return functionReturnValueExpectedInfo(descriptor, hasExplicitReturnType = true).singletonOrEmptyList()
|
||||
}
|
||||
|
||||
private fun functionReturnValueExpectedInfo(descriptor: FunctionDescriptor, expectType: Boolean): ExpectedInfo? {
|
||||
private fun functionReturnValueExpectedInfo(descriptor: FunctionDescriptor, hasExplicitReturnType: Boolean): ExpectedInfo? {
|
||||
return when (descriptor) {
|
||||
is SimpleFunctionDescriptor -> {
|
||||
val expectedType = if (expectType) descriptor.returnType else null
|
||||
ExpectedInfo.createForReturnValue(expectedType, descriptor)
|
||||
ExpectedInfo.createForReturnValue(returnTypeToUse(descriptor, hasExplicitReturnType), descriptor)
|
||||
}
|
||||
|
||||
is PropertyGetterDescriptor -> {
|
||||
if (descriptor !is PropertyGetterDescriptor) return null
|
||||
val property = descriptor.correspondingProperty
|
||||
val expectedType = if (expectType) property.type else null
|
||||
ExpectedInfo.createForReturnValue(expectedType, property)
|
||||
ExpectedInfo.createForReturnValue(returnTypeToUse(property, hasExplicitReturnType), property)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun returnTypeToUse(descriptor: CallableDescriptor, hasExplicitReturnType: Boolean): KotlinType? {
|
||||
return if (hasExplicitReturnType)
|
||||
descriptor.returnType
|
||||
else
|
||||
descriptor.overriddenDescriptors.singleOrNull()?.returnType
|
||||
}
|
||||
|
||||
private fun calculateForLoopRange(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val forExpression = (expressionWithType.parent as? KtContainerNode)
|
||||
?.parent as? KtForExpression ?: return null
|
||||
|
||||
Reference in New Issue
Block a user