001    /*
002     * Copyright 2010-2014 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.CallableDescriptor;
024    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorWithVisibility;
025    import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
026    import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
027    import org.jetbrains.jet.lang.psi.*;
028    import org.jetbrains.jet.lang.psi.codeFragmentUtil.CodeFragmentUtilPackage;
029    import org.jetbrains.jet.lang.resolve.BindingTrace;
030    import org.jetbrains.jet.lang.resolve.calls.inference.*;
031    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
032    import org.jetbrains.jet.lang.resolve.name.Name;
033    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
034    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
035    import org.jetbrains.jet.lang.types.JetType;
036    import org.jetbrains.jet.lang.types.Variance;
037    import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
038    import org.jetbrains.jet.lexer.JetToken;
039    import org.jetbrains.jet.lexer.JetTokens;
040    
041    import java.util.Collection;
042    import java.util.List;
043    
044    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
045    import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
046    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
047    
048    public abstract class AbstractTracingStrategy implements TracingStrategy {
049        protected final JetExpression reference;
050        protected final Call call;
051    
052        protected AbstractTracingStrategy(@NotNull JetExpression reference, @NotNull Call call) {
053            this.reference = reference;
054            this.call = call;
055        }
056    
057        @Override
058        public <D extends CallableDescriptor> void recordAmbiguity(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> candidates) {
059            Collection<D> descriptors = Sets.newHashSet();
060            for (ResolvedCall<D> candidate : candidates) {
061                descriptors.add(candidate.getCandidateDescriptor());
062            }
063            trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
064        }
065    
066        @Override
067        public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
068            JetElement reportOn;
069            JetValueArgumentList valueArgumentList = call.getValueArgumentList();
070            if (valueArgumentList != null) {
071                reportOn = valueArgumentList;
072            }
073            else {
074                reportOn = reference;
075            }
076            trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
077        }
078    
079        @Override
080        public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor expectedReceiver) {
081            trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
082        }
083    
084        @Override
085        public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverParameterDescriptor receiverParameter, @NotNull ReceiverValue receiverArgument) {
086            if (receiverArgument instanceof ExpressionReceiver) {
087                ExpressionReceiver expressionReceiver = (ExpressionReceiver)receiverArgument;
088                trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
089            }
090            else {
091                trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
092            }
093        }
094    
095        @Override
096        public void noReceiverAllowed(@NotNull BindingTrace trace) {
097            trace.report(NO_RECEIVER_ADMITTED.on(reference));
098        }
099    
100        @Override
101        public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
102            JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
103            if (typeArgumentList != null) {
104                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
105            }
106            else {
107                trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reference, expectedTypeArgumentCount));
108            }
109        }
110    
111        @Override
112        public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
113            trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(reference, descriptors));
114        }
115    
116        @Override
117        public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> descriptors) {
118            trace.report(NONE_APPLICABLE.on(reference, descriptors));
119        }
120    
121        @Override
122        public <D extends CallableDescriptor> void cannotCompleteResolve(
123                @NotNull BindingTrace trace,
124                @NotNull Collection<? extends ResolvedCall<D>> descriptors
125        ) {
126            trace.report(CANNOT_COMPLETE_RESOLVE.on(reference, descriptors));
127        }
128    
129        @Override
130        public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
131            trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
132        }
133    
134        @Override
135        public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {
136            ASTNode callOperationNode = call.getCallOperationNode();
137            if (callOperationNode != null && !isCallForImplicitInvoke) {
138                trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
139            }
140            else {
141                PsiElement callElement = call.getCallElement();
142                if (callElement instanceof JetBinaryExpression) {
143                    JetBinaryExpression binaryExpression = (JetBinaryExpression)callElement;
144                    JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
145    
146                    Name operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ?
147                                           Name.identifier(operationReference.getText()) :
148                                           OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
149    
150                    JetExpression left = binaryExpression.getLeft();
151                    JetExpression right = binaryExpression.getRight();
152                    if (left != null && right != null) {
153                        trace.report(UNSAFE_INFIX_CALL.on(reference, left.getText(), operationString.asString(), right.getText()));
154                    }
155                }
156                else {
157                    trace.report(UNSAFE_CALL.on(reference, type));
158                }
159            }
160        }
161    
162        @Override
163        public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
164            ASTNode callOperationNode = call.getCallOperationNode();
165            assert callOperationNode != null;
166            trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
167        }
168    
169        @Override
170        public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {
171            for (JetExpression functionLiteralArgument : functionLiteralArguments) {
172                trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument));
173            }
174        }
175    
176        @Override
177        public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor) {
178            if (!CodeFragmentUtilPackage.skipVisibilityCheck(call.getCallElement().getContainingJetFile())) {
179                trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration()));
180            }
181        }
182    
183        @Override
184        public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData data) {
185            ConstraintSystem constraintSystem = data.constraintSystem;
186            ConstraintSystemStatus status = constraintSystem.getStatus();
187            assert !status.isSuccessful() : "Report error only for not successful constraint system";
188    
189            if (status.hasErrorInConstrainingTypes()) {
190                // Do not report type inference errors if there is one in the arguments
191                // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
192                return;
193            }
194            if (status.hasOnlyErrorsFromPosition(ConstraintPosition.EXPECTED_TYPE_POSITION)) {
195                JetType declaredReturnType = data.descriptor.getReturnType();
196                if (declaredReturnType == null) return;
197    
198                ConstraintSystem systemWithoutExpectedTypeConstraint =
199                        ((ConstraintSystemImpl) constraintSystem).filterConstraintsOut(ConstraintPosition.EXPECTED_TYPE_POSITION);
200                JetType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(declaredReturnType, Variance.INVARIANT);
201                assert substitutedReturnType != null; //todo
202    
203                assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
204                trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, data.expectedType, substitutedReturnType));
205            }
206            else if (status.hasViolatedUpperBound()) {
207                trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data));
208            }
209            else if (status.hasTypeConstructorMismatch()) {
210                trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
211            }
212            else if (status.hasConflictingConstraints()) {
213                trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data));
214            }
215            else {
216                assert status.hasUnknownParameters();
217                trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
218            }
219        }
220    
221    }