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.tasks;
018    
019    import com.google.common.collect.Sets;
020    import com.intellij.lang.ASTNode;
021    import com.intellij.psi.PsiElement;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.kotlin.descriptors.*;
024    import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
025    import org.jetbrains.kotlin.lexer.KtToken;
026    import org.jetbrains.kotlin.lexer.KtTokens;
027    import org.jetbrains.kotlin.name.FqName;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.psi.*;
030    import org.jetbrains.kotlin.resolve.BindingTrace;
031    import org.jetbrains.kotlin.resolve.DescriptorUtils;
032    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
033    import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
034    import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
035    import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus;
036    import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
037    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
038    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
039    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
040    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
041    import org.jetbrains.kotlin.types.KotlinType;
042    import org.jetbrains.kotlin.types.Variance;
043    import org.jetbrains.kotlin.types.expressions.OperatorConventions;
044    
045    import java.util.Collection;
046    
047    import static org.jetbrains.kotlin.diagnostics.Errors.*;
048    import static org.jetbrains.kotlin.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
049    import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqNameFromTopLevelClass;
050    import static org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemUtilsKt.filterConstraintsOut;
051    import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION;
052    import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
053    
054    public abstract class AbstractTracingStrategy implements TracingStrategy {
055        protected final KtExpression reference;
056        protected final Call call;
057    
058        protected AbstractTracingStrategy(@NotNull KtExpression reference, @NotNull Call call) {
059            this.reference = reference;
060            this.call = call;
061        }
062    
063        @Override
064        public <D extends CallableDescriptor> void recordAmbiguity(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> candidates) {
065            Collection<D> descriptors = Sets.newHashSet();
066            for (ResolvedCall<D> candidate : candidates) {
067                descriptors.add(candidate.getCandidateDescriptor());
068            }
069            trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
070        }
071    
072        @Override
073        public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
074            KtElement reportOn = CallUtilKt.getValueArgumentListOrElement(call);
075            trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
076        }
077    
078        @Override
079        public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver) {
080            trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
081        }
082    
083        @Override
084        public void wrongReceiverType(
085                @NotNull BindingTrace trace,
086                @NotNull ReceiverParameterDescriptor receiverParameter,
087                @NotNull ReceiverValue receiverArgument,
088                @NotNull ResolutionContext<?> c
089        ) {
090            KtExpression reportOn = receiverArgument instanceof ExpressionReceiver
091                                    ? ((ExpressionReceiver) receiverArgument).getExpression()
092                                    : reference;
093    
094            if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(
095                    c, reportOn, receiverParameter.getType(), receiverArgument.getType())) {
096                trace.report(TYPE_MISMATCH.on(reportOn, receiverParameter.getType(), receiverArgument.getType()));
097            }
098        }
099    
100        @Override
101        public void noReceiverAllowed(@NotNull BindingTrace trace) {
102            trace.report(NO_RECEIVER_ALLOWED.on(reference));
103        }
104    
105        @Override
106        public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
107            KtTypeArgumentList typeArgumentList = call.getTypeArgumentList();
108            if (typeArgumentList != null) {
109                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
110            }
111            else {
112                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reference, expectedTypeArgumentCount));
113            }
114        }
115    
116        @Override
117        public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
118            trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(reference, descriptors));
119        }
120    
121        @Override
122        public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
123            trace.report(NONE_APPLICABLE.on(reference, descriptors));
124        }
125    
126        @Override
127        public <D extends CallableDescriptor> void cannotCompleteResolve(
128                @NotNull BindingTrace trace,
129                @NotNull Collection<? extends ResolvedCall<D>> descriptors
130        ) {
131            trace.report(CANNOT_COMPLETE_RESOLVE.on(reference, descriptors));
132        }
133    
134        @Override
135        public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
136            trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
137        }
138    
139        @Override
140        public void abstractSuperCall(@NotNull BindingTrace trace) {
141            trace.report(ABSTRACT_SUPER_CALL.on(reference));
142        }
143    
144        @Override
145        public void nestedClassAccessViaInstanceReference(
146                @NotNull BindingTrace trace,
147                @NotNull ClassDescriptor classDescriptor,
148                @NotNull ExplicitReceiverKind explicitReceiverKind
149        ) {
150            if (explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) {
151                DeclarationDescriptor importableDescriptor = DescriptorUtilsKt.getImportableDescriptor(classDescriptor);
152                if (DescriptorUtils.getFqName(importableDescriptor).isSafe()) {
153                    FqName fqName = getFqNameFromTopLevelClass(importableDescriptor);
154                    String qualifiedName;
155                    if (reference.getParent() instanceof KtCallableReferenceExpression) {
156                        qualifiedName = fqName.parent() + "::" + classDescriptor.getName();
157                    }
158                    else {
159                        qualifiedName = fqName.asString();
160                    }
161                    trace.report(NESTED_CLASS_SHOULD_BE_QUALIFIED.on(reference, classDescriptor, qualifiedName));
162                    return;
163                }
164            }
165            trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(reference, classDescriptor));
166        }
167    
168        @Override
169        public void unsafeCall(@NotNull BindingTrace trace, @NotNull KotlinType type, boolean isCallForImplicitInvoke) {
170            ASTNode callOperationNode = call.getCallOperationNode();
171            if (callOperationNode != null && !isCallForImplicitInvoke) {
172                trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
173            }
174            else {
175                PsiElement callElement = call.getCallElement();
176                if (callElement instanceof KtBinaryExpression) {
177                    KtBinaryExpression binaryExpression = (KtBinaryExpression)callElement;
178                    KtSimpleNameExpression operationReference = binaryExpression.getOperationReference();
179    
180                    Name operationString = operationReference.getReferencedNameElementType() == KtTokens.IDENTIFIER ?
181                                           Name.identifier(operationReference.getText()) :
182                                           OperatorConventions.getNameForOperationSymbol((KtToken) operationReference.getReferencedNameElementType());
183    
184                    KtExpression left = binaryExpression.getLeft();
185                    KtExpression right = binaryExpression.getRight();
186                    if (left != null && right != null) {
187                        trace.report(UNSAFE_INFIX_CALL.on(reference, left.getText(), operationString.asString(), right.getText()));
188                    }
189                }
190                else if (isCallForImplicitInvoke) {
191                    trace.report(UNSAFE_IMPLICIT_INVOKE_CALL.on(reference, type));
192                }
193                else {
194                    trace.report(UNSAFE_CALL.on(reference, type));
195                }
196            }
197        }
198    
199        @Override
200        public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {
201            trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor));
202        }
203    
204        @Override
205        public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data) {
206            ConstraintSystem constraintSystem = data.constraintSystem;
207            ConstraintSystemStatus status = constraintSystem.getStatus();
208            assert !status.isSuccessful() : "Report error only for not successful constraint system";
209    
210            if (status.hasErrorInConstrainingTypes()) {
211                // Do not report type inference errors if there is one in the arguments
212                // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
213                return;
214            }
215            BindingTrace trace = context.trace;
216            if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
217                KotlinType declaredReturnType = data.descriptor.getReturnType();
218                if (declaredReturnType == null) return;
219    
220                ConstraintSystem systemWithoutExpectedTypeConstraint = filterConstraintsOut(constraintSystem, EXPECTED_TYPE_POSITION);
221                KotlinType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(
222                        declaredReturnType, Variance.OUT_VARIANCE);
223                assert substitutedReturnType != null; //todo
224    
225                assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
226                if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(
227                        context, call.getCallElement(), data.expectedType, substitutedReturnType)) {
228                    trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(call.getCallElement(), data.expectedType, substitutedReturnType));
229                }
230            }
231            else if (status.hasCannotCaptureTypesError()) {
232                trace.report(TYPE_INFERENCE_CANNOT_CAPTURE_TYPES.on(reference, data));
233            }
234            else if (status.hasViolatedUpperBound()) {
235                trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data));
236            }
237            else if (status.hasParameterConstraintError()) {
238                trace.report(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR.on(reference, data));
239            }
240            else if (status.hasConflictingConstraints()) {
241                trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data));
242            }
243            else if (status.hasTypeInferenceIncorporationError()) {
244                trace.report(TYPE_INFERENCE_INCORPORATION_ERROR.on(reference));
245            }
246            else if (status.hasTypeParameterWithUnsatisfiedOnlyInputTypesError()) {
247                //todo
248                trace.report(TYPE_INFERENCE_ONLY_INPUT_TYPES.on(reference, data.descriptor.getTypeParameters().get(0)));
249            }
250            else {
251                assert status.hasUnknownParameters();
252                trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
253            }
254        }
255    
256        @Override
257        public void nonExtensionFunctionCalledAsExtension(@NotNull BindingTrace trace) {
258            trace.report(INVOKE_EXTENSION_ON_NOT_EXTENSION_FUNCTION.on(reference, reference));
259        }
260    }