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 }