Create From Usage: Fix ClassCastException on local property with delegate

#EA-69707 Fixed
This commit is contained in:
Alexey Sedunov
2015-08-18 19:38:46 +03:00
parent 85f85e85b4
commit d48851ba63
5 changed files with 32 additions and 18 deletions
@@ -1147,7 +1147,9 @@ public class JetControlFlowProcessor {
JetExpression delegate = property.getDelegateExpression(); JetExpression delegate = property.getDelegateExpression();
if (delegate != null) { if (delegate != null) {
generateInstructions(delegate); generateInstructions(delegate);
generateDelegateConsumer(property, delegate); if (builder.getBoundValue(delegate) != null) {
createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate);
}
} }
if (JetPsiUtil.isLocal(property)) { 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 @Override
public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) { public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) {
visitMultiDeclaration(declaration, true); visitMultiDeclaration(declaration, true);
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
import com.intellij.refactoring.psi.SearchUtils import com.intellij.refactoring.psi.SearchUtils
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.cfg.pseudocode.* import org.jetbrains.kotlin.cfg.pseudocode.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -171,13 +168,13 @@ fun JetExpression.guessTypes(
} }
} }
parent is JetPropertyDelegate -> { parent is JetPropertyDelegate -> {
val property = context[BindingContext.DECLARATION_TO_DESCRIPTOR, parent.getParent() as JetProperty] as PropertyDescriptor val variableDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, parent.getParent() as JetProperty] as VariableDescriptor
val delegateClassName = if (property.isVar()) "ReadWriteProperty" else "ReadOnlyProperty" val delegateClassName = if (variableDescriptor.isVar()) "ReadWriteProperty" else "ReadOnlyProperty"
val delegateClass = module.resolveTopLevelClass(FqName("kotlin.properties.$delegateClassName")) val delegateClass = module.resolveTopLevelClass(FqName("kotlin.properties.$delegateClassName"))
?: return arrayOf(module.builtIns.getAnyType()) ?: return arrayOf(module.builtIns.getAnyType())
val receiverType = (property.getExtensionReceiverParameter() ?: property.getDispatchReceiverParameter())?.getType() val receiverType = (variableDescriptor.getExtensionReceiverParameter() ?: variableDescriptor.getDispatchReceiverParameter())?.getType()
?: module.builtIns.getNullableNothingType() ?: module.builtIns.getNullableNothingType()
val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(property.getType())) val typeArguments = listOf(TypeProjectionImpl(receiverType), TypeProjectionImpl(variableDescriptor.getType()))
arrayOf(TypeUtils.substituteProjectionsForParameters(delegateClass, typeArguments)) arrayOf(TypeUtils.substituteProjectionsForParameters(delegateClass, typeArguments))
} }
parent is JetStringTemplateEntryWithExpression && parent.getExpression() == this -> { parent is JetStringTemplateEntryWithExpression && parent.getExpression() == this -> {
@@ -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 <caret>foo
}
@@ -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<Nothing?, Int>
fun test() {
val x: Int by foo
}
@@ -2735,6 +2735,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); 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") @TestMetadata("localValNoReceiver.kt")
public void testLocalValNoReceiver() throws Exception { public void testLocalValNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/localValNoReceiver.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createVariable/property/localValNoReceiver.kt");