Create From Usage: Fix ClassCastException on local property with delegate
#EA-69707 Fixed
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
+5
-8
@@ -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 -> {
|
||||||
|
|||||||
+7
@@ -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
|
||||||
|
}
|
||||||
Vendored
+11
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user