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.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 KtExpression expression;
038
039 private final KtElement reportErrorsOn;
040
041 private final boolean isExternal;
042
043 private ExpressionValueArgument(
044 @Nullable KtExpression expression,
045 @NotNull KtElement 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 KtExpression 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 KtElement 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 KtElement callElement;
105 private final ReceiverValue explicitReceiver;
106 private final ASTNode callOperationNode;
107 private final KtExpression calleeExpression;
108 private final List<? extends ValueArgument> valueArguments;
109 private final Call.CallType callType;
110
111 protected CallImpl(@NotNull KtElement callElement, @NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @Nullable KtExpression calleeExpression, @NotNull List<? extends ValueArgument> valueArguments) {
112 this(callElement, explicitReceiver, callOperationNode, calleeExpression, valueArguments, CallType.DEFAULT);
113 }
114
115 protected CallImpl(@NotNull KtElement callElement, @NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
116 @Nullable KtExpression 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 KtExpression 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 KtElement getCallElement() {
156 return callElement;
157 }
158
159 @Override
160 public KtValueArgumentList 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<KtTypeProjection> getTypeArguments() {
172 return Collections.emptyList();
173 }
174
175 @Override
176 public KtTypeArgumentList 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 KtElement callElement, @NotNull ReceiverValue explicitReceiver,
194 @Nullable ASTNode callOperationNode, @NotNull KtExpression calleeExpression,
195 @NotNull List<KtExpression> argumentExpressions) {
196 return makeCallWithExpressions(callElement, explicitReceiver, callOperationNode, calleeExpression, argumentExpressions, CallType.DEFAULT);
197 }
198
199 @NotNull
200 public static Call makeCallWithExpressions(@NotNull KtElement callElement, @NotNull ReceiverValue explicitReceiver,
201 @Nullable ASTNode callOperationNode, @NotNull KtExpression calleeExpression,
202 @NotNull List<KtExpression> argumentExpressions, @NotNull CallType callType) {
203 List<ValueArgument> arguments = new ArrayList<ValueArgument>(argumentExpressions.size());
204 for (KtExpression 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(KtElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, KtExpression calleeExpression, List<? extends ValueArgument> arguments) {
212 return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, CallType.DEFAULT);
213 }
214
215 @NotNull
216 public static Call makeCall(
217 KtElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
218 KtExpression calleeExpression, List<? extends ValueArgument> arguments, CallType callType) {
219 return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
220 }
221
222 @NotNull
223 public static Call makeCall(@NotNull ReceiverValue leftAsReceiver, KtBinaryExpression expression) {
224 return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
225 }
226
227 @NotNull
228 public static Call makeCall(@NotNull ReceiverValue baseAsReceiver, KtUnaryExpression expression) {
229 return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.<ValueArgument>emptyList());
230 }
231
232 @NotNull
233 public static Call makeArraySetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull KtArrayAccessExpression arrayAccessExpression,
234 @NotNull KtExpression rightHandSide, @NotNull CallType callType) {
235 List<KtExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
236 arguments.add(rightHandSide);
237 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments, callType);
238 }
239
240 @NotNull
241 public static Call makeArrayGetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull KtArrayAccessExpression arrayAccessExpression,
242 @NotNull CallType callType) {
243 return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
244 }
245
246 @NotNull
247 public static ValueArgument makeValueArgument(@NotNull KtExpression expression) {
248 return makeValueArgument(expression, expression);
249 }
250
251 @NotNull
252 public static ValueArgument makeValueArgument(@Nullable KtExpression expression, @NotNull KtElement reportErrorsOn) {
253 return new ExpressionValueArgument(expression, reportErrorsOn, false);
254 }
255
256 @NotNull
257 public static ValueArgument makeExternalValueArgument(@NotNull KtExpression expression) {
258 return new ExpressionValueArgument(expression, expression, true);
259 }
260
261 @NotNull
262 public static Call makePropertyCall(@NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull KtSimpleNameExpression nameExpression) {
263 return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<KtExpression>emptyList());
264 }
265
266 @NotNull
267 public static Call makeCall(@NotNull final ReceiverValue explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final KtCallElement callElement) {
268 return new Call() {
269 @Override
270 public ASTNode getCallOperationNode() {
271 return callOperationNode;
272 }
273
274 @NotNull
275 @Override
276 public ReceiverValue getExplicitReceiver() {
277 return explicitReceiver;
278 }
279
280 @NotNull
281 @Override
282 public ReceiverValue getDispatchReceiver() {
283 return ReceiverValue.NO_RECEIVER;
284 }
285
286 @Override
287 @Nullable
288 public KtExpression getCalleeExpression() {
289 return callElement.getCalleeExpression();
290 }
291
292 @Override
293 @Nullable
294 public KtValueArgumentList getValueArgumentList() {
295 return callElement.getValueArgumentList();
296 }
297
298 @Override
299 @NotNull
300 public List<? extends ValueArgument> getValueArguments() {
301 return callElement.getValueArguments();
302 }
303
304 @Override
305 @NotNull
306 public List<? extends FunctionLiteralArgument> getFunctionLiteralArguments() {
307 return callElement.getFunctionLiteralArguments();
308 }
309
310 @Override
311 @NotNull
312 public List<KtTypeProjection> getTypeArguments() {
313 return callElement.getTypeArguments();
314 }
315
316 @Override
317 @Nullable
318 public KtTypeArgumentList getTypeArgumentList() {
319 return callElement.getTypeArgumentList();
320 }
321
322 @NotNull
323 @Override
324 public KtElement getCallElement() {
325 return callElement;
326 }
327
328 @Override
329 public String toString() {
330 return DebugTextUtilKt.getDebugText(callElement);
331 }
332
333 @NotNull
334 @Override
335 public CallType getCallType() {
336 return CallType.DEFAULT;
337 }
338 };
339 }
340
341 @NotNull
342 public static Call makeCall(@NotNull KtElement callElement, @NotNull ReceiverValue explicitReceiver) {
343 return new CallImpl(callElement, explicitReceiver, null, null, Collections.<ValueArgument>emptyList());
344 }
345 }