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 */ 21 package com.github.javaparser.ast; 22 23 import com.github.javaparser.JavaParser; 24 import com.github.javaparser.ParseResult; 25 import com.github.javaparser.ParseStart; 26 import com.github.javaparser.TokenRange; 27 import com.github.javaparser.ast.body.AnnotationDeclaration; 28 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 29 import com.github.javaparser.ast.body.EnumDeclaration; 30 import com.github.javaparser.ast.body.TypeDeclaration; 31 import com.github.javaparser.ast.comments.Comment; 32 import com.github.javaparser.ast.comments.JavadocComment; 33 import com.github.javaparser.ast.expr.Name; 34 import com.github.javaparser.ast.modules.ModuleDeclaration; 35 import com.github.javaparser.ast.nodeTypes.NodeWithName; 36 import com.github.javaparser.ast.observer.ObservableProperty; 37 import com.github.javaparser.ast.visitor.CloneVisitor; 38 import com.github.javaparser.ast.visitor.GenericVisitor; 39 import com.github.javaparser.ast.visitor.VoidVisitor; 40 import com.github.javaparser.metamodel.CompilationUnitMetaModel; 41 import com.github.javaparser.metamodel.InternalProperty; 42 import com.github.javaparser.metamodel.JavaParserMetaModel; 43 import com.github.javaparser.metamodel.OptionalProperty; 44 import com.github.javaparser.printer.PrettyPrinter; 45 import com.github.javaparser.utils.ClassUtils; 46 import com.github.javaparser.utils.CodeGenerationUtils; 47 import com.github.javaparser.utils.Utils; 48 import javax.annotation.Generated; 49 import java.io.IOException; 50 import java.nio.file.Files; 51 import java.nio.file.Path; 52 import java.nio.file.Paths; 53 import java.util.Arrays; 54 import java.util.EnumSet; 55 import java.util.List; 56 import java.util.Optional; 57 import java.util.function.Function; 58 import java.util.stream.Collectors; 59 import static com.github.javaparser.JavaParser.parseName; 60 import static com.github.javaparser.Providers.UTF8; 61 import static com.github.javaparser.Providers.provider; 62 import static com.github.javaparser.utils.CodeGenerationUtils.subtractPaths; 63 import static com.github.javaparser.utils.Utils.assertNotNull; 64 import com.github.javaparser.ast.Node; 65 66 /** 67 * <p> 68 * This class represents the entire compilation unit. Each java file denotes a 69 * compilation unit. 70 * </p> 71 * A compilation unit start with an optional package declaration, 72 * followed by zero or more import declarations, 73 * followed by zero or more type declarations. 74 * 75 * @author Julio Vilmar Gesser 76 * @see PackageDeclaration 77 * @see ImportDeclaration 78 * @see TypeDeclaration 79 * @see Storage 80 */ 81 public final class CompilationUnit extends Node { 82 83 @OptionalProperty 84 private PackageDeclaration packageDeclaration; 85 86 private NodeList<ImportDeclaration> imports; 87 88 private NodeList<TypeDeclaration<?>> types; 89 90 @OptionalProperty 91 private ModuleDeclaration module; 92 93 @InternalProperty 94 private Storage storage; 95 CompilationUnit()96 public CompilationUnit() { 97 this(null, null, new NodeList<>(), new NodeList<>(), null); 98 } 99 CompilationUnit(String packageDeclaration)100 public CompilationUnit(String packageDeclaration) { 101 this(null, new PackageDeclaration(new Name(packageDeclaration)), new NodeList<>(), new NodeList<>(), null); 102 } 103 104 @AllFieldsConstructor CompilationUnit(PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module)105 public CompilationUnit(PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module) { 106 this(null, packageDeclaration, imports, types, module); 107 } 108 109 /** 110 * This constructor is used by the parser and is considered private. 111 */ 112 @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator") CompilationUnit(TokenRange tokenRange, PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module)113 public CompilationUnit(TokenRange tokenRange, PackageDeclaration packageDeclaration, NodeList<ImportDeclaration> imports, NodeList<TypeDeclaration<?>> types, ModuleDeclaration module) { 114 super(tokenRange); 115 setPackageDeclaration(packageDeclaration); 116 setImports(imports); 117 setTypes(types); 118 setModule(module); 119 customInitialization(); 120 } 121 122 @Override 123 @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") accept(final GenericVisitor<R, A> v, final A arg)124 public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) { 125 return v.visit(this, arg); 126 } 127 128 @Override 129 @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") accept(final VoidVisitor<A> v, final A arg)130 public <A> void accept(final VoidVisitor<A> v, final A arg) { 131 v.visit(this, arg); 132 } 133 134 /** 135 * Return a list containing all comments declared in this compilation unit. 136 * Including javadocs, line comments and block comments of all types, 137 * inner-classes and other members.<br> 138 * If there is no comment, an empty list is returned. 139 * 140 * @return list with all comments of this compilation unit. 141 * @see JavadocComment 142 * @see com.github.javaparser.ast.comments.LineComment 143 * @see com.github.javaparser.ast.comments.BlockComment 144 */ getComments()145 public List<Comment> getComments() { 146 return this.getAllContainedComments(); 147 } 148 149 /** 150 * Retrieves the list of imports declared in this compilation unit or 151 * <code>null</code> if there is no import. 152 * 153 * @return the list of imports or <code>none</code> if there is no import 154 */ 155 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") getImports()156 public NodeList<ImportDeclaration> getImports() { 157 return imports; 158 } 159 getImport(int i)160 public ImportDeclaration getImport(int i) { 161 return getImports().get(i); 162 } 163 164 /** 165 * Retrieves the package declaration of this compilation unit.<br> 166 * If this compilation unit has no package declaration (default package), 167 * <code>Optional.none()</code> is returned. 168 * 169 * @return the package declaration or <code>none</code> 170 */ 171 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") getPackageDeclaration()172 public Optional<PackageDeclaration> getPackageDeclaration() { 173 return Optional.ofNullable(packageDeclaration); 174 } 175 176 /** 177 * Return the list of top level types declared in this compilation unit.<br> 178 * If there are no types declared, <code>none</code> is returned. 179 * 180 * @return the list of types or <code>none</code> null if there is no type 181 * @see AnnotationDeclaration 182 * @see ClassOrInterfaceDeclaration 183 * @see EnumDeclaration 184 */ 185 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") getTypes()186 public NodeList<TypeDeclaration<?>> getTypes() { 187 return types; 188 } 189 190 /** 191 * Convenience method that wraps <code>getTypes()</code>.<br> 192 * If <code>i</code> is out of bounds, throws <code>IndexOutOfBoundsException.</code> 193 * 194 * @param i the index of the type declaration to retrieve 195 */ getType(int i)196 public TypeDeclaration<?> getType(int i) { 197 return getTypes().get(i); 198 } 199 200 /** 201 * Sets the list of imports of this compilation unit. The list is initially 202 * <code>null</code>. 203 * 204 * @param imports the list of imports 205 */ 206 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") setImports(final NodeList<ImportDeclaration> imports)207 public CompilationUnit setImports(final NodeList<ImportDeclaration> imports) { 208 assertNotNull(imports); 209 if (imports == this.imports) { 210 return (CompilationUnit) this; 211 } 212 notifyPropertyChange(ObservableProperty.IMPORTS, this.imports, imports); 213 if (this.imports != null) 214 this.imports.setParentNode(null); 215 this.imports = imports; 216 setAsParentNodeOf(imports); 217 return this; 218 } 219 setImport(int i, ImportDeclaration imports)220 public CompilationUnit setImport(int i, ImportDeclaration imports) { 221 getImports().set(i, imports); 222 return this; 223 } 224 addImport(ImportDeclaration imports)225 public CompilationUnit addImport(ImportDeclaration imports) { 226 getImports().add(imports); 227 return this; 228 } 229 230 /** 231 * Sets or clear the package declarations of this compilation unit. 232 * 233 * @param packageDeclaration the packageDeclaration declaration to set or <code>null</code> to default package 234 */ 235 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") setPackageDeclaration(final PackageDeclaration packageDeclaration)236 public CompilationUnit setPackageDeclaration(final PackageDeclaration packageDeclaration) { 237 if (packageDeclaration == this.packageDeclaration) { 238 return (CompilationUnit) this; 239 } 240 notifyPropertyChange(ObservableProperty.PACKAGE_DECLARATION, this.packageDeclaration, packageDeclaration); 241 if (this.packageDeclaration != null) 242 this.packageDeclaration.setParentNode(null); 243 this.packageDeclaration = packageDeclaration; 244 setAsParentNodeOf(packageDeclaration); 245 return this; 246 } 247 248 /** 249 * Sets the list of types declared in this compilation unit. 250 */ 251 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") setTypes(final NodeList<TypeDeclaration<?>> types)252 public CompilationUnit setTypes(final NodeList<TypeDeclaration<?>> types) { 253 assertNotNull(types); 254 if (types == this.types) { 255 return (CompilationUnit) this; 256 } 257 notifyPropertyChange(ObservableProperty.TYPES, this.types, types); 258 if (this.types != null) 259 this.types.setParentNode(null); 260 this.types = types; 261 setAsParentNodeOf(types); 262 return this; 263 } 264 setType(int i, TypeDeclaration<?> type)265 public CompilationUnit setType(int i, TypeDeclaration<?> type) { 266 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 267 copy.addAll(getTypes()); 268 getTypes().set(i, type); 269 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 270 return this; 271 } 272 addType(TypeDeclaration<?> type)273 public CompilationUnit addType(TypeDeclaration<?> type) { 274 NodeList<TypeDeclaration<?>> copy = new NodeList<>(); 275 copy.addAll(getTypes()); 276 getTypes().add(type); 277 notifyPropertyChange(ObservableProperty.TYPES, copy, types); 278 return this; 279 } 280 281 /** 282 * sets the package declaration of this compilation unit 283 * 284 * @param name the name of the package 285 * @return this, the {@link CompilationUnit} 286 */ setPackageDeclaration(String name)287 public CompilationUnit setPackageDeclaration(String name) { 288 setPackageDeclaration(new PackageDeclaration(parseName(name))); 289 return this; 290 } 291 292 /** 293 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 294 * shorthand for {@link #addImport(String, boolean, boolean)} with name,false,false 295 * 296 * @param name the import name 297 * @return this, the {@link CompilationUnit} 298 */ addImport(String name)299 public CompilationUnit addImport(String name) { 300 return addImport(name, false, false); 301 } 302 303 /** 304 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 305 * shorthand for {@link #addImport(String)} with clazz.getName() 306 * 307 * @param clazz the class to import 308 * @return this, the {@link CompilationUnit} 309 * @throws RuntimeException if clazz is an anonymous or local class 310 */ addImport(Class<?> clazz)311 public CompilationUnit addImport(Class<?> clazz) { 312 if (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.getName().startsWith("java.lang")) 313 return this; 314 else if (clazz.isMemberClass()) 315 return addImport(clazz.getName().replace("$", ".")); 316 else if (clazz.isArray() && !ClassUtils.isPrimitiveOrWrapper(clazz.getComponentType()) && !clazz.getComponentType().getName().startsWith("java.lang")) 317 return addImport(clazz.getComponentType().getName()); 318 else if (clazz.isAnonymousClass() || clazz.isLocalClass()) 319 throw new RuntimeException(clazz.getName() + " is an anonymous or local class therefore it can't be added with addImport"); 320 return addImport(clazz.getName()); 321 } 322 323 /** 324 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 325 * <b>This method check if no import with the same name is already in the list</b> 326 * 327 * @param name the import name 328 * @param isStatic is it an "import static" 329 * @param isAsterisk does the import end with ".*" 330 * @return this, the {@link CompilationUnit} 331 */ addImport(String name, boolean isStatic, boolean isAsterisk)332 public CompilationUnit addImport(String name, boolean isStatic, boolean isAsterisk) { 333 final StringBuilder i = new StringBuilder("import "); 334 if (isStatic) { 335 i.append("static "); 336 } 337 i.append(name); 338 if (isAsterisk) { 339 i.append(".*"); 340 } 341 i.append(";"); 342 ImportDeclaration importDeclaration = JavaParser.parseImport(i.toString()); 343 if (getImports().stream().anyMatch(im -> im.toString().equals(importDeclaration.toString()))) 344 return this; 345 else { 346 getImports().add(importDeclaration); 347 return this; 348 } 349 } 350 351 /** 352 * Add a public class to the types of this compilation unit 353 * 354 * @param name the class name 355 * @return the newly created class 356 */ addClass(String name)357 public ClassOrInterfaceDeclaration addClass(String name) { 358 return addClass(name, Modifier.PUBLIC); 359 } 360 361 /** 362 * Add a class to the types of this compilation unit 363 * 364 * @param name the class name 365 * @param modifiers the modifiers (like Modifier.PUBLIC) 366 * @return the newly created class 367 */ addClass(String name, Modifier... modifiers)368 public ClassOrInterfaceDeclaration addClass(String name, Modifier... modifiers) { 369 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), false, name); 370 getTypes().add(classOrInterfaceDeclaration); 371 return classOrInterfaceDeclaration; 372 } 373 374 /** 375 * Add a public interface class to the types of this compilation unit 376 * 377 * @param name the interface name 378 * @return the newly created class 379 */ addInterface(String name)380 public ClassOrInterfaceDeclaration addInterface(String name) { 381 return addInterface(name, Modifier.PUBLIC); 382 } 383 384 /** 385 * Add an interface to the types of this compilation unit 386 * 387 * @param name the interface name 388 * @param modifiers the modifiers (like Modifier.PUBLIC) 389 * @return the newly created class 390 */ addInterface(String name, Modifier... modifiers)391 public ClassOrInterfaceDeclaration addInterface(String name, Modifier... modifiers) { 392 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), true, name); 393 getTypes().add(classOrInterfaceDeclaration); 394 return classOrInterfaceDeclaration; 395 } 396 397 /** 398 * Add a public enum to the types of this compilation unit 399 * 400 * @param name the enum name 401 * @return the newly created class 402 */ addEnum(String name)403 public EnumDeclaration addEnum(String name) { 404 return addEnum(name, Modifier.PUBLIC); 405 } 406 407 /** 408 * Add an enum to the types of this compilation unit 409 * 410 * @param name the enum name 411 * @param modifiers the modifiers (like Modifier.PUBLIC) 412 * @return the newly created class 413 */ addEnum(String name, Modifier... modifiers)414 public EnumDeclaration addEnum(String name, Modifier... modifiers) { 415 EnumDeclaration enumDeclaration = new EnumDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 416 getTypes().add(enumDeclaration); 417 return enumDeclaration; 418 } 419 420 /** 421 * Add a public annotation declaration to the types of this compilation unit 422 * 423 * @param name the annotation name 424 * @return the newly created class 425 */ addAnnotationDeclaration(String name)426 public AnnotationDeclaration addAnnotationDeclaration(String name) { 427 return addAnnotationDeclaration(name, Modifier.PUBLIC); 428 } 429 430 /** 431 * Add an annotation declaration to the types of this compilation unit 432 * 433 * @param name the annotation name 434 * @param modifiers the modifiers (like Modifier.PUBLIC) 435 * @return the newly created class 436 */ addAnnotationDeclaration(String name, Modifier... modifiers)437 public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier... modifiers) { 438 AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 439 getTypes().add(annotationDeclaration); 440 return annotationDeclaration; 441 } 442 443 /** 444 * Try to get a top level class declaration by its name 445 * 446 * @param className the class name (case-sensitive) 447 */ getClassByName(String className)448 public Optional<ClassOrInterfaceDeclaration> getClassByName(String className) { 449 return getTypes().stream().filter(type -> type.getNameAsString().equals(className) && type instanceof ClassOrInterfaceDeclaration && !((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 450 } 451 452 /** 453 * Try to get a top level interface declaration by its name 454 * 455 * @param interfaceName the interface name (case-sensitive) 456 */ getInterfaceByName(String interfaceName)457 public Optional<ClassOrInterfaceDeclaration> getInterfaceByName(String interfaceName) { 458 return getTypes().stream().filter(type -> type.getNameAsString().equals(interfaceName) && type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) type).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclaration) t); 459 } 460 461 /** 462 * Try to get a top level enum declaration by its name 463 * 464 * @param enumName the enum name (case-sensitive) 465 */ getEnumByName(String enumName)466 public Optional<EnumDeclaration> getEnumByName(String enumName) { 467 return getTypes().stream().filter(type -> type.getNameAsString().equals(enumName) && type instanceof EnumDeclaration).findFirst().map(t -> (EnumDeclaration) t); 468 } 469 470 /** 471 * @return the name that the primary type in this file should have, according to the filename in {@link Storage#getFileName()}. 472 * Empty if no file information is present (when this compilation unit wasn't parsed from a file.) 473 */ getPrimaryTypeName()474 public Optional<String> getPrimaryTypeName() { 475 return getStorage().map(Storage::getFileName).map(Utils::removeFileExtension); 476 } 477 478 /** 479 * @return the type whose name corresponds to the file name. 480 * Empty if no file information is present (when this compilation unit wasn't parsed from a file.) 481 * If for some strange reason there are multiple types of this name, the first one is returned. 482 */ getPrimaryType()483 public Optional<TypeDeclaration<?>> getPrimaryType() { 484 return getPrimaryTypeName().flatMap(name -> getTypes().stream().filter(t -> t.getNameAsString().equals(name)).findFirst()); 485 } 486 487 /** 488 * Try to get a top level annotation type declaration by its name 489 * 490 * @param annotationName the annotation name (case-sensitive) 491 */ getAnnotationDeclarationByName(String annotationName)492 public Optional<AnnotationDeclaration> getAnnotationDeclarationByName(String annotationName) { 493 return getTypes().stream().filter(type -> type.getNameAsString().equals(annotationName) && type instanceof AnnotationDeclaration).findFirst().map(t -> (AnnotationDeclaration) t); 494 } 495 496 @Override 497 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") remove(Node node)498 public boolean remove(Node node) { 499 if (node == null) 500 return false; 501 for (int i = 0; i < imports.size(); i++) { 502 if (imports.get(i) == node) { 503 imports.remove(i); 504 return true; 505 } 506 } 507 if (module != null) { 508 if (node == module) { 509 removeModule(); 510 return true; 511 } 512 } 513 if (packageDeclaration != null) { 514 if (node == packageDeclaration) { 515 removePackageDeclaration(); 516 return true; 517 } 518 } 519 for (int i = 0; i < types.size(); i++) { 520 if (types.get(i) == node) { 521 types.remove(i); 522 return true; 523 } 524 } 525 return super.remove(node); 526 } 527 528 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") removePackageDeclaration()529 public CompilationUnit removePackageDeclaration() { 530 return setPackageDeclaration((PackageDeclaration) null); 531 } 532 533 /** 534 * @return the module declared in this compilation unit. 535 */ 536 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") getModule()537 public Optional<ModuleDeclaration> getModule() { 538 return Optional.ofNullable(module); 539 } 540 541 @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") setModule(final ModuleDeclaration module)542 public CompilationUnit setModule(final ModuleDeclaration module) { 543 if (module == this.module) { 544 return (CompilationUnit) this; 545 } 546 notifyPropertyChange(ObservableProperty.MODULE, this.module, module); 547 if (this.module != null) 548 this.module.setParentNode(null); 549 this.module = module; 550 setAsParentNodeOf(module); 551 return this; 552 } 553 554 @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") removeModule()555 public CompilationUnit removeModule() { 556 return setModule((ModuleDeclaration) null); 557 } 558 559 /** 560 * @return information about where this compilation unit was loaded from, or empty if it wasn't loaded from a file. 561 */ getStorage()562 public Optional<Storage> getStorage() { 563 return Optional.ofNullable(storage); 564 } 565 setStorage(Path path)566 public CompilationUnit setStorage(Path path) { 567 this.storage = new Storage(this, path); 568 return this; 569 } 570 571 /** 572 * Information about where this compilation unit was loaded from. 573 * This class only stores the absolute location. 574 * For more flexibility use SourceRoot. 575 */ 576 public static class Storage { 577 578 private final CompilationUnit compilationUnit; 579 580 private final Path path; 581 Storage(CompilationUnit compilationUnit, Path path)582 private Storage(CompilationUnit compilationUnit, Path path) { 583 this.compilationUnit = compilationUnit; 584 this.path = path.toAbsolutePath(); 585 } 586 587 /** 588 * @return the path to the source for this CompilationUnit 589 */ getPath()590 public Path getPath() { 591 return path; 592 } 593 594 /** 595 * @return the CompilationUnit this Storage is about. 596 */ getCompilationUnit()597 public CompilationUnit getCompilationUnit() { 598 return compilationUnit; 599 } 600 601 /** 602 * @return the source root directory, calculated from the path of this compiation unit, and the package 603 * declaration of this compilation unit. If the package declaration is invalid (when it does not match the end 604 * of the path) a RuntimeException is thrown. 605 */ getSourceRoot()606 public Path getSourceRoot() { 607 final Optional<String> pkgAsString = compilationUnit.getPackageDeclaration().map(NodeWithName::getNameAsString); 608 return pkgAsString.map(p -> Paths.get(CodeGenerationUtils.packageToPath(p))).map(pkg -> subtractPaths(getDirectory(), pkg)).orElse(getDirectory()); 609 } 610 getFileName()611 public String getFileName() { 612 return path.getFileName().toString(); 613 } 614 getDirectory()615 public Path getDirectory() { 616 return path.getParent(); 617 } 618 619 /** 620 * Saves the compilation unit to its original location 621 */ save()622 public void save() { 623 save(cu -> new PrettyPrinter().print(cu)); 624 } 625 626 /** 627 * Saves a compilation unit to its original location with formatting according to the function 628 * passed as a parameter. 629 * 630 * @param makeOutput a function that formats the compilation unit 631 */ save(Function<CompilationUnit, String> makeOutput)632 public void save(Function<CompilationUnit, String> makeOutput) { 633 try { 634 Files.createDirectories(path.getParent()); 635 final String code = makeOutput.apply(getCompilationUnit()); 636 Files.write(path, code.getBytes(UTF8)); 637 } catch (IOException e) { 638 throw new RuntimeException(e); 639 } 640 } 641 reparse(JavaParser javaParser)642 public ParseResult<CompilationUnit> reparse(JavaParser javaParser) { 643 try { 644 return javaParser.parse(ParseStart.COMPILATION_UNIT, provider(getPath())); 645 } catch (IOException e) { 646 throw new RuntimeException(e); 647 } 648 } 649 } 650 651 @Override 652 @Generated("com.github.javaparser.generator.core.node.CloneGenerator") clone()653 public CompilationUnit clone() { 654 return (CompilationUnit) accept(new CloneVisitor(), null); 655 } 656 657 @Override 658 @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator") getMetaModel()659 public CompilationUnitMetaModel getMetaModel() { 660 return JavaParserMetaModel.compilationUnitMetaModel; 661 } 662 663 @Override 664 @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator") replace(Node node, Node replacementNode)665 public boolean replace(Node node, Node replacementNode) { 666 if (node == null) 667 return false; 668 for (int i = 0; i < imports.size(); i++) { 669 if (imports.get(i) == node) { 670 imports.set(i, (ImportDeclaration) replacementNode); 671 return true; 672 } 673 } 674 if (module != null) { 675 if (node == module) { 676 setModule((ModuleDeclaration) replacementNode); 677 return true; 678 } 679 } 680 if (packageDeclaration != null) { 681 if (node == packageDeclaration) { 682 setPackageDeclaration((PackageDeclaration) replacementNode); 683 return true; 684 } 685 } 686 for (int i = 0; i < types.size(); i++) { 687 if (types.get(i) == node) { 688 types.set(i, (TypeDeclaration) replacementNode); 689 return true; 690 } 691 } 692 return super.replace(node, replacementNode); 693 } 694 } 695