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.model;
018
019 import com.google.common.collect.Maps;
020 import com.google.common.collect.Sets;
021 import com.intellij.util.Function;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
025 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
026 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
027 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
028 import org.jetbrains.jet.lang.psi.ValueArgument;
029 import org.jetbrains.jet.lang.resolve.*;
030 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
031 import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
032 import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
033 import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
034 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
035 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
036 import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
037 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
038 import org.jetbrains.jet.lang.types.JetType;
039 import org.jetbrains.jet.lang.types.TypeSubstitutor;
040
041 import java.util.*;
042
043 import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE;
044 import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
045
046 public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedCallWithTrace<D> {
047
048 public static final Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor>() {
049 @Override
050 public CallableDescriptor fun(ResolvedCallWithTrace<? extends CallableDescriptor> resolvedCall) {
051 return resolvedCall.getCandidateDescriptor();
052 }
053 };
054
055 public static final Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_RESULT = new Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor>() {
056 @Override
057 public CallableDescriptor fun(ResolvedCallWithTrace<? extends CallableDescriptor> resolvedCall) {
058 return resolvedCall.getResultingDescriptor();
059 }
060 };
061
062 @NotNull
063 public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate, @NotNull DelegatingBindingTrace trace,
064 @NotNull TracingStrategy tracing) {
065 return new ResolvedCallImpl<D>(candidate, trace, tracing);
066 }
067
068 private final D candidateDescriptor;
069 private D resultingDescriptor; // Probably substituted
070 private final ReceiverValue thisObject; // receiver object of a method
071 private final ReceiverValue receiverArgument; // receiver of an extension function
072 private final ExplicitReceiverKind explicitReceiverKind;
073 private final boolean isSafeCall;
074
075 private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
076 private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
077 private final Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
078 private boolean someArgumentHasNoType = false;
079 private final DelegatingBindingTrace trace;
080 private final TracingStrategy tracing;
081 private ResolutionStatus status = UNKNOWN_STATUS;
082 private boolean hasUnknownTypeParameters = false;
083 private ConstraintSystem constraintSystem = null;
084 private DataFlowInfo dataFlowInfo;
085
086 private ResolvedCallImpl(@NotNull ResolutionCandidate<D> candidate, @NotNull DelegatingBindingTrace trace, @NotNull TracingStrategy tracing) {
087 this.candidateDescriptor = candidate.getDescriptor();
088 this.thisObject = candidate.getThisObject();
089 this.receiverArgument = candidate.getReceiverArgument();
090 this.explicitReceiverKind = candidate.getExplicitReceiverKind();
091 this.isSafeCall = candidate.isSafeCall();
092 this.trace = trace;
093 this.tracing = tracing;
094 }
095
096 @Override
097 @NotNull
098 public ResolutionStatus getStatus() {
099 return status;
100 }
101
102 public void addStatus(@NotNull ResolutionStatus status) {
103 this.status = this.status.combine(status);
104 }
105
106 public void setStatusToSuccess() {
107 assert status == INCOMPLETE_TYPE_INFERENCE || status == UNKNOWN_STATUS;
108 status = ResolutionStatus.SUCCESS;
109 }
110
111 @Override
112 public boolean hasIncompleteTypeParameters() {
113 return hasUnknownTypeParameters;
114 }
115
116 public void setHasUnknownTypeParameters(boolean hasUnknownTypeParameters) {
117 this.hasUnknownTypeParameters = hasUnknownTypeParameters;
118 }
119
120 @Override
121 @NotNull
122 public DelegatingBindingTrace getTrace() {
123 return trace;
124 }
125
126 @NotNull
127 public TracingStrategy getTracing() {
128 return tracing;
129 }
130
131 @Override
132 @NotNull
133 public D getCandidateDescriptor() {
134 return candidateDescriptor;
135 }
136
137 @Override
138 @NotNull
139 public D getResultingDescriptor() {
140 return resultingDescriptor == null ? candidateDescriptor : resultingDescriptor;
141 }
142
143 public void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor) {
144 resultingDescriptor = (D) candidateDescriptor.substitute(substitutor);
145 assert resultingDescriptor != null : candidateDescriptor;
146
147 Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
148 for (ValueParameterDescriptor valueParameterDescriptor : resultingDescriptor.getValueParameters()) {
149 parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
150 }
151
152 Map<ValueParameterDescriptor, ResolvedValueArgument> originalValueArguments = Maps.newLinkedHashMap(valueArguments);
153 valueArguments.clear();
154 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : originalValueArguments.entrySet()) {
155 ValueParameterDescriptor substitutedVersion = parameterMap.get(entry.getKey().getOriginal());
156 assert substitutedVersion != null : entry.getKey();
157 valueArguments.put(substitutedVersion, entry.getValue());
158 }
159 }
160
161 public void recordTypeArgument(@NotNull TypeParameterDescriptor typeParameter, @NotNull JetType typeArgument) {
162 assert !typeArguments.containsKey(typeParameter) : typeParameter + " -> " + typeArgument;
163 typeArguments.put(typeParameter, typeArgument);
164 }
165
166 public void setConstraintSystem(@NotNull ConstraintSystem constraintSystem) {
167 this.constraintSystem = constraintSystem;
168 }
169
170 @Nullable
171 public ConstraintSystem getConstraintSystem() {
172 return constraintSystem;
173 }
174
175 public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) {
176 assert !valueArguments.containsKey(valueParameter) : valueParameter + " -> " + valueArgument;
177 valueArguments.put(valueParameter, valueArgument);
178 }
179
180 public void setUnmappedArguments(@NotNull Collection<ValueArgument> unmappedArguments) {
181 this.unmappedArguments.addAll(unmappedArguments);
182
183 }
184
185 @NotNull
186 public Set<ValueArgument> getUnmappedArguments() {
187 return unmappedArguments;
188 }
189
190 @Override
191 @NotNull
192 public ReceiverValue getReceiverArgument() {
193 return receiverArgument;
194 }
195
196 @Override
197 @NotNull
198 public ReceiverValue getThisObject() {
199 return thisObject;
200 }
201
202 @Override
203 @NotNull
204 public ExplicitReceiverKind getExplicitReceiverKind() {
205 return explicitReceiverKind;
206 }
207
208 @Override
209 @NotNull
210 public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
211 return valueArguments;
212 }
213
214 @NotNull
215 @Override
216 public List<ResolvedValueArgument> getValueArgumentsByIndex() {
217 List<ResolvedValueArgument> arguments = new ArrayList<ResolvedValueArgument>(candidateDescriptor.getValueParameters().size());
218 for (int i = 0; i < candidateDescriptor.getValueParameters().size(); ++i) {
219 arguments.add(null);
220 }
221
222 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : valueArguments.entrySet()) {
223 if (arguments.set(entry.getKey().getIndex(), entry.getValue()) != null) {
224 throw new IllegalStateException();
225 }
226 }
227
228 for (Object o : arguments) {
229 if (o == null) {
230 throw new IllegalStateException();
231 }
232 }
233
234 return arguments;
235 }
236
237 public void argumentHasNoType() {
238 this.someArgumentHasNoType = true;
239 }
240
241 @Override
242 public boolean isDirty() {
243 return someArgumentHasNoType;
244 }
245
246 @NotNull
247 @Override
248 public Map<TypeParameterDescriptor, JetType> getTypeArguments() {
249 return typeArguments;
250 }
251
252 @Override
253 public boolean isSafeCall() {
254 return isSafeCall;
255 }
256
257 @NotNull
258 @Override
259 public DataFlowInfo getDataFlowInfo() {
260 return dataFlowInfo;
261 }
262
263 public void setInitialDataFlowInfo(@NotNull DataFlowInfo info) {
264 assert dataFlowInfo == null;
265 dataFlowInfo = info;
266 }
267
268 public void addDataFlowInfo(@NotNull DataFlowInfo info) {
269 assert dataFlowInfo != null;
270 dataFlowInfo = dataFlowInfo.and(info);
271 }
272
273 @NotNull
274 @Override
275 public ResolvedCallImpl<D> getCallToCompleteTypeArgumentInference() {
276 return this;
277 }
278 }