org.codehaus.groovy.ast.expr.DeclarationExpression Maven / Gradle / Ivy
Show all versions of groovy Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast.expr;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.GroovyCodeVisitor;
import org.codehaus.groovy.syntax.Token;
import static org.apache.groovy.ast.tools.ClassNodeUtils.formatTypeName;
/**
* Represents one or more local variables. Typically it is a single local variable
* declared by name with an expression like "def foo" or with type "String foo". However,
* the multiple assignment feature allows you to create two or more variables using
* an expression like: def (x, y) = [1, 2]
.
*
* You can access the left hand side of a declaration using the
* "Expression getLeftExpression()
" method. In which case you might then
* use instanceof
and casting to perform operations specific to a
* single local variable (VariableExpression
) or for the multiple
* assignment case (TupleExpression
).
*
* Alternatively, if isMultipleAssignmentDeclaration()
is false
* you can use the method "VariableExpression getVariableExpression()
" method.
* Similarly, if isMultipleAssignmentDeclaration()
is true
* you can use the method "TupleExpression getTupleExpression()
" method.
* Calling either of these expression getters when the "isMultipleAssignment" condition
* is not appropriate is unsafe and will result in a ClassCastException
.
*/
public class DeclarationExpression extends BinaryExpression {
/**
* Creates a DeclarationExpression for VariableExpressions like "def x" or "String y = 'foo'".
* @param left
* the left hand side of a variable declaration
* @param operation
* the operation, typically an assignment operator
* @param right
* the right hand side of a declaration
*/
public DeclarationExpression(final VariableExpression left, final Token operation, final Expression right) {
this((Expression) left, operation, right);
}
/**
* Creates a DeclarationExpression for Expressions like "def (x, y) = [1, 2]"
* @param left
* the left hand side of a declaration. Must be either a VariableExpression or
* a TupleExpression with at least one element.
* @param operation
* the operation, typically an assignment operator
* @param right
* the right hand side of a declaration
*/
public DeclarationExpression(final Expression left, final Token operation, final Expression right) {
super(left, Token.newSymbol("=", operation.getStartLine(), operation.getStartColumn()), right);
check(left);
}
private static void check(Expression left) {
if (left instanceof VariableExpression) {
//nothing
} else if (left instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) left;
if (tuple.getExpressions().isEmpty()) throw new GroovyBugError("one element required for left side");
} else {
throw new GroovyBugError("illegal left expression for declaration: "+left);
}
}
@Override
public void visit(GroovyCodeVisitor visitor) {
visitor.visitDeclarationExpression(this);
}
/**
* This method returns the left hand side of the declaration cast to the VariableExpression type.
* This is an unsafe method to call. In a multiple assignment statement, the left hand side will
* be a TupleExpression and a ClassCastException will occur. If you invoke this method then
* be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
* If that method returns true then this method is safe to call.
*
* @return left hand side of normal variable declarations
* @throws ClassCastException if the left hand side is not a VariableExpression (and is probably a multiple assignment statement).
*/
public VariableExpression getVariableExpression() {
Expression leftExpression = this.getLeftExpression();
return leftExpression instanceof VariableExpression
? (VariableExpression) leftExpression
: null;
}
/**
* This method returns the left hand side of the declaration cast to the TupleExpression type.
* This is an unsafe method to call. In a single assignment statement, the left hand side will
* be a VariableExpression and a ClassCastException will occur. If you invoke this method then
* be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so.
* If that method returns true then this method is safe to call.
* @return
* left hand side of multiple assignment declarations
* @throws ClassCastException
* if the left hand side is not a TupleExpression (and is probably a VariableExpression).
*
*/
public TupleExpression getTupleExpression() {
Expression leftExpression = this.getLeftExpression();
return leftExpression instanceof TupleExpression
? (TupleExpression) leftExpression
: null;
}
@Override
public String getText() {
StringBuilder text = new StringBuilder();
if (!isMultipleAssignmentDeclaration()) {
VariableExpression v = getVariableExpression();
if (v.isDynamicTyped()) {
text.append("def");
} else {
text.append(formatTypeName(v.getType()));
}
text.append(' ').append(v.getText());
} else {
TupleExpression t = getTupleExpression();
text.append("def (");
for (Expression e : t.getExpressions()) {
if (e instanceof VariableExpression) {
VariableExpression v = (VariableExpression) e;
if (!v.isDynamicTyped()) {
text.append(formatTypeName(v.getType())).append(' ');
}
}
text.append(e.getText()).append(", ");
}
text.setLength(text.length() - 2);
text.append(')');
}
text.append(' ').append(getOperation().getText());
text.append(' ').append(getRightExpression().getText());
return text.toString();
}
/**
* This method sets the leftExpression for this BinaryExpression. The parameter must be
* either a VariableExpression or a TupleExpression with one or more elements.
* @param leftExpression
* either a VariableExpression or a TupleExpression with one or more elements.
*/
@Override
public void setLeftExpression(Expression leftExpression) {
check(leftExpression);
super.setLeftExpression(leftExpression);
}
@Override
public void setRightExpression(Expression rightExpression) {
super.setRightExpression(rightExpression);
}
@Override
public Expression transformExpression(ExpressionTransformer transformer) {
Expression ret = new DeclarationExpression(transformer.transform(getLeftExpression()),
getOperation(), transformer.transform(getRightExpression()));
ret.setSourcePosition(this);
ret.addAnnotations(getAnnotations());
ret.setDeclaringClass(getDeclaringClass());
ret.copyNodeMetaData(this);
return ret;
}
/**
* This method tells you if this declaration is a multiple assignment declaration, which
* has the form "def (x, y) = ..." in Groovy. If this method returns true, then the left
* hand side is an ArgumentListExpression. Do not call "getVariableExpression()" on this
* object if this method returns true, instead use "getLeftExpression()".
* @return
* true if this declaration is a multiple assignment declaration, which means the
* left hand side is an ArgumentListExpression.
*/
public boolean isMultipleAssignmentDeclaration() {
return getLeftExpression() instanceof TupleExpression;
}
}