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);
|
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")
|
@TestMetadata("ImplicitlyTypedValInitializer1.kt")
|
||||||
public void testImplicitlyTypedValInitializer1() throws Exception {
|
public void testImplicitlyTypedValInitializer1() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ImplicitlyTypedValInitializer1.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ImplicitlyTypedValInitializer1.kt");
|
||||||
|
|||||||
@@ -527,10 +527,11 @@ class ExpectedInfos(
|
|||||||
if (expressionWithType != property.initializer) return null
|
if (expressionWithType != property.initializer) return null
|
||||||
val propertyDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptor ?: return null
|
val propertyDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptor ?: return null
|
||||||
val expectedName = propertyDescriptor.name.asString()
|
val expectedName = propertyDescriptor.name.asString()
|
||||||
val expectedInfo = if (property.typeReference != null)
|
val returnTypeToUse = returnTypeToUse(propertyDescriptor, hasExplicitReturnType = property.typeReference != null)
|
||||||
ExpectedInfo(propertyDescriptor.type, expectedName, null)
|
val expectedInfo = if (returnTypeToUse != null)
|
||||||
|
ExpectedInfo(returnTypeToUse, expectedName, null)
|
||||||
else
|
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)
|
return listOf(expectedInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,33 +539,38 @@ class ExpectedInfos(
|
|||||||
val declaration = expressionWithType.parent as? KtDeclarationWithBody ?: return null
|
val declaration = expressionWithType.parent as? KtDeclarationWithBody ?: return null
|
||||||
if (expressionWithType != declaration.bodyExpression || declaration.hasBlockBody()) return null
|
if (expressionWithType != declaration.bodyExpression || declaration.hasBlockBody()) return null
|
||||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] as? FunctionDescriptor ?: 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>? {
|
private fun calculateForReturn(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||||
val returnExpression = expressionWithType.parent as? KtReturnExpression ?: return null
|
val returnExpression = expressionWithType.parent as? KtReturnExpression ?: return null
|
||||||
val descriptor = returnExpression.getTargetFunctionDescriptor(bindingContext) ?: 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) {
|
return when (descriptor) {
|
||||||
is SimpleFunctionDescriptor -> {
|
is SimpleFunctionDescriptor -> {
|
||||||
val expectedType = if (expectType) descriptor.returnType else null
|
ExpectedInfo.createForReturnValue(returnTypeToUse(descriptor, hasExplicitReturnType), descriptor)
|
||||||
ExpectedInfo.createForReturnValue(expectedType, descriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is PropertyGetterDescriptor -> {
|
is PropertyGetterDescriptor -> {
|
||||||
if (descriptor !is PropertyGetterDescriptor) return null
|
if (descriptor !is PropertyGetterDescriptor) return null
|
||||||
val property = descriptor.correspondingProperty
|
val property = descriptor.correspondingProperty
|
||||||
val expectedType = if (expectType) property.type else null
|
ExpectedInfo.createForReturnValue(returnTypeToUse(property, hasExplicitReturnType), property)
|
||||||
ExpectedInfo.createForReturnValue(expectedType, property)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
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>? {
|
private fun calculateForLoopRange(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||||
val forExpression = (expressionWithType.parent as? KtContainerNode)
|
val forExpression = (expressionWithType.parent as? KtContainerNode)
|
||||||
?.parent as? KtForExpression ?: return null
|
?.parent as? KtForExpression ?: return null
|
||||||
|
|||||||
Reference in New Issue
Block a user