From d48851ba6324db1c40d7398974f8f69618e5be3b Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 18 Aug 2015 19:38:46 +0300 Subject: [PATCH] Create From Usage: Fix ClassCastException on local property with delegate #EA-69707 Fixed --- .../kotlin/cfg/JetControlFlowProcessor.java | 13 +++---------- .../createFromUsage/callableBuilder/typeUtils.kt | 13 +++++-------- .../property/localValDelegateRuntime.kt | 7 +++++++ .../property/localValDelegateRuntime.kt.after | 11 +++++++++++ .../kotlin/idea/quickfix/QuickFixTestGenerated.java | 6 ++++++ 5 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt create mode 100644 idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java index 009380aa147..16f7141f5e1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java @@ -1147,7 +1147,9 @@ public class JetControlFlowProcessor { JetExpression delegate = property.getDelegateExpression(); if (delegate != null) { generateInstructions(delegate); - generateDelegateConsumer(property, delegate); + if (builder.getBoundValue(delegate) != null) { + createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate); + } } if (JetPsiUtil.isLocal(property)) { @@ -1157,15 +1159,6 @@ public class JetControlFlowProcessor { } } - private void generateDelegateConsumer(@NotNull JetProperty property, @NotNull JetExpression delegate) { - DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); - if (!(descriptor instanceof PropertyDescriptor)) return; - - if (builder.getBoundValue(delegate) == null) return; - - createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate); - } - @Override public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) { visitMultiDeclaration(declaration, true); diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt index 5e88306649d..9c25872225d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -19,10 +19,7 @@ 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.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName @@ -171,13 +168,13 @@ fun JetExpression.guessTypes( } } parent is JetPropertyDelegate -> { - val property = context[BindingContext.DECLARATION_TO_DESCRIPTOR, parent.getParent() as JetProperty] as PropertyDescriptor - val delegateClassName = if (property.isVar()) "ReadWriteProperty" else "ReadOnlyProperty" + val variableDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, parent.getParent() as JetProperty] as VariableDescriptor + val delegateClassName = if (variableDescriptor.isVar()) "ReadWriteProperty" else "ReadOnlyProperty" val delegateClass = module.resolveTopLevelClass(FqName("kotlin.properties.$delegateClassName")) ?: return arrayOf(module.builtIns.getAnyType()) - val receiverType = (property.getExtensionReceiverParameter() ?: property.getDispatchReceiverParameter())?.getType() + val receiverType = (variableDescriptor.getExtensionReceiverParameter() ?: variableDescriptor.getDispatchReceiverParameter())?.getType() ?: module.builtIns.getNullableNothingType() - val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(property.getType())) + val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(variableDescriptor.getType())) arrayOf(TypeUtils.substituteProjectionsForParameters(delegateClass, typeArguments)) } parent is JetStringTemplateEntryWithExpression && parent.getExpression() == this -> { diff --git a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt new file mode 100644 index 00000000000..85550c300d1 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt @@ -0,0 +1,7 @@ +// "Create property 'foo'" "true" +// ERROR: Local variables are not allowed to have delegates +// ERROR: Property must be initialized + +fun test() { + val x: Int by foo +} diff --git a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after new file mode 100644 index 00000000000..394e5ba90e7 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after @@ -0,0 +1,11 @@ +import kotlin.properties.ReadOnlyProperty + +// "Create property 'foo'" "true" +// ERROR: Local variables are not allowed to have delegates +// ERROR: Property must be initialized + +val foo: ReadOnlyProperty + +fun test() { + val x: Int by foo +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index f25328765c1..72f636dbf1d 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -2735,6 +2735,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("localValDelegateRuntime.kt") + public void testLocalValDelegateRuntime() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt"); + doTest(fileName); + } + @TestMetadata("localValNoReceiver.kt") public void testLocalValNoReceiver() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/localValNoReceiver.kt");