Copyright (c) 2013, 2014 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM Corporation - initial API and implementation
/*******************************************************************************
* Copyright (c) 2013, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.dom;
import java.util.ArrayList;
import java.util.List;
Lambda expression AST node type (added in JLS8 API).
LambdaExpression:
Identifier -> Body
( [ Identifier { , Identifier } ] ) -> Body
( [ FormalParameter { , FormalParameter } ] ) -> Body
The first two forms use VariableDeclarationFragment
for the parameter or parameters, while the third form uses SingleVariableDeclaration
.
The Body can be either a Block
or an Expression
.
Since: 3.10 @noinstantiate This class is not intended to be instantiated by clients
/**
* Lambda expression AST node type (added in JLS8 API).
* <pre>
* LambdaExpression:
* Identifier <b>-></b> Body
* <b>(</b> [ Identifier { <b>,</b> Identifier } ] <b>)</b> <b>-></b> Body
* <b>(</b> [ FormalParameter { <b>,</b> FormalParameter } ] <b>)</b> <b>-></b> Body
* </pre>
*
*<p>
* The first two forms use {@link VariableDeclarationFragment} for the parameter or parameters,
* while the third form uses {@link SingleVariableDeclaration}.</p>
*<p>The Body can be either a {@link Block} or an {@link Expression}.</p>
*
* @since 3.10
* @noinstantiate This class is not intended to be instantiated by clients
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class LambdaExpression extends Expression {
The "parentheses" structural property of this node type (type: Boolean
). Note that parentheses are required unless parameters()
contains just a single VariableDeclarationFragment
. ASTRewrite may ignore this property if necessary.
/**
* The "parentheses" structural property of this node type (type: {@link Boolean}).
* <p>
* Note that parentheses are required unless {@link #parameters()} contains
* just a single {@link VariableDeclarationFragment}.
* ASTRewrite may ignore this property if necessary.
* </p>
*/
public static final SimplePropertyDescriptor PARENTHESES_PROPERTY =
new SimplePropertyDescriptor(LambdaExpression.class, "parentheses", boolean.class, MANDATORY); //$NON-NLS-1$
The "parameters" structural property of this node type (element type: VariableDeclaration
). Note that all elements must be of the same type, either all SingleVariableDeclaration
or all VariableDeclarationFragment
.
/**
* The "parameters" structural property of this node type (element type: {@link VariableDeclaration}).
* <p>
* Note that all elements must be of the same type, either all {@link SingleVariableDeclaration} or all {@link VariableDeclarationFragment}.
* </p>
*/
public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
new ChildListPropertyDescriptor(LambdaExpression.class, "parameters", VariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
The "body" structural property of this node type (child type: ASTNode
, must be either a Block
or an Expression
). /**
* The "body" structural property of this node type (child type: {@link ASTNode},
* must be either a {@link Block} or an {@link Expression}).
*/
public static final ChildPropertyDescriptor BODY_PROPERTY =
new ChildPropertyDescriptor(LambdaExpression.class, "body", ASTNode.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
A list of property descriptors (element type: StructuralPropertyDescriptor
), or null if uninitialized. /**
* A list of property descriptors (element type:
* {@link StructuralPropertyDescriptor}),
* or null if uninitialized.
*/
private static final List PROPERTY_DESCRIPTORS_8_0;
static {
List propertyList = new ArrayList(4);
createPropertyList(LambdaExpression.class, propertyList);
addProperty(PARENTHESES_PROPERTY, propertyList);
addProperty(PARAMETERS_PROPERTY, propertyList);
addProperty(BODY_PROPERTY, propertyList);
PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList);
}
Returns a list of structural property descriptors for this node type.
Clients must not modify the result.
Params: - apiLevel – the API level; one of the AST.JLS* constants
Returns: a list of property descriptors (element type: StructuralPropertyDescriptor
)
/**
* Returns a list of structural property descriptors for this node type.
* Clients must not modify the result.
*
* @param apiLevel the API level; one of the AST.JLS* constants
* @return a list of property descriptors (element type:
* {@link StructuralPropertyDescriptor})
*/
public static List propertyDescriptors(int apiLevel) {
return PROPERTY_DESCRIPTORS_8_0;
}
Indicates whether parentheses are present or not.
Defaults to true
.
/**
* Indicates whether parentheses are present or not.
* Defaults to <code>true</code>.
*/
private boolean hasParentheses = true;
The parameter declarations (element type: VariableDeclaration
). Defaults to an empty list. /**
* The parameter declarations
* (element type: {@link VariableDeclaration}).
* Defaults to an empty list.
*/
private ASTNode.NodeList parameters =
new ASTNode.NodeList(PARAMETERS_PROPERTY);
The method body.
The method body; lazily initialized, defaults to an empty Block.
/**
* The method body.
* The method body; lazily initialized, defaults to an empty Block.
*/
private ASTNode body = null;
Creates a new AST node for a LambdaExpression declaration owned
by the given AST.
N.B. This constructor is package-private; all subclasses must be
declared in the same package; clients are unable to declare
additional subclasses.
Params: - ast – the AST that is to own this node
/**
* Creates a new AST node for a LambdaExpression declaration owned
* by the given AST.
* <p>
* N.B. This constructor is package-private; all subclasses must be
* declared in the same package; clients are unable to declare
* additional subclasses.
* </p>
*
* @param ast the AST that is to own this node
*/
LambdaExpression(AST ast) {
super(ast);
unsupportedIn2_3_4();
}
@Override
final List internalStructuralPropertiesForType(int apiLevel) {
return propertyDescriptors(apiLevel);
}
@Override
final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
if (property == PARENTHESES_PROPERTY) {
if (get) {
return hasParentheses();
} else {
setParentheses(value);
return false;
}
}
// allow default implementation to flag the error
return super.internalGetSetBooleanProperty(property, get, value);
}
@Override
final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
if (property == PARAMETERS_PROPERTY) {
return parameters();
}
// allow default implementation to flag the error
return super.internalGetChildListProperty(property);
}
@Override
final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
if (property == BODY_PROPERTY) {
if (get) {
return getBody();
} else {
setBody( child);
return null;
}
}
// allow default implementation to flag the error
return super.internalGetSetChildProperty(property, get, child);
}
@Override
final int getNodeType0() {
return LAMBDA_EXPRESSION;
}
@Override
ASTNode clone0(AST target) {
LambdaExpression result = new LambdaExpression(target);
result.setSourceRange(getStartPosition(), getLength());
result.setParentheses(hasParentheses());
result.parameters().addAll(ASTNode.copySubtrees(target, parameters()));
result.setBody(ASTNode.copySubtree(target, getBody()));
return result;
}
@Override
final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
// dispatch to correct overloaded match method
return matcher.match(this, other);
}
@Override
void accept0(ASTVisitor visitor) {
boolean visitChildren = visitor.visit(this);
if (visitChildren) {
// visit children in normal left to right reading order
acceptChildren(visitor, this.parameters);
acceptChild(visitor, getBody());
}
visitor.endVisit(this);
}
Returns whether parentheses around the parameters are present or not.
Note that parentheses are required unless parameters()
contains just a single VariableDeclarationFragment
. ASTRewrite may ignore this property if necessary.
Returns: true
if this lambda expression has parentheses around
its parameters and false
otherwise
/**
* Returns whether parentheses around the parameters are present or not.
* <p>
* Note that parentheses are required unless {@link #parameters()} contains
* just a single {@link VariableDeclarationFragment}.
* ASTRewrite may ignore this property if necessary.
* </p>
*
* @return <code>true</code> if this lambda expression has parentheses around
* its parameters and <code>false</code> otherwise
*/
public boolean hasParentheses() {
return this.hasParentheses;
}
Sets whether this lambda expression has parentheses around its parameters or not.
Note that parentheses are required unless parameters()
contains just a single VariableDeclarationFragment
. ASTRewrite may ignore this property if necessary.
Params: - hasParentheses –
true
if this lambda expression has parentheses around its parameters
and false
otherwise
/**
* Sets whether this lambda expression has parentheses around its parameters or not.
* <p>
* Note that parentheses are required unless {@link #parameters()} contains
* just a single {@link VariableDeclarationFragment}.
* ASTRewrite may ignore this property if necessary.
* </p>
*
* @param hasParentheses <code>true</code> if this lambda expression has parentheses around its parameters
* and <code>false</code> otherwise
*/
public void setParentheses(boolean hasParentheses) {
preValueChange(PARENTHESES_PROPERTY);
this.hasParentheses = hasParentheses;
postValueChange(PARENTHESES_PROPERTY);
}
Returns the live ordered list of formal parameters of this lambda expression.
Note that all elements must be of the same type, either
- all
SingleVariableDeclaration
(explicit type), or
- all
VariableDeclarationFragment
(inferred type).
Returns: the live list of formal parameters of this lambda expression (element type: VariableDeclaration
)
/**
* Returns the live ordered list of formal parameters of this lambda expression.
* Note that all elements must be of the same type, either
* <ul>
* <li>all {@link SingleVariableDeclaration} (explicit type), or</li>
* <li>all {@link VariableDeclarationFragment} (inferred type).</li>
* </ul>
*
* @return the live list of formal parameters of this lambda expression
* (element type: {@link VariableDeclaration})
*/
public List parameters() {
return this.parameters;
}
Returns the body of this lambda expression.
Returns: the lambda expression body, which can be either a Block
or an Expression
/**
* Returns the body of this lambda expression.
*
* @return the lambda expression body, which can be either a {@link Block} or an {@link Expression}
*/
public ASTNode getBody() {
if (this.body == null) {
// lazy init must be thread-safe for readers
synchronized (this) {
if (this.body == null) {
preLazyInit();
this.body = new Block(this.ast);
postLazyInit(this.body, BODY_PROPERTY);
}
}
}
return this.body;
}
Sets the body of this lambda expression.
Params: - body – a block node or an expression node
Throws: - IllegalArgumentException – if:
- the node belongs to a different AST
- the node already has a parent
- a cycle in would be created
- body is neither a
Block
nor an Expression
/**
* Sets the body of this lambda expression.
*
* @param body a block node or an expression node
* @exception IllegalArgumentException if:
* <ul>
* <li>the node belongs to a different AST</li>
* <li>the node already has a parent</li>
* <li>a cycle in would be created</li>
* <li>body is neither a {@link Block} nor an {@link Expression}</li>
* </ul>
*/
public void setBody(ASTNode body) {
if (!(body instanceof Expression || body instanceof Block)) {
throw new IllegalArgumentException();
}
ASTNode oldChild = this.body;
preReplaceChild(oldChild, body, BODY_PROPERTY);
this.body = body;
postReplaceChild(oldChild, body, BODY_PROPERTY);
}
Resolves and returns the binding for the lambda expression
Note that bindings are generally unavailable unless requested when the
AST is being built.
Returns: the binding, or null
if the binding cannot be
resolved
/**
* Resolves and returns the binding for the lambda expression
* <p>
* Note that bindings are generally unavailable unless requested when the
* AST is being built.
* </p>
*
* @return the binding, or <code>null</code> if the binding cannot be
* resolved
*/
public IMethodBinding resolveMethodBinding() {
return this.ast.getBindingResolver().resolveMethod(this);
}
@Override
int memSize() {
return BASE_NODE_SIZE + 3 * 4;
}
@Override
int treeSize() {
return
memSize()
+ this.parameters.listSize()
+ (this.body == null ? 0 : getBody().treeSize());
}
}