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