Destructuring declaration initializer now cannot use extension componentX() on nullable #KT-7794 Fixed
This commit is contained in:
+2
-1
@@ -49,7 +49,8 @@ class DestructuringDeclarationResolver(
|
|||||||
val componentName = createComponentName(componentIndex + 1)
|
val componentName = createComponentName(componentIndex + 1)
|
||||||
|
|
||||||
val expectedType = getExpectedTypeForComponent(context, entry)
|
val expectedType = getExpectedTypeForComponent(context, entry)
|
||||||
val results = fakeCallResolver.resolveFakeCall(context.replaceExpectedType(expectedType), receiver, componentName, entry)
|
val results = fakeCallResolver.resolveFakeCall(context.replaceExpectedType(expectedType), receiver, componentName,
|
||||||
|
entry, reportErrorsOn, FakeCallKind.COMPONENT)
|
||||||
|
|
||||||
var componentType: KotlinType? = null
|
var componentType: KotlinType? = null
|
||||||
if (results.isSuccess) {
|
if (results.isSuccess) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.psi.Call
|
|||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||||
@@ -35,6 +34,12 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.utils.doNothing
|
import org.jetbrains.kotlin.utils.doNothing
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
enum class FakeCallKind {
|
||||||
|
ITERATOR,
|
||||||
|
COMPONENT,
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
class FakeCallResolver(
|
class FakeCallResolver(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val callResolver: CallResolver
|
private val callResolver: CallResolver
|
||||||
@@ -44,33 +49,31 @@ class FakeCallResolver(
|
|||||||
receiver: ReceiverValue?,
|
receiver: ReceiverValue?,
|
||||||
name: Name,
|
name: Name,
|
||||||
callElement: KtExpression?,
|
callElement: KtExpression?,
|
||||||
|
reportErrorsOn: KtExpression? = callElement,
|
||||||
|
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||||
vararg argumentTypes: KotlinType
|
vararg argumentTypes: KotlinType
|
||||||
): OverloadResolutionResults<FunctionDescriptor> {
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
val traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name)
|
val traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name)
|
||||||
val fakeArguments = ArrayList<KtExpression>()
|
val fakeArguments = ArrayList<KtExpression>()
|
||||||
for (type in argumentTypes) {
|
for (type in argumentTypes) {
|
||||||
fakeArguments.add(ExpressionTypingUtils.createFakeExpressionOfType(project, traceWithFakeArgumentInfo, "fakeArgument" + fakeArguments.size, type))
|
fakeArguments.add(ExpressionTypingUtils.createFakeExpressionOfType(project, traceWithFakeArgumentInfo,
|
||||||
|
"fakeArgument" + fakeArguments.size, type))
|
||||||
}
|
}
|
||||||
return makeAndResolveFakeCall(receiver, context.replaceBindingTrace(traceWithFakeArgumentInfo), fakeArguments, name, callElement).second
|
return makeAndResolveFakeCall(receiver, context.replaceBindingTrace(traceWithFakeArgumentInfo),
|
||||||
|
fakeArguments, name, callElement, callKind, reportErrorsOn).second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
fun resolveFakeCall(
|
fun resolveFakeCall(
|
||||||
context: ExpressionTypingContext,
|
context: ExpressionTypingContext,
|
||||||
receiver: ReceiverValue,
|
receiver: ReceiverValue,
|
||||||
name: Name,
|
name: Name,
|
||||||
callElement: KtExpression
|
callElement: KtExpression,
|
||||||
|
reportErrorsOn: KtExpression = callElement,
|
||||||
|
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||||
|
valueArguments: List<KtExpression> = emptyList()
|
||||||
): OverloadResolutionResults<FunctionDescriptor> {
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
return resolveFakeCall(receiver, context, emptyList(), name, callElement)
|
return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement, callKind, reportErrorsOn).second
|
||||||
}
|
|
||||||
|
|
||||||
fun resolveFakeCall(
|
|
||||||
receiver: ReceiverValue,
|
|
||||||
context: ExpressionTypingContext,
|
|
||||||
valueArguments: List<KtExpression>,
|
|
||||||
name: Name,
|
|
||||||
callElement: KtExpression
|
|
||||||
): OverloadResolutionResults<FunctionDescriptor> {
|
|
||||||
return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement).second
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeAndResolveFakeCall(
|
fun makeAndResolveFakeCall(
|
||||||
@@ -79,25 +82,33 @@ class FakeCallResolver(
|
|||||||
valueArguments: List<KtExpression>,
|
valueArguments: List<KtExpression>,
|
||||||
name: Name,
|
name: Name,
|
||||||
callElement: KtExpression?,
|
callElement: KtExpression?,
|
||||||
iteratorCheck: Boolean = false
|
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||||
|
reportErrorsOn: KtExpression? = callElement
|
||||||
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
|
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
|
||||||
val fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name)
|
val fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name)
|
||||||
val fakeBindingTrace = context.replaceBindingTrace(fakeTrace)
|
val fakeBindingTrace = context.replaceBindingTrace(fakeTrace)
|
||||||
|
|
||||||
var hasUnreportedIteratorError = false
|
var hasUnreportedError = false
|
||||||
val result = makeAndResolveFakeCallInContext(receiver, fakeBindingTrace, valueArguments, name, callElement) { fake ->
|
val result = makeAndResolveFakeCallInContext(receiver, fakeBindingTrace, valueArguments, name, callElement) { fake ->
|
||||||
fakeTrace.commit({ slice, diagnostic, key ->
|
fakeTrace.commit({ slice, diagnostic, key ->
|
||||||
// excluding all entries related to fake expression
|
// excluding all entries related to fake expression
|
||||||
// convert all errors on this expression to ITERATOR_MISSING on callElement
|
// convert all errors on this expression to ITERATOR_MISSING on callElement
|
||||||
val isFakeKey = key == fake
|
val isFakeKey = key == fake
|
||||||
if (iteratorCheck && diagnostic?.severity == Severity.ERROR && isFakeKey) {
|
if (diagnostic?.severity == Severity.ERROR && isFakeKey) {
|
||||||
hasUnreportedIteratorError = true
|
hasUnreportedError = true
|
||||||
}
|
}
|
||||||
!isFakeKey
|
!isFakeKey
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
if (hasUnreportedIteratorError && callElement != null) {
|
if (hasUnreportedError && reportErrorsOn != null) {
|
||||||
context.trace.report(Errors.ITERATOR_MISSING.on(callElement))
|
when (callKind) {
|
||||||
|
FakeCallKind.ITERATOR -> context.trace.report(Errors.ITERATOR_MISSING.on(reportErrorsOn))
|
||||||
|
FakeCallKind.COMPONENT ->
|
||||||
|
if (receiver != null) {
|
||||||
|
context.trace.report(Errors.COMPONENT_FUNCTION_MISSING.on(reportErrorsOn, name, receiver.type))
|
||||||
|
}
|
||||||
|
FakeCallKind.OTHER -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ public class ForLoopConventionsChecker {
|
|||||||
Name iterator = Name.identifier("iterator");
|
Name iterator = Name.identifier("iterator");
|
||||||
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls =
|
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls =
|
||||||
fakeCallResolver.makeAndResolveFakeCall(loopRange, context, Collections.<KtExpression>emptyList(), iterator,
|
fakeCallResolver.makeAndResolveFakeCall(loopRange, context, Collections.<KtExpression>emptyList(), iterator,
|
||||||
loopRange.getExpression(), true);
|
loopRangeExpression, FakeCallKind.ITERATOR, loopRangeExpression);
|
||||||
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
|
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
|
||||||
|
|
||||||
if (iteratorResolutionResults.isSuccess()) {
|
if (iteratorResolutionResults.isSuccess()) {
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
class Data<T>(val x: T, val y: T)
|
||||||
|
|
||||||
|
operator fun <T> Data<T>.component1() = x
|
||||||
|
|
||||||
|
operator fun <T> Data<T>.component2() = y
|
||||||
|
|
||||||
|
fun foo(): Int {
|
||||||
|
val d: Data<Int>? = null
|
||||||
|
// An error must be here
|
||||||
|
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>d<!>
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
data class NormalData<T>(val x: T, val y: T)
|
||||||
|
|
||||||
|
fun bar(): Int {
|
||||||
|
val d: NormalData<Int>? = null
|
||||||
|
// An error must be here
|
||||||
|
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>d<!>
|
||||||
|
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>+<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>y<!>
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun bar(): kotlin.Int
|
||||||
|
public fun foo(): kotlin.Int
|
||||||
|
public operator fun </*0*/ T> Data<T>.component1(): T
|
||||||
|
public operator fun </*0*/ T> Data<T>.component2(): T
|
||||||
|
|
||||||
|
public final class Data</*0*/ T> {
|
||||||
|
public constructor Data</*0*/ T>(/*0*/ x: T, /*1*/ y: T)
|
||||||
|
public final val x: T
|
||||||
|
public final val y: T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final data class NormalData</*0*/ T> {
|
||||||
|
public constructor NormalData</*0*/ T>(/*0*/ x: T, /*1*/ y: T)
|
||||||
|
public final val x: T
|
||||||
|
public final val y: T
|
||||||
|
public final operator /*synthesized*/ fun component1(): T
|
||||||
|
public final operator /*synthesized*/ fun component2(): T
|
||||||
|
public final /*synthesized*/ fun copy(/*0*/ x: T = ..., /*1*/ y: T = ...): NormalData<T>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -3600,6 +3600,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionComponentsOnNullable.kt")
|
||||||
|
public void testExtensionComponentsOnNullable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dataClasses/extensionComponentsOnNullable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("implementTraitWhichHasComponent1.kt")
|
@TestMetadata("implementTraitWhichHasComponent1.kt")
|
||||||
public void testImplementTraitWhichHasComponent1() throws Exception {
|
public void testImplementTraitWhichHasComponent1() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dataClasses/implementTraitWhichHasComponent1.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dataClasses/implementTraitWhichHasComponent1.kt");
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.tests.di.InjectionKt;
|
|||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||||
|
import org.jetbrains.kotlin.types.expressions.FakeCallKind;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -146,7 +147,7 @@ public class ExpectedResolveDataUtil {
|
|||||||
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
|
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
|
||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor> functions = container.getFakeCallResolver().resolveFakeCall(
|
OverloadResolutionResults<FunctionDescriptor> functions = container.getFakeCallResolver().resolveFakeCall(
|
||||||
context, null, Name.identifier(name), null, parameterTypes);
|
context, null, Name.identifier(name), null, null, FakeCallKind.OTHER, parameterTypes);
|
||||||
|
|
||||||
for (ResolvedCall<? extends FunctionDescriptor> resolvedCall : functions.getResultingCalls()) {
|
for (ResolvedCall<? extends FunctionDescriptor> resolvedCall : functions.getResultingCalls()) {
|
||||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
|
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
|
||||||
|
|||||||
Reference in New Issue
Block a user