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 017package org.jetbrains.jet.lang.resolve.calls.tasks; 018 019import com.google.common.collect.Sets; 020import com.intellij.lang.ASTNode; 021import com.intellij.psi.PsiElement; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.jet.lang.descriptors.*; 024import org.jetbrains.jet.lang.diagnostics.Errors; 025import org.jetbrains.jet.lang.psi.*; 026import org.jetbrains.jet.lang.resolve.BindingTrace; 027import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; 028import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData; 029import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; 030import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; 031import org.jetbrains.jet.lang.resolve.name.Name; 032import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; 033import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 034import org.jetbrains.jet.lang.types.ErrorUtils; 035import org.jetbrains.jet.lang.types.JetType; 036import org.jetbrains.jet.lang.types.TypeUtils; 037import org.jetbrains.jet.lang.types.Variance; 038import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 039import org.jetbrains.jet.lexer.JetToken; 040import org.jetbrains.jet.lexer.JetTokens; 041 042import java.util.Collection; 043import java.util.List; 044 045import static org.jetbrains.jet.lang.diagnostics.Errors.*; 046import static org.jetbrains.jet.lang.resolve.BindingContext.*; 047 048public 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}