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 JetElement reportErrorsOn;
039    
040            private ExpressionValueArgument(@Nullable JetExpression expression, @NotNull JetElement 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 JetElement 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 JetElement 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 JetElement 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 JetElement 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 JetElement 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        @NotNull
163        public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
164                                                   @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
165                                                   @NotNull List<JetExpression> argumentExpressions) {
166            return makeCallWithExpressions(callElement, explicitReceiver, callOperationNode, calleeExpression, argumentExpressions, CallType.DEFAULT);
167        }
168    
169        @NotNull
170        public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
171                                                   @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
172                                                   @NotNull List<JetExpression> argumentExpressions, @NotNull CallType callType) {
173            List<ValueArgument> arguments = Lists.newArrayList();
174            for (JetExpression argumentExpression : argumentExpressions) {
175                arguments.add(makeValueArgument(argumentExpression, calleeExpression));
176            }
177            return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
178        }
179    
180        @NotNull
181        public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, JetExpression calleeExpression, List<? extends ValueArgument> arguments) {
182            return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, CallType.DEFAULT);
183        }
184    
185        @NotNull
186        public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
187                JetExpression calleeExpression, List<? extends ValueArgument> arguments, CallType callType) {
188            return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
189        }
190    
191        @NotNull
192        public static Call makeCall(@NotNull ReceiverValue leftAsReceiver, JetBinaryExpression expression) {
193            return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
194        }
195    
196        @NotNull
197        public static Call makeCall(@NotNull ReceiverValue baseAsReceiver, JetUnaryExpression expression) {
198            return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.<ValueArgument>emptyList());
199        }
200    
201        @NotNull
202        public static Call makeArraySetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
203                @NotNull JetExpression rightHandSide, @NotNull CallType callType) {
204            List<JetExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
205            arguments.add(rightHandSide);
206            return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments, callType);
207        }
208    
209        @NotNull
210        public static Call makeArrayGetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
211                @NotNull CallType callType) {
212            return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
213        }
214    
215        @NotNull
216        public static ValueArgument makeValueArgument(@NotNull JetExpression expression) {
217            return makeValueArgument(expression, expression);
218        }
219    
220        @NotNull
221        public static ValueArgument makeValueArgument(@Nullable JetExpression expression, @NotNull JetElement reportErrorsOn) {
222            return new ExpressionValueArgument(expression, reportErrorsOn);
223        }
224    
225        @NotNull
226        public static Call makePropertyCall(@NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
227            return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<JetExpression>emptyList());
228        }
229    
230        @NotNull
231        public static Call makeCall(@NotNull final ReceiverValue explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final JetCallElement callElement) {
232            return new Call() {
233                @Override
234                public ASTNode getCallOperationNode() {
235                    return callOperationNode;
236                }
237    
238                @NotNull
239                @Override
240                public ReceiverValue getExplicitReceiver() {
241                    return explicitReceiver;
242                }
243    
244                @NotNull
245                @Override
246                public ReceiverValue getThisObject() {
247                    return ReceiverValue.NO_RECEIVER;
248                }
249    
250                @Override
251                @Nullable
252                public JetExpression getCalleeExpression() {
253                    return callElement.getCalleeExpression();
254                }
255    
256                @Override
257                @Nullable
258                public JetValueArgumentList getValueArgumentList() {
259                    return callElement.getValueArgumentList();
260                }
261    
262                @Override
263                @NotNull
264                public List<? extends ValueArgument> getValueArguments() {
265                    return callElement.getValueArguments();
266                }
267    
268                @Override
269                @NotNull
270                public List<JetExpression> getFunctionLiteralArguments() {
271                    return callElement.getFunctionLiteralArguments();
272                }
273    
274                @Override
275                @NotNull
276                public List<JetTypeProjection> getTypeArguments() {
277                    return callElement.getTypeArguments();
278                }
279    
280                @Override
281                @Nullable
282                public JetTypeArgumentList getTypeArgumentList() {
283                    return callElement.getTypeArgumentList();
284                }
285    
286                @NotNull
287                @Override
288                public JetElement getCallElement() {
289                    return callElement;
290                }
291    
292                @Override
293                public String toString() {
294                    return callElement.getText();
295                }
296    
297                @NotNull
298                @Override
299                public CallType getCallType() {
300                    return CallType.DEFAULT;
301                }
302            };
303        }
304    
305        @NotNull
306        public static Call makeCall(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver) {
307            return new CallImpl(callElement, explicitReceiver, null, null, Collections.<ValueArgument>emptyList());
308        }
309    }