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