001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.resolve.calls;
018    
019    import com.intellij.lang.ASTNode;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.util.PsiTreeUtil;
022    import kotlin.jvm.functions.Function1;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
026    import org.jetbrains.kotlin.descriptors.*;
027    import org.jetbrains.kotlin.psi.*;
028    import org.jetbrains.kotlin.resolve.*;
029    import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
030    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
031    import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
032    import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
033    import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
034    import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
035    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
036    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
037    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
038    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
039    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
040    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
041    import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
042    import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
043    import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
044    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
045    import org.jetbrains.kotlin.resolve.scopes.receivers.*;
046    import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
047    import org.jetbrains.kotlin.types.ErrorUtils;
048    import org.jetbrains.kotlin.types.KotlinType;
049    import org.jetbrains.kotlin.types.TypeUtils;
050    import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer;
051    import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
052    import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
053    import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
054    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
055    
056    import javax.inject.Inject;
057    import java.util.Collections;
058    import java.util.List;
059    
060    import static org.jetbrains.kotlin.diagnostics.Errors.*;
061    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
062    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
063    
064    public class CallExpressionResolver {
065    
066        @NotNull private final CallResolver callResolver;
067        @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
068        @NotNull private final DataFlowAnalyzer dataFlowAnalyzer;
069        @NotNull private final KotlinBuiltIns builtIns;
070        @NotNull private final QualifiedExpressionResolver qualifiedExpressionResolver;
071        @NotNull private final SymbolUsageValidator symbolUsageValidator;
072    
073        public CallExpressionResolver(
074                @NotNull CallResolver callResolver,
075                @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
076                @NotNull DataFlowAnalyzer dataFlowAnalyzer,
077                @NotNull KotlinBuiltIns builtIns,
078                @NotNull QualifiedExpressionResolver qualifiedExpressionResolver,
079                @NotNull SymbolUsageValidator symbolUsageValidator
080        ) {
081            this.callResolver = callResolver;
082            this.constantExpressionEvaluator = constantExpressionEvaluator;
083            this.dataFlowAnalyzer = dataFlowAnalyzer;
084            this.builtIns = builtIns;
085            this.qualifiedExpressionResolver = qualifiedExpressionResolver;
086            this.symbolUsageValidator = symbolUsageValidator;
087        }
088    
089        private ExpressionTypingServices expressionTypingServices;
090    
091        // component dependency cycle
092        @Inject
093        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
094            this.expressionTypingServices = expressionTypingServices;
095        }
096    
097        @Nullable
098        public ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
099                @NotNull Call call,
100                @NotNull ResolutionContext context, @NotNull CheckArgumentTypesMode checkArguments,
101                @NotNull boolean[] result
102        ) {
103            OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
104                    BasicCallResolutionContext.create(context, call, checkArguments));
105            if (!results.isNothing()) {
106                result[0] = true;
107                return OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency);
108            }
109            result[0] = false;
110            return null;
111        }
112    
113        @Nullable
114        private KotlinType getVariableType(
115                @NotNull KtSimpleNameExpression nameExpression, @Nullable Receiver receiver,
116                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context, @NotNull boolean[] result
117        ) {
118            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
119                    context, "trace to resolve as local variable or property", nameExpression);
120            Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
121            BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
122                    context.replaceTraceAndCache(temporaryForVariable),
123                    call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
124            OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
125    
126            // if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
127            boolean isLHSOfDot = KtPsiUtil.isLHSOfDot(nameExpression);
128            if (!resolutionResult.isNothing() && resolutionResult.getResultCode() != OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER) {
129                boolean isQualifier = isLHSOfDot &&
130                                      resolutionResult.isSingleResult() &&
131                                      resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject;
132                if (!isQualifier) {
133                    result[0] = true;
134                    temporaryForVariable.commit();
135                    return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
136                }
137            }
138    
139            temporaryForVariable.commit();
140            result[0] = !resolutionResult.isNothing();
141            return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
142        }
143    
144        @NotNull
145        public KotlinTypeInfo getSimpleNameExpressionTypeInfo(
146                @NotNull KtSimpleNameExpression nameExpression, @Nullable Receiver receiver,
147                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
148        ) {
149            boolean[] result = new boolean[1];
150    
151            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
152                    context, "trace to resolve as variable", nameExpression);
153            KotlinType type =
154                    getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
155    
156            if (result[0]) {
157                temporaryForVariable.commit();
158                return TypeInfoFactoryKt.createTypeInfo(type, context);
159            }
160    
161            Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList());
162            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
163                    context, "trace to resolve as function", nameExpression);
164            ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
165            ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
166                    call, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
167            if (result[0]) {
168                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
169                if (!(functionDescriptor instanceof ConstructorDescriptor)) {
170                    temporaryForFunction.commit();
171                    boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
172                    context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
173                    type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
174                    return TypeInfoFactoryKt.createTypeInfo(type, context);
175                }
176            }
177    
178            TemporaryTraceAndCache temporaryForQualifier = TemporaryTraceAndCache.create(context, "trace to resolve as qualifier", nameExpression);
179            ExpressionTypingContext contextForQualifier = context.replaceTraceAndCache(temporaryForQualifier);
180            Qualifier qualifier = qualifiedExpressionResolver.resolveNameExpressionAsQualifierForDiagnostics(nameExpression, receiver, contextForQualifier);
181            if (qualifier != null) {
182                QualifiedExpressionResolveUtilKt.resolveQualifierAsStandaloneExpression(qualifier, contextForQualifier, symbolUsageValidator);
183                temporaryForQualifier.commit();
184                return TypeInfoFactoryKt.noTypeInfo(context);
185            }
186    
187            temporaryForVariable.commit();
188            return TypeInfoFactoryKt.noTypeInfo(context);
189        }
190    
191        @NotNull
192        public KotlinTypeInfo getCallExpressionTypeInfo(
193                @NotNull KtCallExpression callExpression, @Nullable ReceiverValue receiver,
194                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
195        ) {
196            KotlinTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
197            if (context.contextDependency == INDEPENDENT) {
198                dataFlowAnalyzer.checkType(typeInfo.getType(), callExpression, context);
199            }
200            return typeInfo;
201        }
202    
203        /**
204         * Visits a call expression and its arguments.
205         * Determines the result type and data flow information after the call.
206         */
207        @NotNull
208        private KotlinTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(
209                @NotNull KtCallExpression callExpression, @Nullable Receiver receiver,
210                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
211        ) {
212            boolean[] result = new boolean[1];
213            Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
214    
215            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
216                    context, "trace to resolve as function call", callExpression);
217            ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
218                    call,
219                    context.replaceTraceAndCache(temporaryForFunction),
220                    CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
221            if (result[0]) {
222                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
223                temporaryForFunction.commit();
224                if (callExpression.getValueArgumentList() == null && callExpression.getLambdaArguments().isEmpty()) {
225                    // there are only type arguments
226                    boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
227                    context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
228                }
229                if (functionDescriptor == null) {
230                    return TypeInfoFactoryKt.noTypeInfo(context);
231                }
232                if (functionDescriptor instanceof ConstructorDescriptor) {
233                    DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
234                    if (DescriptorUtils.isAnnotationClass(containingDescriptor)
235                        && !canInstantiateAnnotationClass(callExpression, context.trace)) {
236                        context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression));
237                    }
238                    if (DescriptorUtils.isEnumClass(containingDescriptor)) {
239                        context.trace.report(ENUM_CLASS_CONSTRUCTOR_CALL.on(callExpression));
240                    }
241                    if (containingDescriptor instanceof ClassDescriptor
242                        && ((ClassDescriptor) containingDescriptor).getModality() == Modality.SEALED) {
243                        context.trace.report(SEALED_CLASS_CONSTRUCTOR_CALL.on(callExpression));
244                    }
245                }
246    
247                KotlinType type = functionDescriptor.getReturnType();
248                // Extracting jump out possible and jump point flow info from arguments, if any
249                List<? extends ValueArgument> arguments = callExpression.getValueArguments();
250                DataFlowInfo resultFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
251                DataFlowInfo jumpFlowInfo = resultFlowInfo;
252                boolean jumpOutPossible = false;
253                for (ValueArgument argument: arguments) {
254                    KotlinTypeInfo argTypeInfo = context.trace.get(BindingContext.EXPRESSION_TYPE_INFO, argument.getArgumentExpression());
255                    if (argTypeInfo != null && argTypeInfo.getJumpOutPossible()) {
256                        jumpOutPossible = true;
257                        jumpFlowInfo = argTypeInfo.getJumpFlowInfo();
258                        break;
259                    }
260                }
261                return TypeInfoFactoryKt.createTypeInfo(type, resultFlowInfo, jumpOutPossible, jumpFlowInfo);
262            }
263    
264            KtExpression calleeExpression = callExpression.getCalleeExpression();
265            if (calleeExpression instanceof KtSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
266                TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
267                        context, "trace to resolve as variable with 'invoke' call", callExpression);
268                KotlinType type = getVariableType((KtSimpleNameExpression) calleeExpression, receiver, callOperationNode,
269                                                  context.replaceTraceAndCache(temporaryForVariable), result);
270                Qualifier qualifier = temporaryForVariable.trace.get(BindingContext.QUALIFIER, calleeExpression);
271                if (result[0] && (qualifier == null || !(qualifier instanceof PackageQualifier))) {
272                    temporaryForVariable.commit();
273                    context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression,
274                                                              type != null ? type : ErrorUtils.createErrorType("")));
275                    return TypeInfoFactoryKt.noTypeInfo(context);
276                }
277            }
278            temporaryForFunction.commit();
279            return TypeInfoFactoryKt.noTypeInfo(context);
280        }
281    
282        private static boolean canInstantiateAnnotationClass(@NotNull KtCallExpression expression, @NotNull BindingTrace trace) {
283            //noinspection unchecked
284            PsiElement parent = PsiTreeUtil.getParentOfType(expression, KtValueArgument.class, KtParameter.class);
285            if (parent instanceof KtValueArgument) {
286                if (PsiTreeUtil.getParentOfType(parent, KtAnnotationEntry.class) != null) {
287                    return true;
288                }
289                parent = PsiTreeUtil.getParentOfType(parent, KtParameter.class);
290                if (parent != null) {
291                    return isUnderAnnotationClassDeclaration(trace, parent);
292                }
293            }
294            else if (parent instanceof KtParameter) {
295                return isUnderAnnotationClassDeclaration(trace, parent);
296            }
297            return false;
298        }
299    
300        private static boolean isUnderAnnotationClassDeclaration(@NotNull BindingTrace trace, PsiElement parent) {
301            KtClass ktClass = PsiTreeUtil.getParentOfType(parent, KtClass.class);
302            if (ktClass != null) {
303                DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ktClass);
304                return DescriptorUtils.isAnnotationClass(descriptor);
305            }
306            return false;
307        }
308    
309        @NotNull
310        private KotlinTypeInfo getSelectorReturnTypeInfo(
311                @NotNull Receiver receiver,
312                @Nullable ASTNode callOperationNode,
313                @Nullable KtExpression selectorExpression,
314                @NotNull ExpressionTypingContext context
315        ) {
316            if (selectorExpression instanceof KtCallExpression) {
317                return getCallExpressionTypeInfoWithoutFinalTypeCheck((KtCallExpression) selectorExpression, receiver,
318                                                                      callOperationNode, context);
319            }
320            else if (selectorExpression instanceof KtSimpleNameExpression) {
321                return getSimpleNameExpressionTypeInfo((KtSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
322            }
323            else if (selectorExpression != null) {
324                context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
325            }
326            return TypeInfoFactoryKt.noTypeInfo(context);
327        }
328    
329        public static void reportUnnecessarySafeCall(
330                @NotNull BindingTrace trace, @NotNull KotlinType type,
331                @NotNull ASTNode callOperationNode, @Nullable Receiver explicitReceiver
332        ) {
333            if (explicitReceiver instanceof ExpressionReceiver &&
334                ((ExpressionReceiver) explicitReceiver).getExpression() instanceof KtSuperExpression) {
335                trace.report(UNEXPECTED_SAFE_CALL.on(callOperationNode.getPsi()));
336            }
337            else {
338                trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
339            }
340        }
341    
342        /**
343         * Visits a qualified expression like x.y or x?.z controlling data flow information changes.
344         *
345         * @return qualified expression type together with data flow information
346         */
347        @NotNull
348        public KotlinTypeInfo getQualifiedExpressionTypeInfo(
349                @NotNull KtQualifiedExpression expression, @NotNull final ExpressionTypingContext context
350        ) {
351            ExpressionTypingContext currentContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
352            BindingTrace trace = currentContext.trace;
353    
354            Function1<KtSimpleNameExpression, Boolean> isValueFunction = new Function1<KtSimpleNameExpression, Boolean>() {
355                @Override
356                public Boolean invoke(KtSimpleNameExpression nameExpression) {
357                    TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
358                            context, "trace to resolve as local variable or property", nameExpression);
359                    Call call = CallMaker.makePropertyCall(null, null, nameExpression);
360                    BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
361                            context.replaceTraceAndCache(temporaryForVariable),
362                            call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
363                    OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
364    
365                    if (resolutionResult.isSingleResult() &&
366                        resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject) {
367                        return false;
368                    }
369    
370                    OverloadResolutionResults.Code resultCode = resolutionResult.getResultCode();
371                    return resultCode != OverloadResolutionResults.Code.NAME_NOT_FOUND &&
372                           resultCode != OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
373                }
374            };
375            List<CallExpressionElement> elementChain =
376                    qualifiedExpressionResolver.resolveQualifierInExpressionAndUnroll(expression, context, isValueFunction);
377    
378            KotlinTypeInfo receiverTypeInfo;
379            KotlinType receiverType;
380            DataFlowInfo receiverDataFlowInfo;
381    
382            CallExpressionElement firstElement = elementChain.iterator().next();
383            KtExpression firstReceiver = firstElement.getReceiver();
384            Qualifier firstQualifier = trace.get(BindingContext.QUALIFIER, firstReceiver);
385            if (firstQualifier == null) {
386                receiverTypeInfo = expressionTypingServices.getTypeInfo(firstReceiver, currentContext);
387                receiverType = receiverTypeInfo.getType();
388                receiverDataFlowInfo = receiverTypeInfo.getDataFlowInfo();
389            }
390            else {
391                receiverType = null;
392                receiverDataFlowInfo = currentContext.dataFlowInfo;
393                //noinspection ConstantConditions
394                receiverTypeInfo = new KotlinTypeInfo(receiverType, receiverDataFlowInfo);
395            }
396    
397            KotlinTypeInfo resultTypeInfo = receiverTypeInfo;
398    
399            boolean unconditional = true;
400            DataFlowInfo unconditionalDataFlowInfo = receiverDataFlowInfo;
401            ExpressionTypingContext contextForSelector = currentContext;
402    
403            for (CallExpressionElement element : elementChain) {
404                if (receiverType == null) {
405                    receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
406                }
407                QualifierReceiver qualifierReceiver = (QualifierReceiver) trace.get(BindingContext.QUALIFIER, element.getReceiver());
408    
409                Receiver receiver = qualifierReceiver == null
410                                    ? ExpressionReceiver.Companion.create(element.getReceiver(), receiverType, trace.getBindingContext())
411                                    : qualifierReceiver;
412    
413                boolean lastStage = element.getQualified() == expression;
414                // Drop NO_EXPECTED_TYPE / INDEPENDENT at last stage
415                ExpressionTypingContext baseContext = lastStage ? context : currentContext;
416                if (TypeUtils.isNullableType(receiverType) && !element.getSafe()) {
417                    // Call with nullable receiver: take unconditional data flow info
418                    contextForSelector = baseContext.replaceDataFlowInfo(unconditionalDataFlowInfo);
419                }
420                else {
421                    // Take data flow info from the current receiver
422                    contextForSelector = baseContext.replaceDataFlowInfo(receiverDataFlowInfo);
423                }
424    
425                if (receiver instanceof ReceiverValue) {
426                    DataFlowValue receiverDataFlowValue = DataFlowValueFactory.createDataFlowValue((ReceiverValue) receiver, context);
427                    // Additional "receiver != null" information
428                    // Should be applied if we consider a safe call
429                    if (element.getSafe()) {
430                        DataFlowInfo dataFlowInfo = contextForSelector.dataFlowInfo;
431                        if (dataFlowInfo.getPredictableNullability(receiverDataFlowValue).canBeNull()) {
432                            contextForSelector = contextForSelector.replaceDataFlowInfo(
433                                    dataFlowInfo.disequate(receiverDataFlowValue, DataFlowValue.nullValue(builtIns)));
434                        }
435                        else {
436                            reportUnnecessarySafeCall(trace, receiverType, element.getNode(), receiver);
437                        }
438                    }
439                }
440    
441                KtExpression selectorExpression = element.getSelector();
442                KotlinTypeInfo selectorReturnTypeInfo =
443                        getSelectorReturnTypeInfo(receiver, element.getNode(), selectorExpression, contextForSelector);
444                KotlinType selectorReturnType = selectorReturnTypeInfo.getType();
445    
446                if (qualifierReceiver != null) {
447                    resolveDeferredReceiverInQualifiedExpression(qualifierReceiver, element.getQualified(), contextForSelector);
448                }
449                checkNestedClassAccess(element.getQualified(), contextForSelector);
450    
451                boolean safeCall = element.getSafe();
452                if (safeCall && selectorReturnType != null && TypeUtils.isNullableType(receiverType)) {
453                    selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
454                    selectorReturnTypeInfo = selectorReturnTypeInfo.replaceType(selectorReturnType);
455                }
456    
457                // TODO : this is suspicious: remove this code?
458                if (selectorExpression != null && selectorReturnType != null) {
459                    trace.recordType(selectorExpression, selectorReturnType);
460                }
461                resultTypeInfo = selectorReturnTypeInfo;
462                CompileTimeConstant<?> value = constantExpressionEvaluator.evaluateExpression(
463                        element.getQualified(), trace, contextForSelector.expectedType);
464                if (value != null && value.isPure()) {
465                    resultTypeInfo =  dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, element.getQualified(), contextForSelector);
466                    if (lastStage) return resultTypeInfo;
467                }
468                if (contextForSelector.contextDependency == INDEPENDENT) {
469                    dataFlowAnalyzer.checkType(resultTypeInfo.getType(), element.getQualified(), contextForSelector);
470                }
471                // For the next stage, if any, current stage selector is the receiver!
472                receiverTypeInfo = selectorReturnTypeInfo;
473                receiverType = selectorReturnType;
474                receiverDataFlowInfo = receiverTypeInfo.getDataFlowInfo();
475                // if we have only dots and not ?. move unconditional data flow info further
476                if (safeCall) {
477                    unconditional = false;
478                }
479                else if (unconditional) {
480                    unconditionalDataFlowInfo = receiverDataFlowInfo;
481                }
482                //noinspection ConstantConditions
483                if (!lastStage && !trace.get(BindingContext.PROCESSED, element.getQualified())) {
484                    // Store type information (to prevent problems in call completer)
485                    trace.record(BindingContext.PROCESSED, element.getQualified());
486                    trace.record(BindingContext.EXPRESSION_TYPE_INFO, element.getQualified(),
487                                                resultTypeInfo.replaceDataFlowInfo(unconditionalDataFlowInfo));
488                    // save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
489                    BindingContextUtilsKt.recordScope(trace, contextForSelector.scope, element.getQualified());
490                    BindingContextUtilsKt.recordDataFlowInfo(contextForSelector.replaceDataFlowInfo(unconditionalDataFlowInfo),
491                                                             element.getQualified());
492                }
493            }
494            // if we are at last stage, we should just take result type info and set unconditional data flow info
495            return resultTypeInfo.replaceDataFlowInfo(unconditionalDataFlowInfo);
496        }
497    
498        private void resolveDeferredReceiverInQualifiedExpression(
499                @NotNull QualifierReceiver qualifierReceiver,
500                @NotNull KtQualifiedExpression qualifiedExpression,
501                @NotNull ExpressionTypingContext context
502        ) {
503            KtExpression calleeExpression =
504                    KtPsiUtil.deparenthesize(CallUtilKt.getCalleeExpressionIfAny(qualifiedExpression.getSelectorExpression()));
505            DeclarationDescriptor selectorDescriptor =
506                    calleeExpression instanceof KtReferenceExpression
507                    ? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null;
508    
509            QualifiedExpressionResolveUtilKt.resolveQualifierAsReceiverInExpression(qualifierReceiver, selectorDescriptor, context, symbolUsageValidator);
510        }
511    
512        private static void checkNestedClassAccess(
513                @NotNull KtQualifiedExpression expression,
514                @NotNull ExpressionTypingContext context
515        ) {
516            KtExpression selectorExpression = expression.getSelectorExpression();
517            if (selectorExpression == null) return;
518    
519            // A.B - if B is a nested class accessed by outer class, 'A' and 'A.B' were marked as qualifiers
520            // a.B - if B is a nested class accessed by instance reference, 'a.B' was marked as a qualifier, but 'a' was not (it's an expression)
521    
522            Qualifier expressionQualifier = context.trace.get(BindingContext.QUALIFIER, expression);
523            Qualifier receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.getReceiverExpression());
524    
525            if (receiverQualifier == null && expressionQualifier != null) {
526                assert expressionQualifier instanceof ClassQualifier :
527                        "Only class can (package cannot) be accessed by instance reference: " + expressionQualifier;
528                context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(
529                        selectorExpression,
530                        ((ClassQualifier) expressionQualifier).getClassifier()));
531            }
532        }
533    }