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();
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);
@@ -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 -> {
@@ -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);
}
@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");