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