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 }