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.model; 018 019import com.google.common.collect.Maps; 020import com.google.common.collect.Sets; 021import com.intellij.util.Function; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.annotations.Nullable; 024import org.jetbrains.jet.lang.descriptors.CallableDescriptor; 025import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 026import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; 027import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; 028import org.jetbrains.jet.lang.psi.ValueArgument; 029import org.jetbrains.jet.lang.resolve.*; 030import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 031import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext; 032import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind; 033import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate; 034import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus; 035import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; 036import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy; 037import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 038import org.jetbrains.jet.lang.types.JetType; 039import org.jetbrains.jet.lang.types.TypeSubstitutor; 040 041import java.util.*; 042 043import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE; 044import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS; 045 046public 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}