Home | History | Annotate | Download | only in expr
      1 /*
      2  * Copyright (C) 2007-2010 Jlio Vilmar Gesser.
      3  * Copyright (C) 2011, 2013-2016 The JavaParser Team.
      4  *
      5  * This file is part of JavaParser.
      6  *
      7  * JavaParser can be used either under the terms of
      8  * a) the GNU Lesser General Public License as published by
      9  *     the Free Software Foundation, either version 3 of the License, or
     10  *     (at your option) any later version.
     11  * b) the terms of the Apache License
     12  *
     13  * You should have received a copy of both licenses in LICENCE.LGPL and
     14  * LICENCE.APACHE. Please refer to those files for details.
     15  *
     16  * JavaParser is distributed in the hope that it will be useful,
     17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19  * GNU Lesser General Public License for more details.
     20  */
     21 package com.github.javaparser.ast.expr;
     22 
     23 import com.github.javaparser.ast.AllFieldsConstructor;
     24 import com.github.javaparser.ast.NodeList;
     25 import com.github.javaparser.ast.body.Parameter;
     26 import com.github.javaparser.ast.nodeTypes.NodeWithParameters;
     27 import com.github.javaparser.ast.observer.ObservableProperty;
     28 import com.github.javaparser.ast.stmt.ExpressionStmt;
     29 import com.github.javaparser.ast.stmt.ReturnStmt;
     30 import com.github.javaparser.ast.stmt.Statement;
     31 import com.github.javaparser.ast.visitor.GenericVisitor;
     32 import com.github.javaparser.ast.visitor.VoidVisitor;
     33 import java.util.Optional;
     34 import static com.github.javaparser.utils.Utils.assertNotNull;
     35 import com.github.javaparser.ast.Node;
     36 import com.github.javaparser.ast.visitor.CloneVisitor;
     37 import com.github.javaparser.metamodel.DerivedProperty;
     38 import com.github.javaparser.metamodel.LambdaExprMetaModel;
     39 import com.github.javaparser.metamodel.JavaParserMetaModel;
     40 import javax.annotation.Generated;
     41 import com.github.javaparser.TokenRange;
     42 import java.util.function.Consumer;
     43 
     44 /**
     45  * <h1>A lambda expression</h1>
     46  * <h2>Java 1-7</h2>
     47  * Does not exist.
     48  * <h2>Java 8+</h2>
     49  * <code>(a, b) -> a + b</code>
     50  * <br/><code>a -> ...</code>
     51  * <br/><code>(Long a) -> { println(a); }</code>
     52  * <p/>The parameters are on the left side of the ->.
     53  * If a parameter uses type inference (it has no type specified) then its type is set to <code>UnknownType</code>.
     54  * If they are in ( ), "isEnclosingParameters" is true.
     55  * <br/>The body is to the right of the ->.
     56  * The body is either a BlockStatement when it is in { } braces, or an ExpressionStatement when it is not in braces.
     57  *
     58  * @author Raquel Pau
     59  */
     60 public final class LambdaExpr extends Expression implements NodeWithParameters<LambdaExpr> {
     61 
     62     private NodeList<Parameter> parameters;
     63 
     64     private boolean isEnclosingParameters;
     65 
     66     private Statement body;
     67 
     68     public LambdaExpr() {
     69         this(null, new NodeList<>(), new ReturnStmt(), false);
     70     }
     71 
     72     @AllFieldsConstructor
     73     public LambdaExpr(NodeList<Parameter> parameters, Statement body, boolean isEnclosingParameters) {
     74         this(null, parameters, body, isEnclosingParameters);
     75     }
     76 
     77     /**
     78      * This constructor is used by the parser and is considered private.
     79      */
     80     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
     81     public LambdaExpr(TokenRange tokenRange, NodeList<Parameter> parameters, Statement body, boolean isEnclosingParameters) {
     82         super(tokenRange);
     83         setParameters(parameters);
     84         setBody(body);
     85         setEnclosingParameters(isEnclosingParameters);
     86         customInitialization();
     87     }
     88 
     89     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     90     public NodeList<Parameter> getParameters() {
     91         return parameters;
     92     }
     93 
     94     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     95     public LambdaExpr setParameters(final NodeList<Parameter> parameters) {
     96         assertNotNull(parameters);
     97         if (parameters == this.parameters) {
     98             return (LambdaExpr) this;
     99         }
    100         notifyPropertyChange(ObservableProperty.PARAMETERS, this.parameters, parameters);
    101         if (this.parameters != null)
    102             this.parameters.setParentNode(null);
    103         this.parameters = parameters;
    104         setAsParentNodeOf(parameters);
    105         return this;
    106     }
    107 
    108     /**
    109      * @return a BlockStatement or an ExpressionStatement. See class Javadoc.
    110      */
    111     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
    112     public Statement getBody() {
    113         return body;
    114     }
    115 
    116     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
    117     public LambdaExpr setBody(final Statement body) {
    118         assertNotNull(body);
    119         if (body == this.body) {
    120             return (LambdaExpr) this;
    121         }
    122         notifyPropertyChange(ObservableProperty.BODY, this.body, body);
    123         if (this.body != null)
    124             this.body.setParentNode(null);
    125         this.body = body;
    126         setAsParentNodeOf(body);
    127         return this;
    128     }
    129 
    130     @Override
    131     @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
    132     public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) {
    133         return v.visit(this, arg);
    134     }
    135 
    136     @Override
    137     @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
    138     public <A> void accept(final VoidVisitor<A> v, final A arg) {
    139         v.visit(this, arg);
    140     }
    141 
    142     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
    143     public boolean isEnclosingParameters() {
    144         return isEnclosingParameters;
    145     }
    146 
    147     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
    148     public LambdaExpr setEnclosingParameters(final boolean isEnclosingParameters) {
    149         if (isEnclosingParameters == this.isEnclosingParameters) {
    150             return (LambdaExpr) this;
    151         }
    152         notifyPropertyChange(ObservableProperty.ENCLOSING_PARAMETERS, this.isEnclosingParameters, isEnclosingParameters);
    153         this.isEnclosingParameters = isEnclosingParameters;
    154         return this;
    155     }
    156 
    157     @Override
    158     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
    159     public boolean remove(Node node) {
    160         if (node == null)
    161             return false;
    162         for (int i = 0; i < parameters.size(); i++) {
    163             if (parameters.get(i) == node) {
    164                 parameters.remove(i);
    165                 return true;
    166             }
    167         }
    168         return super.remove(node);
    169     }
    170 
    171     /**
    172      * @return if the body of this lambda is a simple expression, return that expression.
    173      * Otherwise (when the body is a block) return Optional.empty().
    174      */
    175     @DerivedProperty
    176     public Optional<Expression> getExpressionBody() {
    177         if (body.isExpressionStmt()) {
    178             return Optional.of(body.asExpressionStmt().getExpression());
    179         } else {
    180             return Optional.empty();
    181         }
    182     }
    183 
    184     @Override
    185     @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
    186     public LambdaExpr clone() {
    187         return (LambdaExpr) accept(new CloneVisitor(), null);
    188     }
    189 
    190     @Override
    191     @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
    192     public LambdaExprMetaModel getMetaModel() {
    193         return JavaParserMetaModel.lambdaExprMetaModel;
    194     }
    195 
    196     @Override
    197     @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
    198     public boolean replace(Node node, Node replacementNode) {
    199         if (node == null)
    200             return false;
    201         if (node == body) {
    202             setBody((Statement) replacementNode);
    203             return true;
    204         }
    205         for (int i = 0; i < parameters.size(); i++) {
    206             if (parameters.get(i) == node) {
    207                 parameters.set(i, (Parameter) replacementNode);
    208                 return true;
    209             }
    210         }
    211         return super.replace(node, replacementNode);
    212     }
    213 
    214     @Override
    215     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
    216     public boolean isLambdaExpr() {
    217         return true;
    218     }
    219 
    220     @Override
    221     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
    222     public LambdaExpr asLambdaExpr() {
    223         return this;
    224     }
    225 
    226     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
    227     public void ifLambdaExpr(Consumer<LambdaExpr> action) {
    228         action.accept(this);
    229     }
    230 
    231     @Override
    232     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
    233     public Optional<LambdaExpr> toLambdaExpr() {
    234         return Optional.of(this);
    235     }
    236 }
    237