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.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.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.diagnostics.Errors;
025    import org.jetbrains.jet.lang.psi.*;
026    import org.jetbrains.jet.lang.resolve.BindingTrace;
027    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
028    import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData;
029    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
030    import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
031    import org.jetbrains.jet.lang.resolve.name.Name;
032    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
033    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
034    import org.jetbrains.jet.lang.types.ErrorUtils;
035    import org.jetbrains.jet.lang.types.JetType;
036    import org.jetbrains.jet.lang.types.TypeUtils;
037    import org.jetbrains.jet.lang.types.Variance;
038    import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
039    import org.jetbrains.jet.lexer.JetToken;
040    import org.jetbrains.jet.lexer.JetTokens;
041    
042    import java.util.Collection;
043    import java.util.List;
044    
045    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
046    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
047    
048    public class TracingStrategyImpl implements TracingStrategy {
049        private final JetReferenceExpression reference;
050        private final Call call;
051    
052        private TracingStrategyImpl(@NotNull JetReferenceExpression reference, @NotNull Call call) {
053            this.reference = reference;
054            this.call = call;
055        }
056    
057        @NotNull
058        public static TracingStrategy create(@NotNull JetReferenceExpression reference, @NotNull Call call) {
059            return new TracingStrategyImpl(reference, call);
060        }
061    
062        @Override
063        public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall) {
064            CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
065            if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
066                descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getResultingDescriptor();
067            }
068            DeclarationDescriptor storedReference = trace.get(REFERENCE_TARGET, reference);
069            if (storedReference == null || !ErrorUtils.isError(descriptor)) {
070                trace.record(REFERENCE_TARGET, reference, descriptor);
071            }
072        }
073    
074        @Override
075        public <D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall) {
076            trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
077            trace.record(CALL, call.getCalleeExpression(), call);
078        }
079    
080        @Override
081        public <D extends CallableDescriptor> void recordAmbiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> candidates) {
082            Collection<D> descriptors = Sets.newHashSet();
083            for (ResolvedCallWithTrace<D> candidate : candidates) {
084                descriptors.add(candidate.getCandidateDescriptor());
085            }
086            trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
087        }
088    
089        @Override
090        public void unresolvedReference(@NotNull BindingTrace trace) {
091            trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
092        }
093    
094        @Override
095        public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> candidates) {
096            trace.report(UNRESOLVED_REFERENCE_WRONG_RECEIVER.on(reference, candidates));
097        }
098    
099        @Override
100        public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
101            JetElement reportOn;
102            JetValueArgumentList valueArgumentList = call.getValueArgumentList();
103            if (valueArgumentList != null) {
104                reportOn = valueArgumentList;
105            }
106            else {
107                reportOn = reference;
108            }
109            trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
110        }
111    
112        @Override
113        public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver) {
114            trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
115        }
116    
117        @Override
118        public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument) {
119            if (receiverArgument instanceof ExpressionReceiver) {
120                ExpressionReceiver expressionReceiver = (ExpressionReceiver)receiverArgument;
121                trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
122            }
123            else {
124                trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
125            }
126        }
127    
128        @Override
129        public void noReceiverAllowed(@NotNull BindingTrace trace) {
130            trace.report(NO_RECEIVER_ADMITTED.on(reference));
131        }
132    
133        @Override
134        public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
135            JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
136            if (typeArgumentList != null) {
137                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
138            }
139            else {
140                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reference, expectedTypeArgumentCount));
141            }
142        }
143    
144        @Override
145        public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {
146            trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors));
147        }
148    
149        @Override
150        public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {
151            trace.report(NONE_APPLICABLE.on(reference, descriptors));
152        }
153    
154        @Override
155        public <D extends CallableDescriptor> void cannotCompleteResolve(
156                @NotNull BindingTrace trace,
157                @NotNull Collection<ResolvedCallWithTrace<D>> descriptors
158        ) {
159            trace.report(CANNOT_COMPLETE_RESOLVE.on(reference, descriptors));
160        }
161    
162        @Override
163        public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
164            trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
165        }
166    
167        @Override
168        public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType 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 JetBinaryExpression) {
176                    JetBinaryExpression binaryExpression = (JetBinaryExpression)callElement;
177                    JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
178    
179                    Name operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ?
180                            Name.identifier(operationReference.getText()) :
181                            OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
182    
183                    JetExpression left = binaryExpression.getLeft();
184                    JetExpression 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 {
190                    trace.report(UNSAFE_CALL.on(reference, type));
191                }
192            }
193        }
194    
195        @Override
196        public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
197            ASTNode callOperationNode = call.getCallOperationNode();
198            assert callOperationNode != null;
199            trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
200        }
201    
202        @Override
203        public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {
204            for (JetExpression functionLiteralArgument : functionLiteralArguments) {
205                trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument));
206            }
207        }
208    
209        @Override
210        public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {
211            trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration()));
212        }
213    
214        @Override
215        public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData.ExtendedInferenceErrorData data) {
216            ConstraintSystem constraintSystem = data.constraintSystem;
217            assert !constraintSystem.isSuccessful() : "Report error only for not successful constraint system";
218    
219            if (constraintSystem.hasErrorInConstrainingTypes()) {
220                // Do not report type inference errors if there is one in the arguments
221                // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
222                return;
223            }
224            if (constraintSystem.hasOnlyExpectedTypeMismatch()) {
225                JetType declaredReturnType = data.descriptor.getReturnType();
226                if (declaredReturnType == null) return;
227    
228                JetType substitutedReturnType = constraintSystem.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
229                assert substitutedReturnType != null; //todo
230    
231                assert data.expectedType != TypeUtils.NO_EXPECTED_TYPE : "Expected type doesn't exist, but there is an expected type mismatch error";
232                trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, substitutedReturnType, data.expectedType));
233            }
234            else if (constraintSystem.hasTypeConstructorMismatch()) {
235                trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
236            }
237            else if (constraintSystem.hasConflictingConstraints()) {
238                trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data));
239            }
240            else {
241                assert constraintSystem.hasUnknownParameters();
242                trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
243            }
244        }
245    
246        @Override
247        public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {
248            trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, inferenceErrorData));
249        }
250    }