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