001 /*
002 * Copyright 2010-2015 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.kotlin.resolve.calls.util;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.lang.ASTNode;
021 import com.intellij.psi.impl.source.tree.LeafPsiElement;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.kotlin.psi.*;
025 import org.jetbrains.kotlin.psi.Call.CallType;
026 import org.jetbrains.kotlin.psi.debugText.DebugTextPackage;
027 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
028
029 import java.util.ArrayList;
030 import java.util.Collections;
031 import java.util.List;
032
033 public class CallMaker {
034
035 private static class ExpressionValueArgument implements ValueArgument {
036
037 private final JetExpression expression;
038
039 private final JetElement reportErrorsOn;
040
041 private final boolean isExternal;
042
043 private ExpressionValueArgument(
044 @Nullable JetExpression expression,
045 @NotNull JetElement reportErrorsOn,
046 boolean isExternal
047 ) {
048 this.expression = expression;
049 this.reportErrorsOn = expression == null ? reportErrorsOn : expression;
050 this.isExternal = isExternal;
051 }
052
053 @Override
054 public boolean isExternal() {
055 return isExternal;
056 }
057
058 @Override
059 public JetExpression getArgumentExpression() {
060 return expression;
061 }
062
063 @Override
064 public ValueArgumentName getArgumentName() {
065 return null;
066 }
067
068 @Override
069 public boolean isNamed() {
070 return false;
071 }
072
073 @NotNull
074 @Override
075 public JetElement asElement() {
076 return reportErrorsOn;
077 }
078
079 @Override
080 public LeafPsiElement getSpreadElement() {
081 return null;
082 }
083
084 @Override
085 public boolean equals(Object o) {
086 if (this == o) return true;
087 if (o == null || getClass() != o.getClass()) return false;
088
089 ExpressionValueArgument argument = (ExpressionValueArgument) o;
090
091 if (expression != null ? !expression.equals(argument.expression) : argument.expression != null) return false;
092
093 return true;
094 }
095
096 @Override
097 public int hashCode() {
098 return expression != null ? expression.hashCode() : 0;
099 }
100 }
101
102 private static class CallImpl implements Call {
103
104 private final JetElement callElement;
105 private final ReceiverValue explicitReceiver;
106 private final ASTNode callOperationNode;
107 private final JetExpression calleeExpression;
108 private final List<? extends ValueArgument> valueArguments;
109 private final Call.CallType callType;
110
111 protected CallImpl(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @Nullable JetExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments) {
112 this(callElement, explicitReceiver, callOperationNode, calleeExpression, valueArguments, CallType.DEFAULT);
113 }
114
115 protected CallImpl(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
116 @Nullable JetExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments, @NotNull CallType callType) {
117 this.callElement = callElement;
118 this.explicitReceiver = explicitReceiver;
119 this.callOperationNode = callOperationNode;
120 this.calleeExpression = calleeExpression;
121 this.valueArguments = valueArguments;
122 this.callType = callType;
123 }
124
125 @Override
126 public ASTNode getCallOperationNode() {
127 return callOperationNode;
128 }
129
130 @NotNull
131 @Override
132 public ReceiverValue getExplicitReceiver() {
133 return explicitReceiver;
134 }
135
136 @NotNull
137 @Override
138 public ReceiverValue getDispatchReceiver() {
139 return ReceiverValue.NO_RECEIVER;
140 }
141
142 @Override
143 public JetExpression getCalleeExpression() {
144 return calleeExpression;
145 }
146
147 @NotNull
148 @Override
149 public List<? extends ValueArgument> getValueArguments() {
150 return valueArguments;
151 }
152
153 @NotNull
154 @Override
155 public JetElement getCallElement() {
156 return callElement;
157 }
158
159 @Override
160 public JetValueArgumentList getValueArgumentList() {
161 return null;
162 }
163
164 @NotNull
165 @Override
166 public List<FunctionLiteralArgument> getFunctionLiteralArguments() {
167 return Collections.emptyList();
168 }
169 @NotNull
170 @Override
171 public List<JetTypeProjection> getTypeArguments() {
172 return Collections.emptyList();
173 }
174
175 @Override
176 public JetTypeArgumentList getTypeArgumentList() {
177 return null;
178 }
179
180 @Override
181 public String toString() {
182 return getCallElement().getText();
183 }
184
185 @NotNull
186 @Override
187 public CallType getCallType() {
188 return callType;
189 }
190 }
191
192 @NotNull
193 public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
194 @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
195 @NotNull List<JetExpression> argumentExpressions) {
196 return makeCallWithExpressions(callElement, explicitReceiver, callOperationNode, calleeExpression, argumentExpressions, CallType.DEFAULT);
197 }
198
199 @NotNull
200 public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
201 @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
202 @NotNull List<JetExpression> argumentExpressions, @NotNull CallType callType) {
203 List<ValueArgument> arguments = new ArrayList<ValueArgument>(argumentExpressions.size());
204 for (JetExpression argumentExpression : argumentExpressions) {
205 arguments.add(makeValueArgument(argumentExpression, calleeExpression));
206 }
207 return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
208 }
209
210 @NotNull
211 public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, JetExpression calleeExpression, List<? extends ValueArgument> arguments) {
212 return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, CallType.DEFAULT);
213 }
214
215 @NotNull
216 public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
217 JetExpression calleeExpression, List<? extends ValueArgument> arguments, CallType callType) {
218 return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
219 }
220
221 @NotNull
222 public static Call makeCall(@NotNull ReceiverValue leftAsReceiver, JetBinaryExpression expression) {
223 return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
224 }
225
226 @NotNull
227 public static Call makeCall(@NotNull ReceiverValue baseAsReceiver, JetUnaryExpression expression) {
228 return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.<ValueArgument>emptyList());
229 }
230
231 @NotNull
232 public static Call makeArraySetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
233 @NotNull JetExpression rightHandSide, @NotNull CallType callType) {
234 List<JetExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
235 arguments.add(rightHandSide);
236 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments, callType);
237 }
238
239 @NotNull
240 public static Call makeArrayGetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
241 @NotNull CallType callType) {
242 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
243 }
244
245 @NotNull
246 public static ValueArgument makeValueArgument(@NotNull JetExpression expression) {
247 return makeValueArgument(expression, expression);
248 }
249
250 @NotNull
251 public static ValueArgument makeValueArgument(@Nullable JetExpression expression, @NotNull JetElement reportErrorsOn) {
252 return new ExpressionValueArgument(expression, reportErrorsOn, false);
253 }
254
255 @NotNull
256 public static ValueArgument makeExternalValueArgument(@NotNull JetExpression expression) {
257 return new ExpressionValueArgument(expression, expression, true);
258 }
259
260 @NotNull
261 public static Call makePropertyCall(@NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
262 return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<JetExpression>emptyList());
263 }
264
265 @NotNull
266 public static Call makeCall(@NotNull final ReceiverValue explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final JetCallElement callElement) {
267 return new Call() {
268 @Override
269 public ASTNode getCallOperationNode() {
270 return callOperationNode;
271 }
272
273 @NotNull
274 @Override
275 public ReceiverValue getExplicitReceiver() {
276 return explicitReceiver;
277 }
278
279 @NotNull
280 @Override
281 public ReceiverValue getDispatchReceiver() {
282 return ReceiverValue.NO_RECEIVER;
283 }
284
285 @Override
286 @Nullable
287 public JetExpression getCalleeExpression() {
288 return callElement.getCalleeExpression();
289 }
290
291 @Override
292 @Nullable
293 public JetValueArgumentList getValueArgumentList() {
294 return callElement.getValueArgumentList();
295 }
296
297 @Override
298 @NotNull
299 public List<? extends ValueArgument> getValueArguments() {
300 return callElement.getValueArguments();
301 }
302
303 @Override
304 @NotNull
305 public List<? extends FunctionLiteralArgument> getFunctionLiteralArguments() {
306 return callElement.getFunctionLiteralArguments();
307 }
308
309 @Override
310 @NotNull
311 public List<JetTypeProjection> getTypeArguments() {
312 return callElement.getTypeArguments();
313 }
314
315 @Override
316 @Nullable
317 public JetTypeArgumentList getTypeArgumentList() {
318 return callElement.getTypeArgumentList();
319 }
320
321 @NotNull
322 @Override
323 public JetElement getCallElement() {
324 return callElement;
325 }
326
327 @Override
328 public String toString() {
329 return DebugTextPackage.getDebugText(callElement);
330 }
331
332 @NotNull
333 @Override
334 public CallType getCallType() {
335 return CallType.DEFAULT;
336 }
337 };
338 }
339
340 @NotNull
341 public static Call makeCall(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver) {
342 return new CallImpl(callElement, explicitReceiver, null, null, Collections.<ValueArgument>emptyList());
343 }
344 }