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