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    }