From 977bf593e0849486d6b04f5fb699d956334734ff Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 24 Jul 2015 21:21:52 +0300 Subject: [PATCH] KT-8574 'Convert to block body' inserts spurious < token #KT-8574 Fixed --- .../idea/util/IdeDescriptorRenderers.kt | 23 +++++++++++++++--- .../extractableAnalysisUtil.kt | 8 +++++-- .../valueIsAnonymousObject.kt | 1 + .../valueIsAnonymousObject.kt.after | 3 +++ .../valueIsAnonymousObject2.kt | 3 +++ .../valueIsAnonymousObject2.kt.after | 5 ++++ .../valueIsAnonymousObject3.kt | 6 +++++ .../valueIsAnonymousObject3.kt.after | 8 +++++++ .../valueIsAnonymousObject4.kt | 5 ++++ .../valueIsAnonymousObject4.kt.after | 7 ++++++ .../intentions/IntentionTestGenerated.java | 24 +++++++++++++++++++ 11 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt.after create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt.after create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt.after create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt create mode 100644 idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt.after diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/IdeDescriptorRenderers.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/IdeDescriptorRenderers.kt index b7a52668a38..e7d5ebb3f1e 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/IdeDescriptorRenderers.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/IdeDescriptorRenderers.kt @@ -16,17 +16,34 @@ package org.jetbrains.kotlin.idea.util +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererModifier import org.jetbrains.kotlin.renderer.NameShortness import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.types.isDynamic public object IdeDescriptorRenderers { public val APPROXIMATE_FLEXIBLE_TYPES: (JetType) -> JetType = { approximateFlexibleTypes(it, true) } public val APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS: (JetType) -> JetType = { approximateFlexibleTypes(it, false) } + private fun unwrapAnonymousType(type: JetType): JetType { + if (type.isDynamic()) return type + + val classifier = type.constructor.declarationDescriptor + if (classifier != null && !classifier.name.isSpecial) return type + + type.constructor.supertypes.singleOrNull()?.let { return it } + + val builtIns = KotlinBuiltIns.getInstance() + return if (type.isMarkedNullable) + builtIns.nullableAnyType + else + builtIns.anyType + } + private val BASE: DescriptorRenderer = DescriptorRenderer.withOptions { normalizedVisibilities = true withDefinedIn = false @@ -38,16 +55,16 @@ public object IdeDescriptorRenderers { public val SOURCE_CODE: DescriptorRenderer = BASE.withOptions { nameShortness = NameShortness.SOURCE_CODE_QUALIFIED - typeNormalizer = APPROXIMATE_FLEXIBLE_TYPES + typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) } } public val SOURCE_CODE_FOR_TYPE_ARGUMENTS: DescriptorRenderer = BASE.withOptions { nameShortness = NameShortness.SOURCE_CODE_QUALIFIED - typeNormalizer = APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS + typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS(unwrapAnonymousType(it)) } } public val SOURCE_CODE_SHORT_NAMES_IN_TYPES: DescriptorRenderer = BASE.withOptions { nameShortness = NameShortness.SHORT - typeNormalizer = APPROXIMATE_FLEXIBLE_TYPES + typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt index ab29f08421c..c6542353df0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt @@ -62,6 +62,7 @@ import org.jetbrains.kotlin.idea.util.approximateWithResolvableType import org.jetbrains.kotlin.idea.util.isResolvableInScope import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement @@ -87,8 +88,11 @@ private val DEFAULT_PARAMETER_TYPE = KotlinBuiltIns.getInstance().getNullableAny private fun DeclarationDescriptor.renderForMessage(): String = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(this) -private fun JetType.renderForMessage(): String = - IdeDescriptorRenderers.SOURCE_CODE.renderType(this) +private val TYPE_RENDERER = DescriptorRenderer.FQ_NAMES_IN_TYPES.withOptions { + typeNormalizer = IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES +} + +private fun JetType.renderForMessage(): String = TYPE_RENDERER.renderType(this) private fun JetDeclaration.renderForMessage(bindingContext: BindingContext): String? = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this]?.renderForMessage() diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt new file mode 100644 index 00000000000..9431b407bd7 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt @@ -0,0 +1 @@ +fun f() = object { } diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt.after b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt.after new file mode 100644 index 00000000000..f7cf4355d36 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt.after @@ -0,0 +1,3 @@ +fun f(): Any { + return object { } +} diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt new file mode 100644 index 00000000000..a04f23c8916 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt @@ -0,0 +1,3 @@ +interface I + +fun f() = object : I { } diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt.after b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt.after new file mode 100644 index 00000000000..a0783880c35 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt.after @@ -0,0 +1,5 @@ +interface I + +fun f(): I { + return object : I { } +} diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt new file mode 100644 index 00000000000..a2633ec05c2 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt @@ -0,0 +1,6 @@ +interface I1 +interface I2 + +fun f() { + fun g() = object : I1, I2 { } +} diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt.after b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt.after new file mode 100644 index 00000000000..8085bea17b3 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt.after @@ -0,0 +1,8 @@ +interface I1 +interface I2 + +fun f() { + fun g(): Any { + return object : I1, I2 { } + } +} diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt new file mode 100644 index 00000000000..23082e4560f --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt @@ -0,0 +1,5 @@ +// WITH_RUNTIME + +interface I + +fun f() = listOf(object : I { }) diff --git a/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt.after b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt.after new file mode 100644 index 00000000000..17b1dd91496 --- /dev/null +++ b/idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +interface I + +fun f(): List { + return listOf(object : I { }) +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 6d1333cd1e0..4960897beb1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -3810,6 +3810,30 @@ public class IntentionTestGenerated extends AbstractIntentionTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertToBlockBody/setter.kt"); doTest(fileName); } + + @TestMetadata("valueIsAnonymousObject.kt") + public void testValueIsAnonymousObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject.kt"); + doTest(fileName); + } + + @TestMetadata("valueIsAnonymousObject2.kt") + public void testValueIsAnonymousObject2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject2.kt"); + doTest(fileName); + } + + @TestMetadata("valueIsAnonymousObject3.kt") + public void testValueIsAnonymousObject3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject3.kt"); + doTest(fileName); + } + + @TestMetadata("valueIsAnonymousObject4.kt") + public void testValueIsAnonymousObject4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertToBlockBody/valueIsAnonymousObject4.kt"); + doTest(fileName); + } } @TestMetadata("idea/testData/intentions/convertToConcatenatedString")