001 /*
002 $Id: MethodCallExpression.java 4287 2006-12-01 13:00:13Z blackdrag $
003
004 Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005
006 Redistribution and use of this software and associated documentation
007 ("Software"), with or without modification, are permitted provided
008 that the following conditions are met:
009
010 1. Redistributions of source code must retain copyright
011 statements and notices. Redistributions must also contain a
012 copy of this document.
013
014 2. Redistributions in binary form must reproduce the
015 above copyright notice, this list of conditions and the
016 following disclaimer in the documentation and/or other
017 materials provided with the distribution.
018
019 3. The name "groovy" must not be used to endorse or promote
020 products derived from this Software without prior written
021 permission of The Codehaus. For written permission,
022 please contact info@codehaus.org.
023
024 4. Products derived from this Software may not be called "groovy"
025 nor may "groovy" appear in their names without prior written
026 permission of The Codehaus. "groovy" is a registered
027 trademark of The Codehaus.
028
029 5. Due credit should be given to The Codehaus -
030 http://groovy.codehaus.org/
031
032 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
036 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043 OF THE POSSIBILITY OF SUCH DAMAGE.
044
045 */
046 package org.codehaus.groovy.ast.expr;
047
048 import groovy.lang.MetaMethod;
049
050 import org.codehaus.groovy.ast.ClassHelper;
051 import org.codehaus.groovy.ast.GroovyCodeVisitor;
052
053 /**
054 * A method call on an object or class
055 *
056 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
057 * @version $Revision: 4287 $
058 */
059 public class MethodCallExpression extends Expression {
060
061 private Expression objectExpression;
062 private Expression method;
063 private Expression arguments;
064 private boolean spreadSafe = false;
065 private boolean safe = false;
066 private boolean implicitThis;
067
068 public static Expression NO_ARGUMENTS = new TupleExpression();
069
070 public MetaMethod getMetaMethod() {
071 return metaMethod;
072 }
073
074 private MetaMethod metaMethod = null;
075
076 public MethodCallExpression(Expression objectExpression, String method, Expression arguments) {
077 this(objectExpression,new ConstantExpression(method),arguments);
078 }
079
080 public MethodCallExpression(Expression objectExpression, Expression method, Expression arguments) {
081 this.objectExpression = objectExpression;
082 this.method = method;
083 this.arguments = arguments;
084 //TODO: set correct type here
085 // if setting type and a methodcall is the last expresssion in a method,
086 // then the method will return null if the method itself is not void too!
087 // (in bytecode after call: aconst_null, areturn)
088 this.setType(ClassHelper.DYNAMIC_TYPE);
089 this.setImplicitThis(true);
090 }
091
092 public void visit(GroovyCodeVisitor visitor) {
093 visitor.visitMethodCallExpression(this);
094 }
095
096 public Expression transformExpression(ExpressionTransformer transformer) {
097 MethodCallExpression answer =
098 new MethodCallExpression(transformer.transform(objectExpression), transformer.transform(method), transformer.transform(arguments));
099 answer.setSafe(safe);
100 answer.setSourcePosition(this);
101 return answer;
102 }
103
104 public Expression getArguments() {
105 return arguments;
106 }
107
108 public Expression getMethod() {
109 return method;
110 }
111
112 /**
113 * This method returns the method name as String if it is no dynamic
114 * calculated method name, but an constant.
115 */
116 public String getMethodAsString() {
117 if (! (method instanceof ConstantExpression)) return null;
118 ConstantExpression constant = (ConstantExpression) method;
119 return constant.getText();
120 }
121
122 public Expression getObjectExpression() {
123 return objectExpression;
124 }
125
126 public String getText() {
127 return objectExpression.getText() + "." + method.getText() + arguments.getText();
128 }
129
130 /**
131 * @return is this a safe method call, i.e. if true then if the source object is null
132 * then this method call will return null rather than throwing a null pointer exception
133 */
134 public boolean isSafe() {
135 return safe;
136 }
137
138 public void setSafe(boolean safe) {
139 this.safe = safe;
140 }
141
142 public boolean isSpreadSafe() {
143 return spreadSafe;
144 }
145
146 public void setSpreadSafe(boolean value) {
147 spreadSafe = value;
148 }
149
150 /**
151 * @return true if no object expression was specified otherwise if
152 * some expression was specified for the object on which to evaluate
153 * the method then return false
154 */
155 public boolean isImplicitThis() {
156 return implicitThis;
157 }
158
159 public void setImplicitThis(boolean implicitThis) {
160 this.implicitThis = implicitThis;
161 }
162
163 public String toString() {
164 return super.toString()
165 + "[object: "
166 + objectExpression
167 + " method: "
168 + method
169 + " arguments: "
170 + arguments
171 + "]";
172 }
173
174 public void setMethod(MetaMethod mmeth) {
175 this.metaMethod = mmeth;
176 super.setType(ClassHelper.make(mmeth.getReturnType()));
177 }
178 }