001    /*
002     * Copyright 2010-2016 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(
107                @NotNull BindingTrace trace, int expectedTypeArgumentCount, @NotNull CallableDescriptor descriptor
108        ) {
109            KtTypeArgumentList typeArgumentList = call.getTypeArgumentList();
110            trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(
111                    typeArgumentList != null ? typeArgumentList : reference, expectedTypeArgumentCount, descriptor
112            ));
113        }
114    
115        @Override
116        public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
117            trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(reference, descriptors));
118        }
119    
120        @Override
121        public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
122            trace.report(NONE_APPLICABLE.on(reference, descriptors));
123        }
124    
125        @Override
126        public <D extends CallableDescriptor> void cannotCompleteResolve(
127                @NotNull BindingTrace trace,
128                @NotNull Collection<? extends ResolvedCall<D>> descriptors
129        ) {
130            trace.report(CANNOT_COMPLETE_RESOLVE.on(reference, descriptors));
131        }
132    
133        @Override
134        public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
135            trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
136        }
137    
138        @Override
139        public void abstractSuperCall(@NotNull BindingTrace trace) {
140            trace.report(ABSTRACT_SUPER_CALL.on(reference));
141        }
142    
143        @Override
144        public void nestedClassAccessViaInstanceReference(
145                @NotNull BindingTrace trace,
146                @NotNull ClassDescriptor classDescriptor,
147                @NotNull ExplicitReceiverKind explicitReceiverKind
148        ) {
149            if (explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) {
150                DeclarationDescriptor importableDescriptor = DescriptorUtilsKt.getImportableDescriptor(classDescriptor);
151                if (DescriptorUtils.getFqName(importableDescriptor).isSafe()) {
152                    FqName fqName = getFqNameFromTopLevelClass(importableDescriptor);
153                    String qualifiedName;
154                    if (reference.getParent() instanceof KtCallableReferenceExpression) {
155                        qualifiedName = fqName.parent() + "::" + classDescriptor.getName();
156                    }
157                    else {
158                        qualifiedName = fqName.asString();
159                    }
160                    trace.report(NESTED_CLASS_SHOULD_BE_QUALIFIED.on(reference, classDescriptor, qualifiedName));
161                    return;
162                }
163            }
164            trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(reference, classDescriptor));
165        }
166    
167        @Override
168        public void unsafeCall(@NotNull BindingTrace trace, @NotNull KotlinType type, boolean isCallForImplicitInvoke) {
169            ASTNode callOperationNode = call.getCallOperationNode();
170            if (callOperationNode != null && !isCallForImplicitInvoke) {
171                trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
172            }
173            else {
174                PsiElement callElement = call.getCallElement();
175                if (callElement instanceof KtBinaryExpression) {
176                    KtBinaryExpression binaryExpression = (KtBinaryExpression)callElement;
177                    KtSimpleNameExpression operationReference = binaryExpression.getOperationReference();
178    
179                    Name operationString = operationReference.getReferencedNameElementType() == KtTokens.IDENTIFIER ?
180                                           Name.identifier(operationReference.getText()) :
181                                           OperatorConventions.getNameForOperationSymbol((KtToken) operationReference.getReferencedNameElementType());
182    
183                    KtExpression left = binaryExpression.getLeft();
184                    KtExpression right = binaryExpression.getRight();
185                    if (left != null && right != null) {
186                        trace.report(UNSAFE_INFIX_CALL.on(reference, left.getText(), operationString.asString(), right.getText()));
187                    }
188                }
189                else if (isCallForImplicitInvoke) {
190                    trace.report(UNSAFE_IMPLICIT_INVOKE_CALL.on(reference, type));
191                }
192                else {
193                    trace.report(UNSAFE_CALL.on(reference, type));
194                }
195            }
196        }
197    
198        @Override
199        public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {
200            trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor));
201        }
202    
203        @Override
204        public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data) {
205            ConstraintSystem constraintSystem = data.constraintSystem;
206            ConstraintSystemStatus status = constraintSystem.getStatus();
207            assert !status.isSuccessful() : "Report error only for not successful constraint system";
208    
209            if (status.hasErrorInConstrainingTypes()) {
210                // Do not report type inference errors if there is one in the arguments
211                // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
212                return;
213            }
214            BindingTrace trace = context.trace;
215            if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
216                KotlinType declaredReturnType = data.descriptor.getReturnType();
217                if (declaredReturnType == null) return;
218    
219                ConstraintSystem systemWithoutExpectedTypeConstraint = filterConstraintsOut(constraintSystem, EXPECTED_TYPE_POSITION);
220                KotlinType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(
221                        declaredReturnType, Variance.OUT_VARIANCE);
222                assert substitutedReturnType != null; //todo
223    
224                assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
225                if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(
226                        context, call.getCallElement(), data.expectedType, substitutedReturnType)) {
227                    trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(call.getCallElement(), data.expectedType, substitutedReturnType));
228                }
229            }
230            else if (status.hasCannotCaptureTypesError()) {
231                trace.report(TYPE_INFERENCE_CANNOT_CAPTURE_TYPES.on(reference, data));
232            }
233            else if (status.hasViolatedUpperBound()) {
234                trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data));
235            }
236            else if (status.hasParameterConstraintError()) {
237                trace.report(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR.on(reference, data));
238            }
239            else if (status.hasConflictingConstraints()) {
240                trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data));
241            }
242            else if (status.hasTypeInferenceIncorporationError()) {
243                trace.report(TYPE_INFERENCE_INCORPORATION_ERROR.on(reference));
244            }
245            else if (status.hasTypeParameterWithUnsatisfiedOnlyInputTypesError()) {
246                //todo
247                trace.report(TYPE_INFERENCE_ONLY_INPUT_TYPES.on(reference, data.descriptor.getTypeParameters().get(0)));
248            }
249            else {
250                assert status.hasUnknownParameters();
251                trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
252            }
253        }
254    }