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