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 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
|
||||
if (results.isSuccess) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.psi.Call
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
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 java.util.*
|
||||
|
||||
enum class FakeCallKind {
|
||||
ITERATOR,
|
||||
COMPONENT,
|
||||
OTHER
|
||||
}
|
||||
|
||||
class FakeCallResolver(
|
||||
private val project: Project,
|
||||
private val callResolver: CallResolver
|
||||
@@ -44,33 +49,31 @@ class FakeCallResolver(
|
||||
receiver: ReceiverValue?,
|
||||
name: Name,
|
||||
callElement: KtExpression?,
|
||||
reportErrorsOn: KtExpression? = callElement,
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
vararg argumentTypes: KotlinType
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
val traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name)
|
||||
val fakeArguments = ArrayList<KtExpression>()
|
||||
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(
|
||||
context: ExpressionTypingContext,
|
||||
receiver: ReceiverValue,
|
||||
name: Name,
|
||||
callElement: KtExpression
|
||||
callElement: KtExpression,
|
||||
reportErrorsOn: KtExpression = callElement,
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
valueArguments: List<KtExpression> = emptyList()
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
return resolveFakeCall(receiver, context, emptyList(), name, callElement)
|
||||
}
|
||||
|
||||
fun resolveFakeCall(
|
||||
receiver: ReceiverValue,
|
||||
context: ExpressionTypingContext,
|
||||
valueArguments: List<KtExpression>,
|
||||
name: Name,
|
||||
callElement: KtExpression
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement).second
|
||||
return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement, callKind, reportErrorsOn).second
|
||||
}
|
||||
|
||||
fun makeAndResolveFakeCall(
|
||||
@@ -79,25 +82,33 @@ class FakeCallResolver(
|
||||
valueArguments: List<KtExpression>,
|
||||
name: Name,
|
||||
callElement: KtExpression?,
|
||||
iteratorCheck: Boolean = false
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
reportErrorsOn: KtExpression? = callElement
|
||||
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
|
||||
val fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name)
|
||||
val fakeBindingTrace = context.replaceBindingTrace(fakeTrace)
|
||||
|
||||
var hasUnreportedIteratorError = false
|
||||
var hasUnreportedError = false
|
||||
val result = makeAndResolveFakeCallInContext(receiver, fakeBindingTrace, valueArguments, name, callElement) { fake ->
|
||||
fakeTrace.commit({ slice, diagnostic, key ->
|
||||
// excluding all entries related to fake expression
|
||||
// convert all errors on this expression to ITERATOR_MISSING on callElement
|
||||
val isFakeKey = key == fake
|
||||
if (iteratorCheck && diagnostic?.severity == Severity.ERROR && isFakeKey) {
|
||||
hasUnreportedIteratorError = true
|
||||
if (diagnostic?.severity == Severity.ERROR && isFakeKey) {
|
||||
hasUnreportedError = true
|
||||
}
|
||||
!isFakeKey
|
||||
}, true)
|
||||
}
|
||||
if (hasUnreportedIteratorError && callElement != null) {
|
||||
context.trace.report(Errors.ITERATOR_MISSING.on(callElement))
|
||||
if (hasUnreportedError && reportErrorsOn != null) {
|
||||
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
|
||||
}
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class ForLoopConventionsChecker {
|
||||
Name iterator = Name.identifier("iterator");
|
||||
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls =
|
||||
fakeCallResolver.makeAndResolveFakeCall(loopRange, context, Collections.<KtExpression>emptyList(), iterator,
|
||||
loopRange.getExpression(), true);
|
||||
loopRangeExpression, FakeCallKind.ITERATOR, loopRangeExpression);
|
||||
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionComponentsOnNullable.kt")
|
||||
public void testExtensionComponentsOnNullable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dataClasses/extensionComponentsOnNullable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implementTraitWhichHasComponent1.kt")
|
||||
public void testImplementTraitWhichHasComponent1() throws Exception {
|
||||
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.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||
import org.jetbrains.kotlin.types.expressions.FakeCallKind;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -146,7 +147,7 @@ public class ExpectedResolveDataUtil {
|
||||
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
|
||||
|
||||
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()) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
|
||||
|
||||
Reference in New Issue
Block a user