Show substituted type arguments for type instantiation items
This commit is contained in:
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -49,6 +50,26 @@ fun FuzzyType.isAlmostEverything(): Boolean {
|
|||||||
return typeParameter.upperBounds.singleOrNull()?.isAnyOrNullableAny() ?: false
|
return typeParameter.upperBounds.singleOrNull()?.isAnyOrNullableAny() ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces free parameters inside the type with corresponding type parameters of the class (when possible)
|
||||||
|
*/
|
||||||
|
fun FuzzyType.presentationType(): KotlinType {
|
||||||
|
if (freeParameters.isEmpty()) return type
|
||||||
|
|
||||||
|
val map = HashMap<TypeConstructor, TypeProjection>()
|
||||||
|
for ((argument, typeParameter) in type.arguments.zip(type.constructor.parameters)) {
|
||||||
|
if (argument.projectionKind == Variance.INVARIANT) {
|
||||||
|
val equalToFreeParameter = freeParameters.firstOrNull {
|
||||||
|
KotlinTypeChecker.FLEXIBLE_UNEQUAL_TO_INFLEXIBLE.equalTypes(it.defaultType, argument.type)
|
||||||
|
} ?: continue
|
||||||
|
|
||||||
|
map[equalToFreeParameter.typeConstructor] = createProjection(typeParameter.defaultType, Variance.INVARIANT, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val substitutor = TypeSubstitutor.create(map)
|
||||||
|
return substitutor.substitute(type, Variance.INVARIANT)!!
|
||||||
|
}
|
||||||
|
|
||||||
class FuzzyType(
|
class FuzzyType(
|
||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
freeParameters: Collection<TypeParameterDescriptor>
|
freeParameters: Collection<TypeParameterDescriptor>
|
||||||
|
|||||||
+9
-1
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
|||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
||||||
|
import org.jetbrains.kotlin.idea.util.presentationType
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
@@ -208,7 +209,14 @@ class TypeInstantiationItems(
|
|||||||
//TODO: when constructor has one parameter of lambda type with more than one parameter, generate special additional item
|
//TODO: when constructor has one parameter of lambda type with more than one parameter, generate special additional item
|
||||||
signatureText = when (visibleConstructors.size) {
|
signatureText = when (visibleConstructors.size) {
|
||||||
0 -> "()"
|
0 -> "()"
|
||||||
1 -> DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(visibleConstructors.single())
|
|
||||||
|
1 -> {
|
||||||
|
val constructor = visibleConstructors.single()
|
||||||
|
val substitutor = TypeSubstitutor.create(fuzzyType.presentationType())
|
||||||
|
val substitutedConstructor = constructor.substitute(substitutor)
|
||||||
|
DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(substitutedConstructor)
|
||||||
|
}
|
||||||
|
|
||||||
else -> "(...)"
|
else -> "(...)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class Foo<T>
|
class Foo<T>(t: T)
|
||||||
|
|
||||||
fun foo(p : Any){
|
fun foo(p : Any){
|
||||||
var a : Foo<String> = <caret>
|
var a : Foo<String> = <caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText:"() (<root>)" }
|
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText:"(t: String) (<root>)" }
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ interface I<T>
|
|||||||
abstract class C1<T> : I<T>
|
abstract class C1<T> : I<T>
|
||||||
abstract class C2 : I<String>
|
abstract class C2 : I<String>
|
||||||
abstract class C3 : I<Int>
|
abstract class C3 : I<Int>
|
||||||
|
class C4<T>(t: T) : I<T>
|
||||||
|
class C5<T1, T2>(t1: T1, t2: T2) : I<T2>
|
||||||
|
|
||||||
fun foo(i: I<Int>){}
|
fun foo(i: I<Int>){}
|
||||||
|
|
||||||
@@ -13,4 +15,6 @@ fun bar() {
|
|||||||
// EXIST: { itemText: "object: I<Int>{...}" }
|
// EXIST: { itemText: "object: I<Int>{...}" }
|
||||||
// EXIST: { itemText: "object: C1<Int>(){...}" }
|
// EXIST: { itemText: "object: C1<Int>(){...}" }
|
||||||
// EXIST: { itemText: "object: C3(){...}" }
|
// EXIST: { itemText: "object: C3(){...}" }
|
||||||
|
// EXIST: { itemText: "C4", tailText: "(t: Int) (<root>)" }
|
||||||
|
// EXIST: { itemText: "C5", tailText: "(t1: T1, t2: Int) (<root>)" }
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
+1
-1
@@ -13,4 +13,4 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { itemText: "createProperty", typeText: "Property<C, TValue>" }
|
// EXIST: { itemText: "createProperty", typeText: "Property<C, TValue>" }
|
||||||
// EXIST: Property
|
// EXIST: { itemText: "Property", tailText: "(owner: C, value: TValue) (<root>)" }
|
||||||
|
|||||||
+3
-3
@@ -1,16 +1,16 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Property<TOwner, TValue>
|
class Property<TOwner, TValue>(owner: TOwner, value: TValue)
|
||||||
|
|
||||||
operator fun <TValue, TOwner> Property<TOwner, TValue>.getValue(thisRef: TOwner, property: KProperty<*>): TValue {
|
operator fun <TValue, TOwner> Property<TOwner, TValue>.getValue(thisRef: TOwner, property: KProperty<*>): TValue {
|
||||||
throw Exception()
|
throw Exception()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun<TOwner, TValue> createProperty(): Property<TOwner, TValue> = Property()
|
fun<TOwner, TValue> createProperty(owner: TOwner, value: TValue): Property<TOwner, TValue> = Property(owner, value)
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
val v: Int by <caret>
|
val v: Int by <caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { itemText: "createProperty", typeText: "Property<C, Int>" }
|
// EXIST: { itemText: "createProperty", typeText: "Property<C, Int>" }
|
||||||
// EXIST: Property
|
// EXIST: { itemText: "Property", tailText: "(owner: C, value: Int) (<root>)" }
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Property<TOwner1, TValue1>
|
class Property<TOwner1, TValue1>(owner: TOwner1, value: TValue1)
|
||||||
|
|
||||||
operator fun <TValue2, TOwner2> Property<TOwner2, TValue2>.getValue(thisRef: TOwner2, property: KProperty<*>): TValue2 {
|
operator fun <TValue2, TOwner2> Property<TOwner2, TValue2>.getValue(thisRef: TOwner2, property: KProperty<*>): TValue2 {
|
||||||
throw Exception()
|
throw Exception()
|
||||||
@@ -10,11 +10,11 @@ operator fun <TValue3, TOwner3> Property<TOwner3, TValue3>.setValue(thisRef: TOw
|
|||||||
throw Exception()
|
throw Exception()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun<TOwner4, TValue4> createProperty(): Property<TOwner4, TValue4> = Property()
|
fun<TOwner4, TValue4> createProperty(owner: TOwner4, value: TValue4): Property<TOwner4, TValue4> = Property(owner, value)
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
var v by <caret>
|
var v by <caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { itemText: "createProperty", typeText: "Property<C, TValue4>" }
|
// EXIST: { itemText: "createProperty", typeText: "Property<C, TValue4>" }
|
||||||
// EXIST: Property
|
// EXIST: { itemText: "Property", tailText: "(owner: C, value: TValue1) (<root>)" }
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Property<TOwner1, TValue1>
|
class Property<TOwner1, TValue1>(owner: TOwner1, value: TValue1)
|
||||||
|
|
||||||
operator fun <TValue2, TOwner2> Property<TOwner2, TValue2>.getValue(thisRef: TOwner2, property: KProperty<*>): TValue2 {
|
operator fun <TValue2, TOwner2> Property<TOwner2, TValue2>.getValue(thisRef: TOwner2, property: KProperty<*>): TValue2 {
|
||||||
throw Exception()
|
throw Exception()
|
||||||
@@ -10,11 +10,11 @@ operator fun <TValue3, TOwner3> Property<TOwner3, TValue3>.setValue(thisRef: TOw
|
|||||||
throw Exception()
|
throw Exception()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun<TOwner4, TValue4> createProperty(): Property<TOwner4, TValue4> = Property()
|
fun<TOwner4, TValue4> createProperty(owner: TOwner4, value: TValue4): Property<TOwner4, TValue4> = Property(owner, value)
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
var v: Int by <caret>
|
var v: Int by <caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: { itemText: "createProperty", typeText: "Property<C, Int>" }
|
// EXIST: { itemText: "createProperty", typeText: "Property<C, Int>" }
|
||||||
// EXIST: Property
|
// EXIST: { itemText: "Property", tailText: "(owner: C, value: Int) (<root>)" }
|
||||||
|
|||||||
Reference in New Issue
Block a user