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