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