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