CompilationUnit.java revision 4e845ed7ad59e4d904f164bc161d6afc1db0255b
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 public CompilationUnit setImports(final NodeList<ImportDeclaration> imports) { 178 assertNotNull(imports); 179 if (imports == this.imports) { 180 return (CompilationUnit) this; 181 } 182 notifyPropertyChange(ObservableProperty.IMPORTS, this.imports, imports); 183 if (this.imports != null) 184 this.imports.setParentNode(null); 185 this.imports = imports; 186 setAsParentNodeOf(imports); 187 return this; 188 } 189 190 public CompilationUnit setImport(int i, ImportDeclaration imports) { 191 getImports().set(i, imports); 192 return this; 193 } 194 195 public CompilationUnit addImport(ImportDeclaration imports) { 196 getImports().add(imports); 197 return this; 198 } 199 200 /** 201 * Sets or clear the package declarations of this compilation unit. 202 * 203 * @param packageDeclaration the packageDeclaration declaration to set or <code>null</code> to default package 204 */ 205 public CompilationUnit setPackageDeclaration(final PackageDeclaration packageDeclaration) { 206 if (packageDeclaration == this.packageDeclaration) { 207 return (CompilationUnit) this; 208 } 209 notifyPropertyChange(ObservableProperty.PACKAGE_DECLARATION, this.packageDeclaration, packageDeclaration); 210 if (this.packageDeclaration != null) 211 this.packageDeclaration.setParentNode(null); 212 this.packageDeclaration = packageDeclaration; 213 setAsParentNodeOf(packageDeclaration); 214 return this; 215 } 216 217 /** 218 * Sets the list of types declared in this compilation unit. 219 */ 220 public CompilationUnit setTypes(final NodeList<TypeDeclaration<?>> types) { 221 assertNotNull(types); 222 if (types == this.types) { 223 return (CompilationUnit) this; 224 } 225 notifyPropertyChange(ObservableProperty.TYPES, this.types, types); 226 if (this.types != null) 227 this.types.setParentNode(null); 228 this.types = types; 229 setAsParentNodeOf(types); 230 return this; 231 } 232 233 public CompilationUnit setType(int i, TypeDeclaration<?> type) { 234 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 235 copy.addAll(getTypes()); 236 getTypes().set(i, type); 237 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 238 return this; 239 } 240 241 public CompilationUnit addType(TypeDeclaration<?> type) { 242 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 243 copy.addAll(getTypes()); 244 getTypes().add(type); 245 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 246 return this; 247 } 248 249 /** 250 * sets the package declaration of this compilation unit 251 * 252 * @param name the name of the package 253 * @return this, the {@link CompilationUnit} 254 */ 255 public CompilationUnit setPackageDeclaration(String name) { 256 setPackageDeclaration(new PackageDeclaration(parseName(name))); 257 return this; 258 } 259 260 /** 261 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 262 * shorthand for {@link #addImport(String, boolean, boolean)} with name,false,false 263 * 264 * @param name the import name 265 * @return this, the {@link CompilationUnit} 266 */ 267 public CompilationUnit addImport(String name) { 268 return addImport(name, false, false); 269 } 270 271 /** 272 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 273 * shorthand for {@link #addImport(String)} with clazz.getName() 274 * 275 * @param clazz the class to import 276 * @return this, the {@link CompilationUnit} 277 */ 278 public CompilationUnit addImport(Class<?> clazz) { 279 if (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.getName().startsWith("java.lang")) 280 return this; 281 else if (clazz.isArray() && !ClassUtils.isPrimitiveOrWrapper(clazz.getComponentType()) && !clazz.getComponentType().getName().startsWith("java.lang")) 282 return addImport(clazz.getComponentType().getName()); 283 return addImport(clazz.getName()); 284 } 285 286 /** 287 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 288 * <b>This method check if no import with the same name is already in the list</b> 289 * 290 * @param name the import name 291 * @param isStatic is it an "import static" 292 * @param isAsterisk does the import end with ".*" 293 * @return this, the {@link CompilationUnit} 294 */ 295 public CompilationUnit addImport(String name, boolean isStatic, boolean isAsterisk) { 296 final StringBuilder i = new StringBuilder("import "); 297 if (isStatic) { 298 i.append("static "); 299 } 300 i.append(name); 301 if (isAsterisk) { 302 i.append(".*"); 303 } 304 i.append(";"); 305 ImportDeclaration importDeclaration = JavaParser.parseImport(i.toString()); 306 if (getImports().stream().anyMatch(im -> im.toString().equals(importDeclaration.toString()))) 307 return this; 308 else { 309 getImports().add(importDeclaration); 310 return this; 311 } 312 } 313 314 /** 315 * Add a public class to the types of this compilation unit 316 * 317 * @param name the class name 318 * @return the newly created class 319 */ 320 public ClassOrInterfaceDeclaration addClass(String name) { 321 return addClass(name, Modifier.PUBLIC); 322 } 323 324 /** 325 * Add a class to the types of this compilation unit 326 * 327 * @param name the class name 328 * @param modifiers the modifiers (like Modifier.PUBLIC) 329 * @return the newly created class 330 */ 331 public ClassOrInterfaceDeclaration addClass(String name, Modifier... modifiers) { 332 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), false, name); 333 getTypes().add(classOrInterfaceDeclaration); 334 return classOrInterfaceDeclaration; 335 } 336 337 /** 338 * Add a public interface class to the types of this compilation unit 339 * 340 * @param name the interface name 341 * @return the newly created class 342 */ 343 public ClassOrInterfaceDeclaration addInterface(String name) { 344 return addInterface(name, Modifier.PUBLIC); 345 } 346 347 /** 348 * Add an interface to the types of this compilation unit 349 * 350 * @param name the interface name 351 * @param modifiers the modifiers (like Modifier.PUBLIC) 352 * @return the newly created class 353 */ 354 public ClassOrInterfaceDeclaration addInterface(String name, Modifier... modifiers) { 355 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), true, name); 356 getTypes().add(classOrInterfaceDeclaration); 357 return classOrInterfaceDeclaration; 358 } 359 360 /** 361 * Add a public enum to the types of this compilation unit 362 * 363 * @param name the enum name 364 * @return the newly created class 365 */ 366 public EnumDeclaration addEnum(String name) { 367 return addEnum(name, Modifier.PUBLIC); 368 } 369 370 /** 371 * Add an enum to the types of this compilation unit 372 * 373 * @param name the enum name 374 * @param modifiers the modifiers (like Modifier.PUBLIC) 375 * @return the newly created class 376 */ 377 public EnumDeclaration addEnum(String name, Modifier... modifiers) { 378 EnumDeclaration enumDeclaration = new EnumDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 379 getTypes().add(enumDeclaration); 380 return enumDeclaration; 381 } 382 383 /** 384 * Add a public annotation declaration to the types of this compilation unit 385 * 386 * @param name the annotation name 387 * @return the newly created class 388 */ 389 public AnnotationDeclaration addAnnotationDeclaration(String name) { 390 return addAnnotationDeclaration(name, Modifier.PUBLIC); 391 } 392 393 /** 394 * Add an annotation declaration to the types of this compilation unit 395 * 396 * @param name the annotation name 397 * @param modifiers the modifiers (like Modifier.PUBLIC) 398 * @return the newly created class 399 */ 400 public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier... modifiers) { 401 AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 402 getTypes().add(annotationDeclaration); 403 return annotationDeclaration; 404 } 405 406 /** 407 * Try to get a class by its name 408 * 409 * @param className the class name (case-sensitive) 410 */ 411 public Optional<ClassOrInterfaceDeclaration> getClassByName(String className) { 412 return getTypes().stream().filter(type -> type.getNameAsString().equals(className) && type instanceof ClassOrInterfaceDeclaration && !((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 413 } 414 415 /** 416 * Try to get an interface by its name 417 * 418 * @param interfaceName the interface name (case-sensitive) 419 */ 420 public Optional<ClassOrInterfaceDeclaration> getInterfaceByName(String interfaceName) { 421 return getTypes().stream().filter(type -> type.getNameAsString().equals(interfaceName) && type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 422 } 423 424 /** 425 * Try to get an enum by its name 426 * 427 * @param enumName the enum name (case-sensitive) 428 */ 429 public Optional<EnumDeclaration> getEnumByName(String enumName) { 430 return getTypes().stream().filter(type -> type.getNameAsString().equals(enumName) && type instanceof EnumDeclaration).findFirst().map(t -> (EnumDeclaration) t); 431 } 432 433 /** 434 * Try to get an annotation by its name 435 * 436 * @param annotationName the annotation name (case-sensitive) 437 */ 438 public Optional<AnnotationDeclaration> getAnnotationDeclarationByName(String annotationName) { 439 return getTypes().stream().filter(type -> type.getNameAsString().equals(annotationName) && type instanceof AnnotationDeclaration).findFirst().map(t -> (AnnotationDeclaration) t); 440 } 441 442 @Override 443 public List<NodeList<?>> getNodeLists() { 444 return Arrays.asList(getImports(), getTypes()); 445 } 446 447 @Override 448 public boolean remove(Node node) { 449 if (node == null) 450 return false; 451 for (int i = 0; i < imports.size(); i++) { 452 if (imports.get(i) == node) { 453 imports.remove(i); 454 return true; 455 } 456 } 457 if (module != null) { 458 if (node == module) { 459 removeModule(); 460 return true; 461 } 462 } 463 if (packageDeclaration != null) { 464 if (node == packageDeclaration) { 465 removePackageDeclaration(); 466 return true; 467 } 468 } 469 for (int i = 0; i < types.size(); i++) { 470 if (types.get(i) == node) { 471 types.remove(i); 472 return true; 473 } 474 } 475 return super.remove(node); 476 } 477 478 public CompilationUnit removePackageDeclaration() { 479 return setPackageDeclaration((PackageDeclaration) null); 480 } 481 482 public Optional<ModuleDeclaration> getModule() { 483 return Optional.ofNullable(module); 484 } 485 486 public CompilationUnit setModule(final ModuleDeclaration module) { 487 if (module == this.module) { 488 return (CompilationUnit) this; 489 } 490 notifyPropertyChange(ObservableProperty.MODULE, this.module, module); 491 if (this.module != null) 492 this.module.setParentNode(null); 493 this.module = module; 494 setAsParentNodeOf(module); 495 return this; 496 } 497 498 public CompilationUnit removeModule() { 499 return setModule((ModuleDeclaration) null); 500 } 501 502 @Override 503 public CompilationUnit clone() { 504 return (CompilationUnit) accept(new CloneVisitor(), null); 505 } 506 507 @Override 508 public CompilationUnitMetaModel getMetaModel() { 509 return JavaParserMetaModel.compilationUnitMetaModel; 510 } 511} 512