Create from Usage: Use function form when rendering FunctionN types
#KT-7522 Fixed
This commit is contained in:
+31
-16
@@ -19,18 +19,18 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
|
||||
import com.intellij.refactoring.psi.SearchUtils
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
||||
@@ -44,21 +44,36 @@ internal fun JetType.contains(inner: JetType): Boolean {
|
||||
return JetTypeChecker.DEFAULT.equalTypes(this, inner) || getArguments().any { inner in it.getType() }
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.render(
|
||||
typeParameterNameMap: Map<TypeParameterDescriptor, String>,
|
||||
fq: Boolean
|
||||
): String = when {
|
||||
this is TypeParameterDescriptor -> typeParameterNameMap[this] ?: getName().asString()
|
||||
fq -> DescriptorUtils.getFqName(this).asString()
|
||||
else -> getName().asString()
|
||||
}
|
||||
|
||||
private fun JetType.render(typeParameterNameMap: Map<TypeParameterDescriptor, String>, fq: Boolean): String {
|
||||
val arguments = getArguments().map { if (it.isStarProjection) "*" else it.getType().render(typeParameterNameMap, fq) }
|
||||
val typeString = getConstructor().getDeclarationDescriptor()!!.render(typeParameterNameMap, fq)
|
||||
val typeArgumentString = if (arguments.isNotEmpty()) arguments.joinToString(", ", "<", ">") else ""
|
||||
val nullifier = if (isMarkedNullable()) "?" else ""
|
||||
return "$typeString$typeArgumentString$nullifier"
|
||||
val substitution = typeParameterNameMap
|
||||
.mapValues {
|
||||
val name = Name.identifier(it.value)
|
||||
|
||||
val typeParameter = it.key
|
||||
|
||||
var wrappingTypeParameter: TypeParameterDescriptor
|
||||
var wrappingTypeConstructor: TypeConstructor
|
||||
|
||||
wrappingTypeParameter = object : TypeParameterDescriptor by typeParameter {
|
||||
override fun getName() = name
|
||||
override fun getTypeConstructor() = wrappingTypeConstructor
|
||||
}
|
||||
|
||||
wrappingTypeConstructor = object : TypeConstructor by typeParameter.typeConstructor {
|
||||
override fun getDeclarationDescriptor() = wrappingTypeParameter
|
||||
}
|
||||
|
||||
val wrappingType = object : JetType by typeParameter.defaultType {
|
||||
override fun getConstructor() = wrappingTypeConstructor
|
||||
}
|
||||
|
||||
TypeProjectionImpl(wrappingType)
|
||||
}
|
||||
.mapKeys { it.key.typeConstructor }
|
||||
|
||||
val typeToRender = TypeSubstitutor.create(substitution).substitute(this, Variance.INVARIANT)!!
|
||||
val renderer = if (fq) IdeDescriptorRenderers.SOURCE_CODE else IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES
|
||||
return renderer.renderType(typeToRender)
|
||||
}
|
||||
|
||||
internal fun JetType.renderShort(typeParameterNameMap: Map<TypeParameterDescriptor, String>) = render(typeParameterNameMap, false)
|
||||
|
||||
Vendored
+1
-1
@@ -4,6 +4,6 @@ fun test() {
|
||||
val a = Foo(2, "2") { p: Int -> p + 1 }
|
||||
}
|
||||
|
||||
class Foo(i: Int, s: String, function: Function1<Int, Int>) {
|
||||
class Foo(i: Int, s: String, function: (Int) -> Int) {
|
||||
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -4,6 +4,6 @@ fun test() {
|
||||
val a = Foo { p: Int -> p + 1 }
|
||||
}
|
||||
|
||||
class Foo(function: Function1<Int, Int>) {
|
||||
class Foo(function: (Int) -> Int) {
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// "Create member function 'foo'" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun foo(t: T, s: String, function: Function1<T, T>): A<T> {
|
||||
fun foo(t: T, s: String, function: (T) -> T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// "Create member function 'foo'" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun foo(function: Function1<T, T>): A<T> {
|
||||
fun foo(function: (T) -> T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// "Create function 'bar'" "true"
|
||||
|
||||
fun foo(block: (Int) -> String) {
|
||||
<caret>bar(block)
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Create function 'bar'" "true"
|
||||
|
||||
fun foo(block: (Int) -> String) {
|
||||
bar(block)
|
||||
}
|
||||
|
||||
fun bar(block: (Int) -> String) {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
@@ -1784,6 +1784,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionalType.kt")
|
||||
public void testFunctionalType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/functionalType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inLambda.kt")
|
||||
public void testInLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/inLambda.kt");
|
||||
|
||||
Reference in New Issue
Block a user