001    /*
002     * Copyright 2010-2013 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.jet.lang.resolve.calls;
018    
019    import com.intellij.lang.ASTNode;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.util.PsiTreeUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.*;
025    import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
026    import org.jetbrains.jet.lang.psi.*;
027    import org.jetbrains.jet.lang.resolve.BindingContext;
028    import org.jetbrains.jet.lang.resolve.BindingTrace;
029    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
030    import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
031    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
032    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
033    import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
034    import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
035    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
036    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
037    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
038    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
039    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
040    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
041    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
042    import org.jetbrains.jet.lang.resolve.name.Name;
043    import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
044    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
045    import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
046    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
047    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
048    import org.jetbrains.jet.lang.types.*;
049    import org.jetbrains.jet.lang.types.expressions.BasicExpressionTypingVisitor;
050    import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
051    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
052    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
053    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
054    import org.jetbrains.jet.lexer.JetTokens;
055    import org.jetbrains.jet.utils.Printer;
056    
057    import javax.inject.Inject;
058    import java.util.ArrayList;
059    import java.util.Collections;
060    import java.util.List;
061    
062    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
063    import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
064    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
065    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
066    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
067    import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
068    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
069    
070    public class CallExpressionResolver {
071        @NotNull
072        private ExpressionTypingServices expressionTypingServices;
073    
074        @Inject
075        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
076            this.expressionTypingServices = expressionTypingServices;
077        }
078    
079        @Nullable
080        private JetType lookupPackageOrClassObject(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) {
081            Name referencedName = expression.getReferencedNameAsName();
082            final ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
083            if (classifier != null) {
084                JetType classObjectType = classifier.getClassObjectType();
085                if (classObjectType != null) {
086                    context.trace.record(REFERENCE_TARGET, expression, classifier);
087                    JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context);
088                    checkClassObjectVisibility(classifier, expression, context);
089                    return DataFlowUtils.checkType(result, expression, context);
090                }
091            }
092            JetType[] result = new JetType[1];
093            TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
094                    context.trace, "trace for package/class object lookup of name", referencedName);
095            if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
096                temporaryTrace.commit();
097                return DataFlowUtils.checkType(result[0], expression, context);
098            }
099            // To report NO_CLASS_OBJECT when no package found
100            if (classifier != null) {
101                if (classifier instanceof TypeParameterDescriptor) {
102                    if (isLHSOfDot(expression)) {
103                        context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, (TypeParameterDescriptor) classifier));
104                    }
105                    else {
106                        context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, (TypeParameterDescriptor) classifier));
107                    }
108                }
109                else if (!isLHSOfDot(expression)) {
110                    context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
111                }
112                context.trace.record(REFERENCE_TARGET, expression, classifier);
113                JetScope scopeForStaticMembersResolution =
114                        classifier instanceof ClassDescriptor
115                        ? getStaticNestedClassesScope((ClassDescriptor) classifier)
116                        : new JetScopeImpl() {
117                                @NotNull
118                                @Override
119                                public DeclarationDescriptor getContainingDeclaration() {
120                                    return classifier;
121                                }
122    
123                                @Override
124                                public String toString() {
125                                    return "Scope for the type parameter on the left hand side of dot";
126                                }
127    
128                                @Override
129                                public void printScopeStructure(@NotNull Printer p) {
130                                    p.println(toString(), " for ", classifier);
131                                }
132                        };
133                return new PackageType(referencedName, scopeForStaticMembersResolution, NO_RECEIVER);
134            }
135            temporaryTrace.commit();
136            return result[0];
137        }
138    
139        private static void checkClassObjectVisibility(
140                @NotNull ClassifierDescriptor classifier,
141                @NotNull JetSimpleNameExpression expression,
142                @NotNull ExpressionTypingContext context
143        ) {
144            if (!(classifier instanceof ClassDescriptor)) return;
145            ClassDescriptor classObject = ((ClassDescriptor) classifier).getClassObjectDescriptor();
146            assert classObject != null : "This check should be done only for classes with class objects: " + classifier;
147            DeclarationDescriptor from = context.containingDeclaration;
148            if (!Visibilities.isVisible(classObject, from)) {
149                context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), from));
150            }
151        }
152    
153        @NotNull
154        private static JetType getExtendedClassObjectType(
155                @NotNull JetSimpleNameExpression expression,
156                @NotNull JetType classObjectType,
157                @NotNull ClassifierDescriptor classifier,
158                @NotNull ResolutionContext context
159        ) {
160            if (!isLHSOfDot(expression) || !(classifier instanceof ClassDescriptor)) {
161                return classObjectType;
162            }
163            ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
164    
165            if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
166                return classObjectType;
167            }
168    
169            List<JetScope> scopes = new ArrayList<JetScope>(3);
170    
171            scopes.add(classObjectType.getMemberScope());
172            scopes.add(getStaticNestedClassesScope(classDescriptor));
173    
174            Name referencedName = expression.getReferencedNameAsName();
175            PackageViewDescriptor packageView = context.scope.getPackage(referencedName);
176            if (packageView != null) {
177                //for enums loaded from java binaries
178                scopes.add(packageView.getMemberScope());
179            }
180    
181            JetScope scope = new ChainedScope(
182                    classifier, "Member scope for extended class object type " + classifier, scopes.toArray(new JetScope[scopes.size()])
183            );
184            return new PackageType(referencedName, scope, new ExpressionReceiver(expression, classObjectType));
185        }
186    
187        private boolean furtherNameLookup(
188                @NotNull JetSimpleNameExpression expression,
189                @NotNull JetType[] result,
190                @NotNull ResolutionContext context
191        ) {
192            PackageType packageType = lookupPackageType(expression, context);
193            if (packageType == null) {
194                return false;
195            }
196            if (isLHSOfDot(expression)) {
197                result[0] = packageType;
198                return true;
199            }
200            context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(expression));
201            result[0] = ErrorUtils.createErrorType("Type for " + expression.getReferencedNameAsName());
202            return false;
203        }
204    
205        @Nullable
206        private PackageType lookupPackageType(@NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
207            Name name = expression.getReferencedNameAsName();
208            PackageViewDescriptor packageView = context.scope.getPackage(name);
209            if (packageView == null) {
210                return null;
211            }
212            context.trace.record(REFERENCE_TARGET, expression, packageView);
213    
214            // Construct a PackageType with everything from the package and with nested classes of the corresponding class (if any)
215            JetScope scope;
216            ClassifierDescriptor classifier = context.scope.getClassifier(name);
217            if (classifier instanceof ClassDescriptor) {
218                scope = new ChainedScope(
219                        packageView, "Package type member scope for " + expression.getText(), packageView.getMemberScope(), getStaticNestedClassesScope((ClassDescriptor) classifier)
220                );
221            }
222            else {
223                scope = packageView.getMemberScope();
224            }
225            return new PackageType(name, scope, NO_RECEIVER);
226        }
227    
228        @Nullable
229        public ResolvedCallWithTrace<FunctionDescriptor> getResolvedCallForFunction(
230                @NotNull Call call, @NotNull JetExpression callExpression,
231                @NotNull ResolutionContext context, @NotNull CheckValueArgumentsMode checkArguments,
232                @NotNull boolean[] result
233        ) {
234            CallResolver callResolver = expressionTypingServices.getCallResolver();
235            OverloadResolutionResultsImpl<FunctionDescriptor> results = callResolver.resolveFunctionCall(
236                    BasicCallResolutionContext.create(context, call, checkArguments));
237            if (!results.isNothing()) {
238                checkSuper(call.getExplicitReceiver(), results, context.trace, callExpression);
239                result[0] = true;
240                return OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency);
241            }
242            result[0] = false;
243            return null;
244        }
245    
246        @Nullable
247        private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
248                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context, @NotNull boolean[] result
249        ) {
250            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
251                    context, "trace to resolve as local variable or property", nameExpression);
252            CallResolver callResolver = expressionTypingServices.getCallResolver();
253            Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
254            BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
255                    context.replaceTraceAndCache(temporaryForVariable),
256                    call, CheckValueArgumentsMode.ENABLED);
257            OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
258            if (resolutionResult.isSuccess()) {
259                temporaryForVariable.commit();
260                checkSuper(receiver, resolutionResult, context.trace, nameExpression);
261                result[0] = true;
262                return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
263            }
264    
265            ExpressionTypingContext newContext = receiver.exists()
266                                                 ? context.replaceScope(receiver.getType().getMemberScope())
267                                                 : context;
268            TemporaryTraceAndCache temporaryForPackageOrClassObject = TemporaryTraceAndCache.create(
269                    context, "trace to resolve as package or class object", nameExpression);
270            JetType jetType = lookupPackageOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForPackageOrClassObject));
271            if (jetType != null) {
272                temporaryForPackageOrClassObject.commit();
273    
274                // Uncommitted changes in temp context
275                context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
276                if (context.dataFlowInfo.hasTypeInfoConstraints()) {
277                    context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, nameExpression, context.dataFlowInfo);
278                }
279                result[0] = true;
280                return jetType;
281            }
282            temporaryForVariable.commit();
283            result[0] = !resolutionResult.isNothing();
284            return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
285        }
286    
287        @NotNull
288        public JetTypeInfo getSimpleNameExpressionTypeInfo(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver,
289                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
290        ) {
291            boolean[] result = new boolean[1];
292    
293            TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
294                    context, "trace to resolve as variable", nameExpression);
295            JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
296            if (result[0]) {
297                temporaryForVariable.commit();
298                if (type instanceof PackageType && !isLHSOfDot(nameExpression)) {
299                    type = null;
300                }
301                return JetTypeInfo.create(type, context.dataFlowInfo);
302            }
303    
304            Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList());
305            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
306                    context, "trace to resolve as function", nameExpression);
307            ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
308            ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
309                    call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
310            if (result[0]) {
311                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
312                temporaryForFunction.commit();
313                boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
314                context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
315                type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
316                return JetTypeInfo.create(type, context.dataFlowInfo);
317            }
318    
319            temporaryForVariable.commit();
320            return JetTypeInfo.create(null, context.dataFlowInfo);
321        }
322    
323        @NotNull
324        public JetTypeInfo getCallExpressionTypeInfo(
325                @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
326                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
327        ) {
328            JetTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
329            if (context.contextDependency == INDEPENDENT) {
330                DataFlowUtils.checkType(typeInfo, callExpression, context);
331            }
332            return typeInfo;
333        }
334    
335        @NotNull
336        public JetTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(
337                @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
338                @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
339        ) {
340            boolean[] result = new boolean[1];
341            Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
342    
343            TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
344                    context, "trace to resolve as function call", callExpression);
345            ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
346                    call, callExpression, context.replaceTraceAndCache(temporaryForFunction),
347                    CheckValueArgumentsMode.ENABLED, result);
348            if (result[0]) {
349                FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
350                temporaryForFunction.commit();
351                if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) {
352                    // there are only type arguments
353                    boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
354                    context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
355                }
356                if (functionDescriptor == null) {
357                    return JetTypeInfo.create(null, context.dataFlowInfo);
358                }
359                if (functionDescriptor instanceof ConstructorDescriptor && DescriptorUtils.isAnnotationClass(functionDescriptor.getContainingDeclaration())) {
360                    if (!canInstantiateAnnotationClass(callExpression)) {
361                        context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression));
362                    }
363                }
364    
365                JetType type = functionDescriptor.getReturnType();
366    
367                return JetTypeInfo.create(type, resolvedCall.getDataFlowInfoForArguments().getResultInfo());
368            }
369    
370            JetExpression calleeExpression = callExpression.getCalleeExpression();
371            if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
372                TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
373                        context, "trace to resolve as variable with 'invoke' call", callExpression);
374                JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode,
375                                               context.replaceTraceAndCache(temporaryForVariable), result);
376                if (result[0]) {
377                    temporaryForVariable.commit();
378                    context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
379                                                              type != null ? type : ErrorUtils.createErrorType("")));
380                    return JetTypeInfo.create(null, context.dataFlowInfo);
381                }
382            }
383            temporaryForFunction.commit();
384            return JetTypeInfo.create(null, context.dataFlowInfo);
385        }
386    
387        private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression) {
388            PsiElement parent = expression.getParent();
389            if (parent instanceof JetValueArgument) {
390                return PsiTreeUtil.getParentOfType(parent, JetAnnotationEntry.class) != null;
391            }
392            else if (parent instanceof JetParameter) {
393                JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
394                if (jetClass != null) {
395                    return jetClass.hasModifier(JetTokens.ANNOTATION_KEYWORD);
396                }
397            }
398            return false;
399        }
400    
401        private void checkSuper(@NotNull ReceiverValue receiverValue, @NotNull OverloadResolutionResults<? extends CallableDescriptor> results,
402                @NotNull BindingTrace trace, @NotNull JetExpression expression) {
403            if (!results.isSingleResult()) return;
404            if (!(receiverValue instanceof ExpressionReceiver)) return;
405            JetExpression receiver = ((ExpressionReceiver) receiverValue).getExpression();
406            CallableDescriptor descriptor = results.getResultingDescriptor();
407            if (receiver instanceof JetSuperExpression && descriptor instanceof MemberDescriptor) {
408                if (((MemberDescriptor) descriptor).getModality() == Modality.ABSTRACT) {
409                    trace.report(ABSTRACT_SUPER_CALL.on(expression));
410                }
411            }
412        }
413    
414        @NotNull
415        private JetTypeInfo getSelectorReturnTypeInfo(
416                @NotNull ReceiverValue receiver,
417                @Nullable ASTNode callOperationNode,
418                @NotNull JetExpression selectorExpression,
419                @NotNull ExpressionTypingContext context
420        ) {
421            if (selectorExpression instanceof JetCallExpression) {
422                return getCallExpressionTypeInfoWithoutFinalTypeCheck((JetCallExpression) selectorExpression, receiver,
423                                                                      callOperationNode, context);
424            }
425            else if (selectorExpression instanceof JetSimpleNameExpression) {
426                return getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
427            }
428            else {
429                context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
430            }
431            return JetTypeInfo.create(null, context.dataFlowInfo);
432        }
433    
434        @NotNull
435        public JetTypeInfo getQualifiedExpressionTypeInfo(
436                @NotNull JetQualifiedExpression expression, @NotNull ExpressionTypingContext context
437        ) {
438            // TODO : functions as values
439            JetExpression selectorExpression = expression.getSelectorExpression();
440            JetExpression receiverExpression = expression.getReceiverExpression();
441            ResolutionContext contextForReceiver = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
442            JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(receiverExpression, contextForReceiver);
443            JetType receiverType = receiverTypeInfo.getType();
444            if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
445            if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
446    
447            context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
448    
449            JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(
450                    new ExpressionReceiver(receiverExpression, receiverType),
451                    expression.getOperationTokenNode(), selectorExpression, context);
452            JetType selectorReturnType = selectorReturnTypeInfo.getType();
453    
454            //TODO move further
455            if (!(receiverType instanceof PackageType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
456                if (selectorReturnType != null && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) {
457                    if (receiverType.isNullable()) {
458                        selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
459                    }
460                }
461            }
462    
463            // TODO : this is suspicious: remove this code?
464            if (selectorReturnType != null) {
465                context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
466            }
467    
468            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType);
469                if (value != null && value.isPure()) {
470                    return BasicExpressionTypingVisitor.createCompileTimeConstantTypeInfo(value, expression, context);
471                }
472    
473            JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo());
474            if (context.contextDependency == INDEPENDENT) {
475                DataFlowUtils.checkType(typeInfo, expression, context);
476            }
477            return typeInfo;
478        }
479    }