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