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.stmt; 22 23 import com.github.javaparser.TokenRange; 24 import com.github.javaparser.ast.AllFieldsConstructor; 25 import com.github.javaparser.ast.Node; 26 import com.github.javaparser.ast.NodeList; 27 import com.github.javaparser.ast.expr.Expression; 28 import com.github.javaparser.ast.observer.ObservableProperty; 29 import com.github.javaparser.ast.visitor.CloneVisitor; 30 import com.github.javaparser.ast.visitor.GenericVisitor; 31 import com.github.javaparser.ast.visitor.VoidVisitor; 32 import com.github.javaparser.metamodel.JavaParserMetaModel; 33 import com.github.javaparser.metamodel.OptionalProperty; 34 import com.github.javaparser.metamodel.TryStmtMetaModel; 35 import javax.annotation.Generated; 36 import java.util.Arrays; 37 import java.util.List; 38 import java.util.Optional; 39 import static com.github.javaparser.utils.Utils.assertNotNull; 40 import java.util.function.Consumer; 41 42 /** 43 * <h1>The try statement</h1> 44 * <h2>Java 1.0-6</h2> 45 * <pre> 46 * try { 47 * // ... 48 * } catch (IOException e) { 49 * // ... 50 * } finally { 51 * // ... 52 * } 53 * </pre> 54 * In this code, "// do things" is the content of the tryBlock, there is one catch clause that catches IOException e, 55 * and there is a finally block. 56 * <p> 57 * The catch and finally blocks are optional, but they should not be empty at the same time. 58 * <h2>Java 7-8</h2> 59 * <pre> 60 * try (InputStream i = new FileInputStream("file")) { 61 * // ... 62 * } catch (IOException|NullPointerException e) { 63 * // ... 64 * } finally { 65 * // ... 66 * } 67 * </pre> 68 * Java 7 introduced two things: 69 * <ul> 70 * <li>Resources can be specified after "try", but only variable declarations (VariableDeclarationExpr.)</li> 71 * <li>A single catch can catch multiple exception types. This uses the IntersectionType.</li> 72 * </ul> 73 * <h2>Java 9+</h2> 74 * <pre> 75 * try (r) { 76 * // ... 77 * } catch (IOException|NullPointerException e) { 78 * // ... 79 * } finally { 80 * // ... 81 * } 82 * </pre> 83 * Java 9 finishes resources: you can now refer to a resource that was declared somewhere else. 84 * The following types are allowed: 85 * <ul> 86 * <li>VariableDeclarationExpr: "X x = new X()" like in Java 7-8.</li> 87 * <li>NameExpr: "a".</li> 88 * <li>FieldAccessExpr: "x.y.z", "super.test" etc.</li> 89 * </ul> 90 * 91 * @author Julio Vilmar Gesser 92 * @see CatchClause 93 * @see com.github.javaparser.ast.type.IntersectionType 94 * @see com.github.javaparser.ast.expr.FieldAccessExpr 95 * @see com.github.javaparser.ast.expr.NameExpr 96 */ 97 public final class TryStmt extends Statement { 98 99 private NodeList<Expression> resources; 100 101 private BlockStmt tryBlock; 102 103 private NodeList<CatchClause> catchClauses; 104 105 @OptionalProperty 106 private BlockStmt finallyBlock; 107 108 public TryStmt() { 109 this(null, new NodeList<>(), new BlockStmt(), new NodeList<>(), null); 110 } 111 112 public TryStmt(final BlockStmt tryBlock, final NodeList<CatchClause> catchClauses, final BlockStmt finallyBlock) { 113 this(null, new NodeList<>(), tryBlock, catchClauses, finallyBlock); 114 } 115 116 @AllFieldsConstructor 117 public TryStmt(NodeList<Expression> resources, final BlockStmt tryBlock, final NodeList<CatchClause> catchClauses, final BlockStmt finallyBlock) { 118 this(null, resources, tryBlock, catchClauses, finallyBlock); 119 } 120 121 /** 122 * This constructor is used by the parser and is considered private. 123 */ 124 @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator") 125 public TryStmt(TokenRange tokenRange, NodeList<Expression> resources, BlockStmt tryBlock, NodeList<CatchClause> catchClauses, BlockStmt finallyBlock) { 126 super(tokenRange); 127 setResources(resources); 128 setTryBlock(tryBlock); 129 setCatchClauses(catchClauses); 130 setFinallyBlock(finallyBlock); 131 customInitialization(); 132 } 133 134 @Override 135 @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") 136 public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) { 137 return v.visit(this, arg); 138 } 139 140 @Override 141 @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") 142 public <A> void accept(final VoidVisitor<A> v, final A arg) { 143 v.visit(this, arg); 144 } 145 146 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 147 public NodeList<CatchClause> getCatchClauses() { 148 return catchClauses; 149 } 150 151 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 152 public Optional<BlockStmt> getFinallyBlock() { 153 return Optional.ofNullable(finallyBlock); 154 } 155 156 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 157 public BlockStmt getTryBlock() { 158 return tryBlock; 159 } 160 161 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 162 public NodeList<Expression> getResources() { 163 return resources; 164 } 165 166 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 167 public TryStmt setCatchClauses(final NodeList<CatchClause> catchClauses) { 168 assertNotNull(catchClauses); 169 if (catchClauses == this.catchClauses) { 170 return (TryStmt) this; 171 } 172 notifyPropertyChange(ObservableProperty.CATCH_CLAUSES, this.catchClauses, catchClauses); 173 if (this.catchClauses != null) 174 this.catchClauses.setParentNode(null); 175 this.catchClauses = catchClauses; 176 setAsParentNodeOf(catchClauses); 177 return this; 178 } 179 180 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 181 public TryStmt setFinallyBlock(final BlockStmt finallyBlock) { 182 if (finallyBlock == this.finallyBlock) { 183 return (TryStmt) this; 184 } 185 notifyPropertyChange(ObservableProperty.FINALLY_BLOCK, this.finallyBlock, finallyBlock); 186 if (this.finallyBlock != null) 187 this.finallyBlock.setParentNode(null); 188 this.finallyBlock = finallyBlock; 189 setAsParentNodeOf(finallyBlock); 190 return this; 191 } 192 193 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 194 public TryStmt setTryBlock(final BlockStmt tryBlock) { 195 assertNotNull(tryBlock); 196 if (tryBlock == this.tryBlock) { 197 return (TryStmt) this; 198 } 199 notifyPropertyChange(ObservableProperty.TRY_BLOCK, this.tryBlock, tryBlock); 200 if (this.tryBlock != null) 201 this.tryBlock.setParentNode(null); 202 this.tryBlock = tryBlock; 203 setAsParentNodeOf(tryBlock); 204 return this; 205 } 206 207 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 208 public TryStmt setResources(final NodeList<Expression> resources) { 209 assertNotNull(resources); 210 if (resources == this.resources) { 211 return (TryStmt) this; 212 } 213 notifyPropertyChange(ObservableProperty.RESOURCES, this.resources, resources); 214 if (this.resources != null) 215 this.resources.setParentNode(null); 216 this.resources = resources; 217 setAsParentNodeOf(resources); 218 return this; 219 } 220 221 @Override 222 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") 223 public boolean remove(Node node) { 224 if (node == null) 225 return false; 226 for (int i = 0; i < catchClauses.size(); i++) { 227 if (catchClauses.get(i) == node) { 228 catchClauses.remove(i); 229 return true; 230 } 231 } 232 if (finallyBlock != null) { 233 if (node == finallyBlock) { 234 removeFinallyBlock(); 235 return true; 236 } 237 } 238 for (int i = 0; i < resources.size(); i++) { 239 if (resources.get(i) == node) { 240 resources.remove(i); 241 return true; 242 } 243 } 244 return super.remove(node); 245 } 246 247 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") 248 public TryStmt removeFinallyBlock() { 249 return setFinallyBlock((BlockStmt) null); 250 } 251 252 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") 253 public TryStmt removeTryBlock() { 254 return setTryBlock((BlockStmt) null); 255 } 256 257 @Override 258 @Generated("com.github.javaparser.generator.core.node.CloneGenerator") 259 public TryStmt clone() { 260 return (TryStmt) accept(new CloneVisitor(), null); 261 } 262 263 @Override 264 @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator") 265 public TryStmtMetaModel getMetaModel() { 266 return JavaParserMetaModel.tryStmtMetaModel; 267 } 268 269 @Override 270 @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator") 271 public boolean replace(Node node, Node replacementNode) { 272 if (node == null) 273 return false; 274 for (int i = 0; i < catchClauses.size(); i++) { 275 if (catchClauses.get(i) == node) { 276 catchClauses.set(i, (CatchClause) replacementNode); 277 return true; 278 } 279 } 280 if (finallyBlock != null) { 281 if (node == finallyBlock) { 282 setFinallyBlock((BlockStmt) replacementNode); 283 return true; 284 } 285 } 286 for (int i = 0; i < resources.size(); i++) { 287 if (resources.get(i) == node) { 288 resources.set(i, (Expression) replacementNode); 289 return true; 290 } 291 } 292 if (node == tryBlock) { 293 setTryBlock((BlockStmt) replacementNode); 294 return true; 295 } 296 return super.replace(node, replacementNode); 297 } 298 299 @Override 300 @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") 301 public boolean isTryStmt() { 302 return true; 303 } 304 305 @Override 306 @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") 307 public TryStmt asTryStmt() { 308 return this; 309 } 310 311 @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") 312 public void ifTryStmt(Consumer<TryStmt> action) { 313 action.accept(this); 314 } 315 316 @Override 317 @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") 318 public Optional<TryStmt> toTryStmt() { 319 return Optional.of(this); 320 } 321 } 322