EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/LambdaExpression.java
1/*******************************************************************************
2 * Copyright (c) 2013, 2014 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 *     IBM Corporation - initial API and implementation
13 *******************************************************************************/
14package org.eclipse.jdt.core.dom;
15
16import java.util.ArrayList;
17import java.util.List;
18
19/**
20 * Lambda expression AST node type (added in JLS8 API).
21 * <pre>
22 * LambdaExpression:
23 *    Identifier <b>-></b> Body
24 *    <b>(</b> [ Identifier { <b>,</b> Identifier } ] <b>)</b> <b>-></b> Body
25 *    <b>(</b> [ FormalParameter { <b>,</b> FormalParameter } ] <b>)</b> <b>-></b> Body
26 * </pre>
27 *
28 *<p>
29 * The first two forms use {@link VariableDeclarationFragment} for the parameter or parameters,
30 * while the third form uses {@link SingleVariableDeclaration}.</p>
31 *<p>The Body can be either a {@link Block} or an {@link Expression}.</p>
32 *
33 * @since 3.10
34 * @noinstantiate This class is not intended to be instantiated by clients
35 */
36@SuppressWarnings({"rawtypes""unchecked"})
37public class LambdaExpression extends Expression {
38
39    /**
40     * The "parentheses" structural property of this node type (type: {@link Boolean}).
41     * <p>
42     * Note that parentheses are required unless {@link #parameters()} contains
43     * just a single {@link VariableDeclarationFragment}.
44     * ASTRewrite may ignore this property if necessary.
45     * </p>
46     */
47    public static final SimplePropertyDescriptor PARENTHESES_PROPERTY =
48        new SimplePropertyDescriptor(LambdaExpression.class"parentheses"boolean.classMANDATORY); //$NON-NLS-1$
49
50    /**
51     * The "parameters" structural property of this node type (element type: {@link VariableDeclaration}).
52     * <p>
53     * Note that all elements must be of the same type, either all {@link SingleVariableDeclaration} or all {@link VariableDeclarationFragment}.
54     * </p>
55     */
56    public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
57        new ChildListPropertyDescriptor(LambdaExpression.class"parameters"VariableDeclaration.classCYCLE_RISK); //$NON-NLS-1$
58
59    /**
60     * The "body" structural property of this node type (child type: {@link ASTNode},
61     * must be either a {@link Block} or an {@link Expression}).
62     */
63    public static final ChildPropertyDescriptor BODY_PROPERTY =
64        new ChildPropertyDescriptor(LambdaExpression.class"body"ASTNode.classMANDATORYCYCLE_RISK); //$NON-NLS-1$
65
66    /**
67     * A list of property descriptors (element type:
68     * {@link StructuralPropertyDescriptor}),
69     * or null if uninitialized.
70     */
71    private static final List PROPERTY_DESCRIPTORS_8_0;
72
73    static {
74        List propertyList = new ArrayList(4);
75        createPropertyList(LambdaExpression.classpropertyList);
76        addProperty(PARENTHESES_PROPERTYpropertyList);
77        addProperty(PARAMETERS_PROPERTYpropertyList);
78        addProperty(BODY_PROPERTYpropertyList);
79        PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList);
80    }
81
82    /**
83     * Returns a list of structural property descriptors for this node type.
84     * Clients must not modify the result.
85     *
86     * @param apiLevel the API level; one of the AST.JLS* constants
87     * @return a list of property descriptors (element type:
88     * {@link StructuralPropertyDescriptor})
89     */
90    public static List propertyDescriptors(int apiLevel) {
91        return PROPERTY_DESCRIPTORS_8_0;
92    }
93
94    /**
95     * Indicates whether parentheses are present or not.
96     * Defaults to <code>true</code>.
97     */
98    private boolean hasParentheses = true;
99
100    /**
101     * The parameter declarations
102     * (element type: {@link VariableDeclaration}).
103     * Defaults to an empty list.
104     */
105    private ASTNode.NodeList parameters =
106        new ASTNode.NodeList(PARAMETERS_PROPERTY);
107
108    /**
109     * The method body.
110     * The method body; lazily initialized, defaults to an empty Block.
111     */
112    private ASTNode body = null;
113
114    /**
115     * Creates a new AST node for a LambdaExpression declaration owned
116     * by the given AST.
117     * <p>
118     * N.B. This constructor is package-private; all subclasses must be
119     * declared in the same package; clients are unable to declare
120     * additional subclasses.
121     * </p>
122     *
123     * @param ast the AST that is to own this node
124     */
125    LambdaExpression(AST ast) {
126        super(ast);
127        unsupportedIn2_3_4();
128    }
129
130    @Override
131    final List internalStructuralPropertiesForType(int apiLevel) {
132        return propertyDescriptors(apiLevel);
133    }
134
135    @Override
136    final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor propertyboolean getboolean value) {
137        if (property == PARENTHESES_PROPERTY) {
138            if (get) {
139                return hasParentheses();
140            } else {
141                setParentheses(value);
142                return false;
143            }
144        }
145        // allow default implementation to flag the error
146        return super.internalGetSetBooleanProperty(propertygetvalue);
147    }
148
149    @Override
150    final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
151        if (property == PARAMETERS_PROPERTY) {
152            return parameters();
153        }
154        // allow default implementation to flag the error
155        return super.internalGetChildListProperty(property);
156    }
157
158    @Override
159    final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor propertyboolean getASTNode child) {
160        if (property == BODY_PROPERTY) {
161            if (get) {
162                return getBody();
163            } else {
164                setBodychild);
165                return null;
166            }
167        }
168        // allow default implementation to flag the error
169        return super.internalGetSetChildProperty(propertygetchild);
170    }
171
172    @Override
173    final int getNodeType0() {
174        return LAMBDA_EXPRESSION;
175    }
176
177    @Override
178    ASTNode clone0(AST target) {
179        LambdaExpression result = new LambdaExpression(target);
180        result.setSourceRange(getStartPosition(), getLength());
181        result.setParentheses(hasParentheses());
182        result.parameters().addAll(ASTNode.copySubtrees(targetparameters()));
183        result.setBody(ASTNode.copySubtree(targetgetBody()));
184        return result;
185    }
186
187    @Override
188    final boolean subtreeMatch0(ASTMatcher matcherObject other) {
189        // dispatch to correct overloaded match method
190        return matcher.match(this, other);
191    }
192
193    @Override
194    void accept0(ASTVisitor visitor) {
195        boolean visitChildren = visitor.visit(this);
196        if (visitChildren) {
197            // visit children in normal left to right reading order
198            acceptChildren(visitor, this.parameters);
199            acceptChild(visitorgetBody());
200        }
201        visitor.endVisit(this);
202    }
203
204    /**
205     * Returns whether parentheses around the parameters are present or not.
206     * <p>
207     * Note that parentheses are required unless {@link #parameters()} contains
208     * just a single {@link VariableDeclarationFragment}.
209     * ASTRewrite may ignore this property if necessary.
210     * </p>
211     *
212     * @return <code>true</code> if this lambda expression has parentheses around
213     * its parameters and <code>false</code> otherwise
214     */
215    public boolean hasParentheses() {
216        return this.hasParentheses;
217    }
218
219    /**
220     * Sets whether this lambda expression has parentheses around its parameters or not.
221     * <p>
222     * Note that parentheses are required unless {@link #parameters()} contains
223     * just a single {@link VariableDeclarationFragment}.
224     * ASTRewrite may ignore this property if necessary.
225     * </p>
226     *
227     * @param hasParentheses <code>true</code> if this lambda expression has parentheses around its parameters
228     *  and <code>false</code> otherwise
229     */
230    public void setParentheses(boolean hasParentheses) {
231        preValueChange(PARENTHESES_PROPERTY);
232        this.hasParentheses = hasParentheses;
233        postValueChange(PARENTHESES_PROPERTY);
234    }
235
236    /**
237     * Returns the live ordered list of formal parameters of this lambda expression.
238     * Note that all elements must be of the same type, either
239     * <ul>
240     * <li>all {@link SingleVariableDeclaration} (explicit type), or</li>
241     * <li>all {@link VariableDeclarationFragment} (inferred type).</li>
242     * </ul>
243     *
244     * @return the live list of formal parameters of this lambda expression
245     *    (element type: {@link VariableDeclaration})
246     */
247    public List parameters() {
248        return this.parameters;
249    }
250
251    /**
252     * Returns the body of this lambda expression.
253     *
254     * @return the lambda expression body, which can be either a {@link Block} or an {@link Expression}
255     */
256    public ASTNode getBody() {
257        if (this.body == null) {
258            // lazy init must be thread-safe for readers
259            synchronized (this) {
260                if (this.body == null) {
261                    preLazyInit();
262                    this.body = new Block(this.ast);
263                    postLazyInit(this.bodyBODY_PROPERTY);
264                }
265            }
266        }
267        return this.body;
268    }
269
270    /**
271     * Sets the body of this lambda expression.
272     *
273     * @param body a block node or an expression node
274     * @exception IllegalArgumentException if:
275     * <ul>
276     * <li>the node belongs to a different AST</li>
277     * <li>the node already has a parent</li>
278     * <li>a cycle in would be created</li>
279     * <li>body is neither a {@link Block} nor an {@link Expression}</li>
280     * </ul>
281     */
282    public void setBody(ASTNode body) {
283        if (!(body instanceof Expression || body instanceof Block)) {
284            throw new IllegalArgumentException();
285        }
286        ASTNode oldChild = this.body;
287        preReplaceChild(oldChildbodyBODY_PROPERTY);
288        this.body = body;
289        postReplaceChild(oldChildbodyBODY_PROPERTY);
290    }
291
292    /**
293     * Resolves and returns the binding for the lambda expression
294     * <p>
295     * Note that bindings are generally unavailable unless requested when the
296     * AST is being built.
297     * </p>
298     *
299     * @return the binding, or <code>null</code> if the binding cannot be
300     *    resolved
301     */
302    public IMethodBinding resolveMethodBinding() {
303        return this.ast.getBindingResolver().resolveMethod(this);
304    }
305
306    @Override
307    int memSize() {
308        return BASE_NODE_SIZE + 3 * 4;
309    }
310
311    @Override
312    int treeSize() {
313        return
314            memSize()
315            + this.parameters.listSize()
316            + (this.body == null ? 0 : getBody().treeSize());
317    }
318}
319
MembersX
LambdaExpression:parameters
LambdaExpression:Block:propertyList
LambdaExpression:propertyDescriptors
LambdaExpression:internalGetSetChildProperty
LambdaExpression:getNodeType0
LambdaExpression:setParentheses
LambdaExpression:PARAMETERS_PROPERTY
LambdaExpression:setBody
LambdaExpression:internalGetSetBooleanProperty
LambdaExpression:resolveMethodBinding
LambdaExpression:internalStructuralPropertiesForType
LambdaExpression:getBody
LambdaExpression:treeSize
LambdaExpression:PARENTHESES_PROPERTY
LambdaExpression:internalGetChildListProperty
LambdaExpression:LambdaExpression
LambdaExpression:subtreeMatch0
LambdaExpression:clone0
LambdaExpression:clone0:Block:result
LambdaExpression:accept0:Block:visitChildren
LambdaExpression:BODY_PROPERTY
LambdaExpression:setBody:Block:oldChild
LambdaExpression:body
LambdaExpression:hasParentheses
LambdaExpression:PROPERTY_DESCRIPTORS_8_0
LambdaExpression:accept0
LambdaExpression:memSize
Members
X