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