Use parameter names from function type for invoke() function

#KT-435 Fixed
 #KT-9016 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-09-13 22:02:59 +03:00
parent 0abb2edb2b
commit 6b94e5fd34
9 changed files with 82 additions and 12 deletions
@@ -4,6 +4,6 @@ public final class A : (categoryName: [ERROR : No type element]) -> [ERROR : No
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: [ERROR : No type element]): [ERROR : No type element]
public abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ categoryName: [ERROR : No type element]): [ERROR : No type element]
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -6,7 +6,7 @@ package typeReferenceError {
public constructor Pair()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: [ERROR : No type element]): [ERROR : main]
public abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ c: [ERROR : No type element]): [ERROR : main]
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
+7
View File
@@ -0,0 +1,7 @@
fun Any.foo1() : (i : Int) -> Unit {
return {}
}
fun test(a : Any) {
a.foo1()(<!NO_VALUE_FOR_PARAMETER(i)!>)<!>
}
+4
View File
@@ -0,0 +1,4 @@
package
public fun test(/*0*/ a: kotlin.Any): kotlin.Unit
public fun kotlin.Any.foo1(): (i: kotlin.Int) -> kotlin.Unit
@@ -367,6 +367,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("kt435.kt")
public void testKt435() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/kt435.kt");
doTest(fileName);
}
@TestMetadata("kt53.kt")
public void testKt53() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/kt53.kt");
@@ -23,23 +23,29 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
class FunctionInvokeDescriptor private constructor(
container: DeclarationDescriptor,
original: FunctionInvokeDescriptor?,
callableKind: CallableMemberDescriptor.Kind
callableKind: CallableMemberDescriptor.Kind,
private val hasSynthesizedParameterNames: Boolean
) : SimpleFunctionDescriptorImpl(
container,
original,
Annotations.EMPTY,
Name.identifier("invoke"),
OperatorNameConventions.INVOKE,
callableKind,
SourceElement.NO_SOURCE
) {
init {
this.isOperator = true
}
// "p0", "p1", etc. should not be baked into the language
override fun hasStableParameterNames(): Boolean = false
override fun hasSynthesizedParameterNames(): Boolean = true
override fun hasSynthesizedParameterNames(): Boolean = hasSynthesizedParameterNames
override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor,
@@ -49,7 +55,7 @@ class FunctionInvokeDescriptor private constructor(
annotations: Annotations,
source: SourceElement
): FunctionDescriptorImpl {
return FunctionInvokeDescriptor(newOwner, original as FunctionInvokeDescriptor?, kind)
return FunctionInvokeDescriptor(newOwner, original as FunctionInvokeDescriptor?, kind, hasSynthesizedParameterNames)
}
override fun isExternal(): Boolean = false
@@ -58,11 +64,33 @@ class FunctionInvokeDescriptor private constructor(
override fun isTailrec(): Boolean = false
fun replaceParameterNames(parameterNames: List<Name>): FunctionInvokeDescriptor {
val indexShift = valueParameters.size - parameterNames.size
assert(indexShift == 0 || indexShift == 1) // indexShift == 1 for extension function type
val hasSynthesizedParameterNames = parameterNames.any { it.isSpecial }
val newDescriptor = FunctionInvokeDescriptor(containingDeclaration, this, kind, hasSynthesizedParameterNames)
val newValueParameters = valueParameters.map {
var newName = it.name
val parameterIndex = it.index
val nameIndex = parameterIndex - indexShift
if (nameIndex >= 0) {
val parameterName = parameterNames[nameIndex]
if (!parameterName.isSpecial) {
newName = parameterName
}
}
it.copy(newDescriptor, newName, parameterIndex)
}
newDescriptor.initialize(extensionReceiverParameterType, dispatchReceiverParameter, typeParameters, newValueParameters, returnType, modality, visibility)
return newDescriptor
}
companion object Factory {
fun create(functionClass: FunctionClassDescriptor): FunctionInvokeDescriptor {
val typeParameters = functionClass.declaredTypeParameters
val result = FunctionInvokeDescriptor(functionClass, null, CallableMemberDescriptor.Kind.DECLARATION)
val result = FunctionInvokeDescriptor(functionClass, null, CallableMemberDescriptor.Kind.DECLARATION, hasSynthesizedParameterNames = true)
result.initialize(
null,
functionClass.thisAsReceiverParameter,
@@ -74,7 +102,6 @@ class FunctionInvokeDescriptor private constructor(
Modality.ABSTRACT,
Visibilities.PUBLIC
)
result.isOperator = true
return result
}
@@ -16,10 +16,16 @@
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
import java.util.*
abstract class DelegatingSimpleType : SimpleType() {
protected abstract val delegate: SimpleType
@@ -57,6 +63,28 @@ class FunctionType(
*/
val parameterNames: List<Name>
) : DelegatingSimpleType() {
override val memberScope = object: MemberScope by delegate.memberScope {
private val cache = HashMap<FunctionInvokeDescriptor, FunctionInvokeDescriptor>(2)
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
return delegate.memberScope.getContributedFunctions(name, location).replaceParameterNames()
}
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
return delegate.memberScope.getContributedDescriptors(kindFilter, nameFilter).replaceParameterNames()
}
private fun <TDescriptor : DeclarationDescriptor> Collection<TDescriptor>.replaceParameterNames(): List<TDescriptor>
= map { it.replaceParameterNames() }
private fun <TDescriptor : DeclarationDescriptor> TDescriptor.replaceParameterNames(): TDescriptor {
if (this !is FunctionInvokeDescriptor) return this
@Suppress("UNCHECKED_CAST")
return cache.getOrPut(this) { this.replaceParameterNames(parameterNames) } as TDescriptor
}
}
override fun replaceAnnotations(newAnnotations: Annotations)
= FunctionType(delegate.replaceAnnotations(newAnnotations), parameterNames)
@@ -2,7 +2,6 @@ fun x(name: String, next: (name: String) -> String): String {
return next(<caret>)
}
//TODO: use parameter names from functional type
/*
Text: (<highlight>String</highlight>), Disabled: false, Strikeout: false, Green: true
Text: (<highlight>name: String</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -5,8 +5,7 @@ fun call() {
header(<caret>"sdf", "sdjfn")
}
//TODO: use parameter names from functional type
/*
Text: (<highlight>String</highlight>, String), Disabled: false, Strikeout: false, Green: true
Text: (<highlight>name: String</highlight>, value: Int), Disabled: false, Strikeout: false, Green: false
Text: (<highlight>s: String</highlight>, s1: String), Disabled: false, Strikeout: false, Green: true
*/