CompilationUnit.java revision e4610d5f3acd6d03bf51e8c70584a065d3233387
1/* 2 * Copyright (C) 2007-2010 Júlio 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 */ 21package com.github.javaparser.ast; 22 23import com.github.javaparser.JavaParser; 24import com.github.javaparser.Range; 25import com.github.javaparser.ast.body.AnnotationDeclaration; 26import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 27import com.github.javaparser.ast.body.EnumDeclaration; 28import com.github.javaparser.ast.body.TypeDeclaration; 29import com.github.javaparser.ast.comments.Comment; 30import com.github.javaparser.ast.comments.JavadocComment; 31import com.github.javaparser.ast.expr.Name; 32import com.github.javaparser.ast.modules.ModuleDeclaration; 33import com.github.javaparser.ast.observer.ObservableProperty; 34import com.github.javaparser.ast.visitor.CloneVisitor; 35import com.github.javaparser.ast.visitor.GenericVisitor; 36import com.github.javaparser.ast.visitor.VoidVisitor; 37import com.github.javaparser.metamodel.CompilationUnitMetaModel; 38import com.github.javaparser.metamodel.InternalProperty; 39import com.github.javaparser.metamodel.JavaParserMetaModel; 40import com.github.javaparser.utils.ClassUtils; 41import java.util.Arrays; 42import java.util.EnumSet; 43import java.util.List; 44import java.util.Optional; 45import java.util.stream.Collectors; 46import static com.github.javaparser.JavaParser.parseName; 47import static com.github.javaparser.utils.Utils.assertNotNull; 48import javax.annotation.Generated; 49 50/** 51 * <p> 52 * This class represents the entire compilation unit. Each java file denotes a 53 * compilation unit. 54 * </p> 55 * A compilation unit start with an optional package declaration, 56 * followed by zero or more import declarations, 57 * followed by zero or more type declarations. 58 * 59 * @author Julio Vilmar Gesser 60 * @see PackageDeclaration 61 * @see ImportDeclaration 62 * @see TypeDeclaration 63 */ 64public final class CompilationUnit extends Node { 65 66 private PackageDeclaration packageDeclaration; 67 68 private NodeList<ImportDeclaration> imports; 69 70 private NodeList<TypeDeclaration<?>> types; 71 72 private ModuleDeclaration module; 73 74 public CompilationUnit() { 75 this(null, null, new NodeList<>(), new NodeList<>(), null); 76 } 77 78 public CompilationUnit(String packageDeclaration) { 79 this(null, new PackageDeclaration(new Name(packageDeclaration)), new NodeList<>(), new NodeList<>(), null); 80 } 81 82 @AllFieldsConstructor 83 public CompilationUnit(PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module) { 84 this(null, packageDeclaration, imports, types, module); 85 } 86 87 /**This constructor is used by the parser and is considered private.*/ 88 @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator") 89 public CompilationUnit(Range range, PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module) { 90 super(range); 91 setPackageDeclaration(packageDeclaration); 92 setImports(imports); 93 setTypes(types); 94 setModule(module); 95 customInitialization(); 96 } 97 98 @Override 99 public <R, A> R accept(GenericVisitor<R, A> v, A arg) { 100 return v.visit(this, arg); 101 } 102 103 @Override 104 public <A> void accept(VoidVisitor<A> v, A arg) { 105 v.visit(this, arg); 106 } 107 108 /** 109 * Return a list containing all comments declared in this compilation unit. 110 * Including javadocs, line comments and block comments of all types, 111 * inner-classes and other members.<br> 112 * If there is no comment, an empty list is returned. 113 * 114 * @return list with all comments of this compilation unit. 115 * @see JavadocComment 116 * @see com.github.javaparser.ast.comments.LineComment 117 * @see com.github.javaparser.ast.comments.BlockComment 118 */ 119 public List<Comment> getComments() { 120 return this.getAllContainedComments(); 121 } 122 123 /** 124 * Retrieves the list of imports declared in this compilation unit or 125 * <code>null</code> if there is no import. 126 * 127 * @return the list of imports or <code>none</code> if there is no import 128 */ 129 public NodeList<ImportDeclaration> getImports() { 130 return imports; 131 } 132 133 public ImportDeclaration getImport(int i) { 134 return getImports().get(i); 135 } 136 137 /** 138 * Retrieves the package declaration of this compilation unit.<br> 139 * If this compilation unit has no package declaration (default package), 140 * <code>Optional.none()</code> is returned. 141 * 142 * @return the package declaration or <code>none</code> 143 */ 144 public Optional<PackageDeclaration> getPackageDeclaration() { 145 return Optional.ofNullable(packageDeclaration); 146 } 147 148 /** 149 * Return the list of types declared in this compilation unit.<br> 150 * If there is no types declared, <code>none</code> is returned. 151 * 152 * @return the list of types or <code>none</code> null if there is no type 153 * @see AnnotationDeclaration 154 * @see ClassOrInterfaceDeclaration 155 * @see EnumDeclaration 156 */ 157 public NodeList<TypeDeclaration<?>> getTypes() { 158 return types; 159 } 160 161 /** 162 * Convenience method that wraps <code>getTypes()</code>.<br> 163 * If <code>i</code> is out of bounds, throws <code>IndexOutOfBoundsException.</code> 164 * 165 * @param i the index of the type declaration to retrieve 166 */ 167 public TypeDeclaration<?> getType(int i) { 168 return getTypes().get(i); 169 } 170 171 /** 172 * Sets the list of imports of this compilation unit. The list is initially 173 * <code>null</code>. 174 * 175 * @param imports the list of imports 176 */ 177 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 178 public CompilationUnit setImports(final NodeList<ImportDeclaration> imports) { 179 assertNotNull(imports); 180 if (imports == this.imports) { 181 return (CompilationUnit) this; 182 } 183 notifyPropertyChange(ObservableProperty.IMPORTS, this.imports, imports); 184 if (this.imports != null) 185 this.imports.setParentNode(null); 186 this.imports = imports; 187 setAsParentNodeOf(imports); 188 return this; 189 } 190 191 public CompilationUnit setImport(int i, ImportDeclaration imports) { 192 getImports().set(i, imports); 193 return this; 194 } 195 196 public CompilationUnit addImport(ImportDeclaration imports) { 197 getImports().add(imports); 198 return this; 199 } 200 201 /** 202 * Sets or clear the package declarations of this compilation unit. 203 * 204 * @param packageDeclaration the packageDeclaration declaration to set or <code>null</code> to default package 205 */ 206 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 207 public CompilationUnit setPackageDeclaration(final PackageDeclaration packageDeclaration) { 208 if (packageDeclaration == this.packageDeclaration) { 209 return (CompilationUnit) this; 210 } 211 notifyPropertyChange(ObservableProperty.PACKAGE_DECLARATION, this.packageDeclaration, packageDeclaration); 212 if (this.packageDeclaration != null) 213 this.packageDeclaration.setParentNode(null); 214 this.packageDeclaration = packageDeclaration; 215 setAsParentNodeOf(packageDeclaration); 216 return this; 217 } 218 219 /** 220 * Sets the list of types declared in this compilation unit. 221 */ 222 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 223 public CompilationUnit setTypes(final NodeList<TypeDeclaration<?>> types) { 224 assertNotNull(types); 225 if (types == this.types) { 226 return (CompilationUnit) this; 227 } 228 notifyPropertyChange(ObservableProperty.TYPES, this.types, types); 229 if (this.types != null) 230 this.types.setParentNode(null); 231 this.types = types; 232 setAsParentNodeOf(types); 233 return this; 234 } 235 236 public CompilationUnit setType(int i, TypeDeclaration<?> type) { 237 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 238 copy.addAll(getTypes()); 239 getTypes().set(i, type); 240 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 241 return this; 242 } 243 244 public CompilationUnit addType(TypeDeclaration<?> type) { 245 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 246 copy.addAll(getTypes()); 247 getTypes().add(type); 248 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 249 return this; 250 } 251 252 /** 253 * sets the package declaration of this compilation unit 254 * 255 * @param name the name of the package 256 * @return this, the {@link CompilationUnit} 257 */ 258 public CompilationUnit setPackageDeclaration(String name) { 259 setPackageDeclaration(new PackageDeclaration(parseName(name))); 260 return this; 261 } 262 263 /** 264 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 265 * shorthand for {@link #addImport(String, boolean, boolean)} with name,false,false 266 * 267 * @param name the import name 268 * @return this, the {@link CompilationUnit} 269 */ 270 public CompilationUnit addImport(String name) { 271 return addImport(name, false, false); 272 } 273 274 /** 275 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 276 * shorthand for {@link #addImport(String)} with clazz.getName() 277 * 278 * @param clazz the class to import 279 * @return this, the {@link CompilationUnit} 280 */ 281 public CompilationUnit addImport(Class<?> clazz) { 282 if (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.getName().startsWith("java.lang")) 283 return this; 284 else if (clazz.isArray() && !ClassUtils.isPrimitiveOrWrapper(clazz.getComponentType()) && !clazz.getComponentType().getName().startsWith("java.lang")) 285 return addImport(clazz.getComponentType().getName()); 286 return addImport(clazz.getName()); 287 } 288 289 /** 290 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 291 * <b>This method check if no import with the same name is already in the list</b> 292 * 293 * @param name the import name 294 * @param isStatic is it an "import static" 295 * @param isAsterisk does the import end with ".*" 296 * @return this, the {@link CompilationUnit} 297 */ 298 public CompilationUnit addImport(String name, boolean isStatic, boolean isAsterisk) { 299 final StringBuilder i = new StringBuilder("import "); 300 if (isStatic) { 301 i.append("static "); 302 } 303 i.append(name); 304 if (isAsterisk) { 305 i.append(".*"); 306 } 307 i.append(";"); 308 ImportDeclaration importDeclaration = JavaParser.parseImport(i.toString()); 309 if (getImports().stream().anyMatch(im -> im.toString().equals(importDeclaration.toString()))) 310 return this; 311 else { 312 getImports().add(importDeclaration); 313 return this; 314 } 315 } 316 317 /** 318 * Add a public class to the types of this compilation unit 319 * 320 * @param name the class name 321 * @return the newly created class 322 */ 323 public ClassOrInterfaceDeclaration addClass(String name) { 324 return addClass(name, Modifier.PUBLIC); 325 } 326 327 /** 328 * Add a class to the types of this compilation unit 329 * 330 * @param name the class name 331 * @param modifiers the modifiers (like Modifier.PUBLIC) 332 * @return the newly created class 333 */ 334 public ClassOrInterfaceDeclaration addClass(String name, Modifier... modifiers) { 335 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), false, name); 336 getTypes().add(classOrInterfaceDeclaration); 337 return classOrInterfaceDeclaration; 338 } 339 340 /** 341 * Add a public interface class to the types of this compilation unit 342 * 343 * @param name the interface name 344 * @return the newly created class 345 */ 346 public ClassOrInterfaceDeclaration addInterface(String name) { 347 return addInterface(name, Modifier.PUBLIC); 348 } 349 350 /** 351 * Add an interface to the types of this compilation unit 352 * 353 * @param name the interface name 354 * @param modifiers the modifiers (like Modifier.PUBLIC) 355 * @return the newly created class 356 */ 357 public ClassOrInterfaceDeclaration addInterface(String name, Modifier... modifiers) { 358 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), true, name); 359 getTypes().add(classOrInterfaceDeclaration); 360 return classOrInterfaceDeclaration; 361 } 362 363 /** 364 * Add a public enum to the types of this compilation unit 365 * 366 * @param name the enum name 367 * @return the newly created class 368 */ 369 public EnumDeclaration addEnum(String name) { 370 return addEnum(name, Modifier.PUBLIC); 371 } 372 373 /** 374 * Add an enum to the types of this compilation unit 375 * 376 * @param name the enum name 377 * @param modifiers the modifiers (like Modifier.PUBLIC) 378 * @return the newly created class 379 */ 380 public EnumDeclaration addEnum(String name, Modifier... modifiers) { 381 EnumDeclaration enumDeclaration = new EnumDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 382 getTypes().add(enumDeclaration); 383 return enumDeclaration; 384 } 385 386 /** 387 * Add a public annotation declaration to the types of this compilation unit 388 * 389 * @param name the annotation name 390 * @return the newly created class 391 */ 392 public AnnotationDeclaration addAnnotationDeclaration(String name) { 393 return addAnnotationDeclaration(name, Modifier.PUBLIC); 394 } 395 396 /** 397 * Add an annotation declaration to the types of this compilation unit 398 * 399 * @param name the annotation name 400 * @param modifiers the modifiers (like Modifier.PUBLIC) 401 * @return the newly created class 402 */ 403 public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier... modifiers) { 404 AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 405 getTypes().add(annotationDeclaration); 406 return annotationDeclaration; 407 } 408 409 /** 410 * Try to get a class by its name 411 * 412 * @param className the class name (case-sensitive) 413 */ 414 public Optional<ClassOrInterfaceDeclaration> getClassByName(String className) { 415 return getTypes().stream().filter(type -> type.getNameAsString().equals(className) && type instanceof ClassOrInterfaceDeclaration && !((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 416 } 417 418 /** 419 * Try to get an interface by its name 420 * 421 * @param interfaceName the interface name (case-sensitive) 422 */ 423 public Optional<ClassOrInterfaceDeclaration> getInterfaceByName(String interfaceName) { 424 return getTypes().stream().filter(type -> type.getNameAsString().equals(interfaceName) && type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 425 } 426 427 /** 428 * Try to get an enum by its name 429 * 430 * @param enumName the enum name (case-sensitive) 431 */ 432 public Optional<EnumDeclaration> getEnumByName(String enumName) { 433 return getTypes().stream().filter(type -> type.getNameAsString().equals(enumName) && type instanceof EnumDeclaration).findFirst().map(t -> (EnumDeclaration) t); 434 } 435 436 /** 437 * Try to get an annotation by its name 438 * 439 * @param annotationName the annotation name (case-sensitive) 440 */ 441 public Optional<AnnotationDeclaration> getAnnotationDeclarationByName(String annotationName) { 442 return getTypes().stream().filter(type -> type.getNameAsString().equals(annotationName) && type instanceof AnnotationDeclaration).findFirst().map(t -> (AnnotationDeclaration) t); 443 } 444 445 @Override 446 @Generated("com.github.javaparser.generator.core.node.GetNodeListsGenerator") 447 public List<NodeList<?>> getNodeLists() { 448 return Arrays.asList(getImports(), getTypes()); 449 } 450 451 @Override 452 public boolean remove(Node node) { 453 if (node == null) 454 return false; 455 for (int i = 0; i < imports.size(); i++) { 456 if (imports.get(i) == node) { 457 imports.remove(i); 458 return true; 459 } 460 } 461 if (module != null) { 462 if (node == module) { 463 removeModule(); 464 return true; 465 } 466 } 467 if (packageDeclaration != null) { 468 if (node == packageDeclaration) { 469 removePackageDeclaration(); 470 return true; 471 } 472 } 473 for (int i = 0; i < types.size(); i++) { 474 if (types.get(i) == node) { 475 types.remove(i); 476 return true; 477 } 478 } 479 return super.remove(node); 480 } 481 482 public CompilationUnit removePackageDeclaration() { 483 return setPackageDeclaration((PackageDeclaration) null); 484 } 485 486 public Optional<ModuleDeclaration> getModule() { 487 return Optional.ofNullable(module); 488 } 489 490 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") 491 public CompilationUnit setModule(final ModuleDeclaration module) { 492 if (module == this.module) { 493 return (CompilationUnit) this; 494 } 495 notifyPropertyChange(ObservableProperty.MODULE, this.module, module); 496 if (this.module != null) 497 this.module.setParentNode(null); 498 this.module = module; 499 setAsParentNodeOf(module); 500 return this; 501 } 502 503 public CompilationUnit removeModule() { 504 return setModule((ModuleDeclaration) null); 505 } 506 507 @Override 508 @Generated("com.github.javaparser.generator.core.node.CloneGenerator") 509 public CompilationUnit clone() { 510 return (CompilationUnit) accept(new CloneVisitor(), null); 511 } 512 513 @Override 514 @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator") 515 public CompilationUnitMetaModel getMetaModel() { 516 return JavaParserMetaModel.compilationUnitMetaModel; 517 } 518} 519