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 }