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.DebugTextUtilKt;
027 import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver;
028 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
029
030 import java.util.ArrayList;
031 import java.util.Collections;
032 import java.util.List;
033
034 public class CallMaker {
035
036 private static class ExpressionValueArgument implements ValueArgument {
037
038 private final KtExpression expression;
039
040 private final KtElement reportErrorsOn;
041
042 private final boolean isExternal;
043
044 private ExpressionValueArgument(
045 @Nullable KtExpression expression,
046 @NotNull KtElement reportErrorsOn,
047 boolean isExternal
048 ) {
049 this.expression = expression;
050 this.reportErrorsOn = expression == null ? reportErrorsOn : expression;
051 this.isExternal = isExternal;
052 }
053
054 @Override
055 public boolean isExternal() {
056 return isExternal;
057 }
058
059 @Override
060 public KtExpression getArgumentExpression() {
061 return expression;
062 }
063
064 @Override
065 public ValueArgumentName getArgumentName() {
066 return null;
067 }
068
069 @Override
070 public boolean isNamed() {
071 return false;
072 }
073
074 @NotNull
075 @Override
076 public KtElement asElement() {
077 return reportErrorsOn;
078 }
079
080 @Override
081 public LeafPsiElement getSpreadElement() {
082 return null;
083 }
084
085 @Override
086 public boolean equals(Object o) {
087 if (this == o) return true;
088 if (o == null || getClass() != o.getClass()) return false;
089
090 ExpressionValueArgument argument = (ExpressionValueArgument) o;
091
092 if (expression != null ? !expression.equals(argument.expression) : argument.expression != null) return false;
093
094 return true;
095 }
096
097 @Override
098 public int hashCode() {
099 return expression != null ? expression.hashCode() : 0;
100 }
101 }
102
103 private static class CallImpl implements Call {
104
105 private final KtElement callElement;
106 private final Receiver explicitReceiver;
107 private final ASTNode callOperationNode;
108 private final KtExpression calleeExpression;
109 private final List<? extends ValueArgument> valueArguments;
110 private final Call.CallType callType;
111
112 protected CallImpl(@NotNull KtElement callElement, @NotNull Receiver explicitReceiver, @Nullable ASTNode callOperationNode, @Nullable KtExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments) {
113 this(callElement, explicitReceiver, callOperationNode, calleeExpression, valueArguments, CallType.DEFAULT);
114 }
115
116 protected CallImpl(@NotNull KtElement callElement, @Nullable Receiver explicitReceiver, @Nullable ASTNode callOperationNode,
117 @Nullable KtExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments, @NotNull CallType callType) {
118 this.callElement = callElement;
119 this.explicitReceiver = explicitReceiver;
120 this.callOperationNode = callOperationNode;
121 this.calleeExpression = calleeExpression;
122 this.valueArguments = valueArguments;
123 this.callType = callType;
124 }
125
126 @Override
127 public ASTNode getCallOperationNode() {
128 return callOperationNode;
129 }
130
131 @Nullable
132 @Override
133 public Receiver getExplicitReceiver() {
134 return explicitReceiver;
135 }
136
137 @Nullable
138 @Override
139 public ReceiverValue getDispatchReceiver() {
140 return null;
141 }
142
143 @Override
144 public KtExpression getCalleeExpression() {
145 return calleeExpression;
146 }
147
148 @NotNull
149 @Override
150 public List<? extends ValueArgument> getValueArguments() {
151 return valueArguments;
152 }
153
154 @NotNull
155 @Override
156 public KtElement getCallElement() {
157 return callElement;
158 }
159
160 @Override
161 public KtValueArgumentList getValueArgumentList() {
162 return null;
163 }
164
165 @NotNull
166 @Override
167 public List<LambdaArgument> getFunctionLiteralArguments() {
168 return Collections.emptyList();
169 }
170 @NotNull
171 @Override
172 public List<KtTypeProjection> getTypeArguments() {
173 return Collections.emptyList();
174 }
175
176 @Override
177 public KtTypeArgumentList getTypeArgumentList() {
178 return null;
179 }
180
181 @Override
182 public String toString() {
183 return getCallElement().getText();
184 }
185
186 @NotNull
187 @Override
188 public CallType getCallType() {
189 return callType;
190 }
191 }
192
193 @NotNull
194 public static Call makeCallWithExpressions(@NotNull KtElement callElement, @Nullable Receiver explicitReceiver,
195 @Nullable ASTNode callOperationNode, @NotNull KtExpression calleeExpression,
196 @NotNull List<KtExpression> argumentExpressions) {
197 return makeCallWithExpressions(callElement, explicitReceiver, callOperationNode, calleeExpression, argumentExpressions, CallType.DEFAULT);
198 }
199
200 @NotNull
201 public static Call makeCallWithExpressions(@NotNull KtElement callElement, @Nullable Receiver explicitReceiver,
202 @Nullable ASTNode callOperationNode, @NotNull KtExpression calleeExpression,
203 @NotNull List<KtExpression> argumentExpressions, @NotNull CallType callType) {
204 List<ValueArgument> arguments = new ArrayList<ValueArgument>(argumentExpressions.size());
205 for (KtExpression argumentExpression : argumentExpressions) {
206 arguments.add(makeValueArgument(argumentExpression, calleeExpression));
207 }
208 return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
209 }
210
211 @NotNull
212 public static Call makeCall(KtElement callElement, @Nullable Receiver explicitReceiver, @Nullable ASTNode callOperationNode, KtExpression calleeExpression, List<? extends ValueArgument> arguments) {
213 return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, CallType.DEFAULT);
214 }
215
216 @NotNull
217 public static Call makeCall(
218 KtElement callElement, @Nullable Receiver explicitReceiver, @Nullable ASTNode callOperationNode,
219 KtExpression calleeExpression, List<? extends ValueArgument> arguments, CallType callType) {
220 return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
221 }
222
223 @NotNull
224 public static Call makeCall(@NotNull ReceiverValue leftAsReceiver, KtBinaryExpression expression) {
225 return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
226 }
227
228 @NotNull
229 public static Call makeCall(@NotNull ReceiverValue baseAsReceiver, KtUnaryExpression expression) {
230 return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.<ValueArgument>emptyList());
231 }
232
233 @NotNull
234 public static Call makeArraySetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull KtArrayAccessExpression arrayAccessExpression,
235 @NotNull KtExpression rightHandSide, @NotNull CallType callType) {
236 List<KtExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
237 arguments.add(rightHandSide);
238 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments, callType);
239 }
240
241 @NotNull
242 public static Call makeArrayGetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull KtArrayAccessExpression arrayAccessExpression,
243 @NotNull CallType callType) {
244 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
245 }
246
247 @NotNull
248 public static ValueArgument makeValueArgument(@NotNull KtExpression expression) {
249 return makeValueArgument(expression, expression);
250 }
251
252 @NotNull
253 public static ValueArgument makeValueArgument(@Nullable KtExpression expression, @NotNull KtElement reportErrorsOn) {
254 return new ExpressionValueArgument(expression, reportErrorsOn, false);
255 }
256
257 @NotNull
258 public static ValueArgument makeExternalValueArgument(@NotNull KtExpression expression) {
259 return new ExpressionValueArgument(expression, expression, true);
260 }
261
262 @NotNull
263 public static Call makePropertyCall(@Nullable Receiver explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull KtSimpleNameExpression nameExpression) {
264 return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<KtExpression>emptyList());
265 }
266
267
268 @NotNull
269 public static Call makeConstructorCallWithoutTypeArguments(@NotNull KtCallElement callElement) {
270 return new DelegatingCall(makeCall(null, null, callElement)) {
271 @NotNull
272 @Override
273 public List<KtTypeProjection> getTypeArguments() {
274 return Collections.emptyList();
275 }
276
277 @Nullable
278 @Override
279 public KtTypeArgumentList getTypeArgumentList() {
280 return null;
281 }
282 };
283 }
284
285 @NotNull
286 public static Call makeConstructorCallForEnumEntryWithoutInitializer(@NotNull final KtSuperTypeCallEntry callElement) {
287 return new Call() {
288 @Nullable
289 @Override
290 public ASTNode getCallOperationNode() {
291 return null;
292 }
293
294 @Nullable
295 @Override
296 public Receiver getExplicitReceiver() {
297 return null;
298 }
299
300 @Nullable
301 @Override
302 public ReceiverValue getDispatchReceiver() {
303 return null;
304 }
305
306 @Nullable
307 @Override
308 public KtExpression getCalleeExpression() {
309 return callElement.getCalleeExpression();
310 }
311
312 @Nullable
313 @Override
314 public KtValueArgumentList getValueArgumentList() {
315 return callElement.getValueArgumentList();
316 }
317
318 @NotNull
319 @Override
320 public List<? extends ValueArgument> getValueArguments() {
321 return callElement.getValueArguments();
322 }
323
324 @NotNull
325 @Override
326 public List<? extends LambdaArgument> getFunctionLiteralArguments() {
327 return Collections.emptyList();
328 }
329
330 @NotNull
331 @Override
332 public List<KtTypeProjection> getTypeArguments() {
333 return Collections.emptyList();
334 }
335
336 @Nullable
337 @Override
338 public KtTypeArgumentList getTypeArgumentList() {
339 return null;
340 }
341
342 @NotNull
343 @Override
344 public KtElement getCallElement() {
345 return callElement;
346 }
347
348 @NotNull
349 @Override
350 public CallType getCallType() {
351 return CallType.DEFAULT;
352 }
353 };
354 }
355
356 @NotNull
357 public static Call makeCall(@Nullable final Receiver explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final KtCallElement callElement) {
358 return new Call() {
359 @Override
360 public ASTNode getCallOperationNode() {
361 return callOperationNode;
362 }
363
364 @Nullable
365 @Override
366 public Receiver getExplicitReceiver() {
367 return explicitReceiver;
368 }
369
370 @Nullable
371 @Override
372 public ReceiverValue getDispatchReceiver() {
373 return null;
374 }
375
376 @Override
377 @Nullable
378 public KtExpression getCalleeExpression() {
379 return callElement.getCalleeExpression();
380 }
381
382 @Override
383 @Nullable
384 public KtValueArgumentList getValueArgumentList() {
385 return callElement.getValueArgumentList();
386 }
387
388 @Override
389 @NotNull
390 public List<? extends ValueArgument> getValueArguments() {
391 return callElement.getValueArguments();
392 }
393
394 @Override
395 @NotNull
396 public List<? extends LambdaArgument> getFunctionLiteralArguments() {
397 return callElement.getLambdaArguments();
398 }
399
400 @Override
401 @NotNull
402 public List<KtTypeProjection> getTypeArguments() {
403 return callElement.getTypeArguments();
404 }
405
406 @Override
407 @Nullable
408 public KtTypeArgumentList getTypeArgumentList() {
409 return callElement.getTypeArgumentList();
410 }
411
412 @NotNull
413 @Override
414 public KtElement getCallElement() {
415 return callElement;
416 }
417
418 @Override
419 public String toString() {
420 return DebugTextUtilKt.getDebugText(callElement);
421 }
422
423 @NotNull
424 @Override
425 public CallType getCallType() {
426 return CallType.DEFAULT;
427 }
428 };
429 }
430
431 @NotNull
432 public static Call makeCall(@NotNull KtElement callElement, @NotNull ReceiverValue explicitReceiver) {
433 return new CallImpl(callElement, explicitReceiver, null, null, Collections.<ValueArgument>emptyList());
434 }
435 }