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 017package org.jetbrains.jet.lang.resolve.calls.util; 018 019import com.google.common.collect.Lists; 020import com.intellij.lang.ASTNode; 021import com.intellij.psi.PsiElement; 022import com.intellij.psi.impl.source.tree.LeafPsiElement; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.lang.psi.*; 026import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 027import org.jetbrains.jet.lang.psi.Call.CallType; 028 029import java.util.Collections; 030import java.util.List; 031 032public 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}