JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/ast/CompilationUnit.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 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 static com.github.javaparser.JavaToken.Kind.EOF;
24import static com.github.javaparser.Providers.UTF8;
25import static com.github.javaparser.Providers.provider;
26import static com.github.javaparser.Range.range;
27import static com.github.javaparser.StaticJavaParser.parseImport;
28import static com.github.javaparser.StaticJavaParser.parseName;
29import static com.github.javaparser.ast.Modifier.createModifierList;
30import static com.github.javaparser.utils.CodeGenerationUtils.subtractPaths;
31import static com.github.javaparser.utils.Utils.assertNotNull;
32
33import java.io.IOException;
34import java.nio.charset.Charset;
35import java.nio.file.Files;
36import java.nio.file.Path;
37import java.nio.file.Paths;
38import java.util.List;
39import java.util.Objects;
40import java.util.Optional;
41import java.util.function.Function;
42
43import com.github.javaparser.JavaParser;
44import com.github.javaparser.JavaToken;
45import com.github.javaparser.ParseResult;
46import com.github.javaparser.ParseStart;
47import com.github.javaparser.Position;
48import com.github.javaparser.TokenRange;
49import com.github.javaparser.ast.body.AnnotationDeclaration;
50import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
51import com.github.javaparser.ast.body.EnumDeclaration;
52import com.github.javaparser.ast.body.TypeDeclaration;
53import com.github.javaparser.ast.comments.Comment;
54import com.github.javaparser.ast.comments.JavadocComment;
55import com.github.javaparser.ast.expr.Name;
56import com.github.javaparser.ast.modules.ModuleDeclaration;
57import com.github.javaparser.ast.nodeTypes.NodeWithName;
58import com.github.javaparser.ast.observer.ObservableProperty;
59import com.github.javaparser.ast.visitor.CloneVisitor;
60import com.github.javaparser.ast.visitor.GenericVisitor;
61import com.github.javaparser.ast.visitor.VoidVisitor;
62import com.github.javaparser.metamodel.CompilationUnitMetaModel;
63import com.github.javaparser.metamodel.InternalProperty;
64import com.github.javaparser.metamodel.JavaParserMetaModel;
65import com.github.javaparser.metamodel.OptionalProperty;
66import com.github.javaparser.printer.PrettyPrinter;
67import com.github.javaparser.utils.ClassUtils;
68import com.github.javaparser.utils.CodeGenerationUtils;
69import com.github.javaparser.utils.Utils;
70
71/**
72 * <p>
73 * This class represents the entire compilation unit. Each java file denotes a
74 * compilation unit.
75 * </p>
76 * A compilation unit start with an optional package declaration,
77 * followed by zero or more import declarations,
78 * followed by zero or more type declarations.
79 *
80 * @author Julio Vilmar Gesser
81 * @see PackageDeclaration
82 * @see ImportDeclaration
83 * @see TypeDeclaration
84 * @see Storage
85 */
86public class CompilationUnit extends Node {
87
88    private static final String JAVA_LANG = "java.lang";
89
90    @OptionalProperty
91    private PackageDeclaration packageDeclaration;
92
93    private NodeList<ImportDeclarationimports;
94
95    private NodeList<TypeDeclaration<?>> types;
96
97    @OptionalProperty
98    private ModuleDeclaration module;
99
100    @InternalProperty
101    private Storage storage;
102
103    public CompilationUnit() {
104        this(nullnull, new NodeList<>(), new NodeList<>(), null);
105    }
106
107    public CompilationUnit(String packageDeclaration) {
108        this(null, new PackageDeclaration(new Name(packageDeclaration)), new NodeList<>(), new NodeList<>(), null);
109    }
110
111    @AllFieldsConstructor
112    public CompilationUnit(PackageDeclaration packageDeclarationNodeList<ImportDeclarationimportsNodeList<TypeDeclaration<?>> typesModuleDeclaration module) {
113        this(nullpackageDeclarationimportstypesmodule);
114    }
115
116    /**
117     * This constructor is used by the parser and is considered private.
118     */
119    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
120    public CompilationUnit(TokenRange tokenRangePackageDeclaration packageDeclarationNodeList<ImportDeclarationimportsNodeList<TypeDeclaration<?>> typesModuleDeclaration module) {
121        super(tokenRange);
122        setPackageDeclaration(packageDeclaration);
123        setImports(imports);
124        setTypes(types);
125        setModule(module);
126        customInitialization();
127    }
128
129    @Override
130    @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
131    public <RAR accept(final GenericVisitor<RAvfinal A arg) {
132        return v.visit(this, arg);
133    }
134
135    @Override
136    @Generated("com.github.javaparser.generator.core.node.AcceptGenerator")
137    public <Avoid accept(final VoidVisitor<Avfinal A arg) {
138        v.visit(this, arg);
139    }
140
141    /**
142     * @deprecated getComments was a too generic name and it could be confused with getComment
143     * or getAllContainedComments
144     * Use {@link #getAllComments()} instead
145     */
146    @Deprecated
147    public List<CommentgetComments() {
148        List<Commentcomments = this.getAllContainedComments();
149        this.getComment().ifPresent(comments::add);
150        return comments;
151    }
152
153    /**
154     * Return a list containing all comments declared in this compilation unit.
155     * Including javadocs, line comments and block comments of all types,
156     * inner-classes and other members.<br>
157     * If there is no comment, an empty list is returned.
158     *
159     * @return list with all comments of this compilation unit.
160     * @see JavadocComment
161     * @see com.github.javaparser.ast.comments.LineComment
162     * @see com.github.javaparser.ast.comments.BlockComment
163     */
164    public List<CommentgetAllComments() {
165        List<Commentcomments = this.getAllContainedComments();
166        this.getComment().ifPresent(comments::add);
167        return comments;
168    }
169
170    /**
171     * Retrieves the list of imports declared in this compilation unit or
172     * {@code null} if there is no import.
173     *
174     * @return the list of imports or {@code none} if there is no import
175     */
176    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
177    public NodeList<ImportDeclarationgetImports() {
178        return imports;
179    }
180
181    public ImportDeclaration getImport(int i) {
182        return getImports().get(i);
183    }
184
185    /**
186     * Retrieves the package declaration of this compilation unit.<br>
187     * If this compilation unit has no package declaration (default package),
188     * {@code Optional.none()} is returned.
189     *
190     * @return the package declaration or {@code none}
191     */
192    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
193    public Optional<PackageDeclarationgetPackageDeclaration() {
194        return Optional.ofNullable(packageDeclaration);
195    }
196
197    /**
198     * Return the list of top level types declared in this compilation unit.<br>
199     * If there are no types declared, {@code none} is returned.
200     *
201     * @return the list of types or {@code none} null if there is no type
202     * @see AnnotationDeclaration
203     * @see ClassOrInterfaceDeclaration
204     * @see EnumDeclaration
205     */
206    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
207    public NodeList<TypeDeclaration<?>> getTypes() {
208        return types;
209    }
210
211    /**
212     * Convenience method that wraps {@code getTypes()}.<br>
213     * If {@code i} is out of bounds, throws <code>IndexOutOfBoundsException.</code>
214     *
215     * @param i the index of the type declaration to retrieve
216     */
217    public TypeDeclaration<?> getType(int i) {
218        return getTypes().get(i);
219    }
220
221    /**
222     * Sets the list of imports of this compilation unit. The list is initially
223     * {@code null}.
224     *
225     * @param imports the list of imports
226     */
227    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
228    public CompilationUnit setImports(final NodeList<ImportDeclarationimports) {
229        assertNotNull(imports);
230        if (imports == this.imports) {
231            return (CompilationUnit) this;
232        }
233        notifyPropertyChange(ObservableProperty.IMPORTS, this.importsimports);
234        if (this.imports != null)
235            this.imports.setParentNode(null);
236        this.imports = imports;
237        setAsParentNodeOf(imports);
238        return this;
239    }
240
241    public CompilationUnit setImport(int iImportDeclaration imports) {
242        getImports().set(iimports);
243        return this;
244    }
245
246    /**
247     * adds an import if not implicitly imported by java (i.e. java.lang) or
248     * added before. Asterisk imports overrule the other imports within the same package.
249     *
250     * @param importDeclaration
251     * @return {@code this}
252     */
253    public CompilationUnit addImport(ImportDeclaration importDeclaration) {
254        if (importDeclaration.isAsterisk()) {
255            getImports().removeIf(im -> Objects.equals(getImportPackageName(im).get(), getImportPackageName(importDeclaration).orElse(null)));
256        }
257        if (!isImplicitImport(importDeclaration) && getImports().stream().noneMatch(im -> im.equals(importDeclaration) || (im.isAsterisk() && Objects.equals(getImportPackageName(im).get(), getImportPackageName(importDeclaration).orElse(null))))) {
258            getImports().add(importDeclaration);
259        }
260        return this;
261    }
262
263    /**
264     * @param importDeclaration
265     * @return {@code true}, if the import is implicit
266     */
267    private boolean isImplicitImport(ImportDeclaration importDeclaration) {
268        Optional<NameimportPackageName = getImportPackageName(importDeclaration);
269        if (importPackageName.isPresent()) {
270            if (parseName(JAVA_LANG).equals(importPackageName.get())) {
271                // java.lang is implicitly imported
272                return true;
273            }
274            if (packageDeclaration != null) {
275                // the import is within the same package
276                Name currentPackageName = packageDeclaration.getName();
277                return currentPackageName.equals(importPackageName.get());
278            }
279            return false;
280        } else {
281            // imports of unnamed package are not allowed
282            return true;
283        }
284    }
285
286    private static Optional<NamegetImportPackageName(ImportDeclaration importDeclaration) {
287        return (importDeclaration.isAsterisk() ? new Name(importDeclaration.getName(), "*") : importDeclaration.getName()).getQualifier();
288    }
289
290    /**
291     * Sets or clear the package declarations of this compilation unit.
292     *
293     * @param packageDeclaration the packageDeclaration declaration to set or {@code null} to default package
294     */
295    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
296    public CompilationUnit setPackageDeclaration(final PackageDeclaration packageDeclaration) {
297        if (packageDeclaration == this.packageDeclaration) {
298            return (CompilationUnit) this;
299        }
300        notifyPropertyChange(ObservableProperty.PACKAGE_DECLARATION, this.packageDeclarationpackageDeclaration);
301        if (this.packageDeclaration != null)
302            this.packageDeclaration.setParentNode(null);
303        this.packageDeclaration = packageDeclaration;
304        setAsParentNodeOf(packageDeclaration);
305        return this;
306    }
307
308    /**
309     * Sets the list of types declared in this compilation unit.
310     */
311    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
312    public CompilationUnit setTypes(final NodeList<TypeDeclaration<?>> types) {
313        assertNotNull(types);
314        if (types == this.types) {
315            return (CompilationUnit) this;
316        }
317        notifyPropertyChange(ObservableProperty.TYPES, this.typestypes);
318        if (this.types != null)
319            this.types.setParentNode(null);
320        this.types = types;
321        setAsParentNodeOf(types);
322        return this;
323    }
324
325    public CompilationUnit setType(int iTypeDeclaration<?> type) {
326        NodeList<TypeDeclaration<?>> copy = new NodeList<>();
327        copy.addAll(getTypes());
328        getTypes().set(itype);
329        notifyPropertyChange(ObservableProperty.TYPEScopytypes);
330        return this;
331    }
332
333    public CompilationUnit addType(TypeDeclaration<?> type) {
334        NodeList<TypeDeclaration<?>> copy = new NodeList<>();
335        copy.addAll(getTypes());
336        getTypes().add(type);
337        notifyPropertyChange(ObservableProperty.TYPEScopytypes);
338        return this;
339    }
340
341    /**
342     * sets the package declaration of this compilation unit
343     *
344     * @param name the name of the package
345     * @return this, the {@link CompilationUnit}
346     */
347    public CompilationUnit setPackageDeclaration(String name) {
348        setPackageDeclaration(new PackageDeclaration(parseName(name)));
349        return this;
350    }
351
352    /**
353     * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br>
354     * shorthand for {@link #addImport(String, boolean, boolean)} with name,false,false
355     *
356     * @param name the import name
357     * @return this, the {@link CompilationUnit}
358     */
359    public CompilationUnit addImport(String name) {
360        return addImport(namefalsefalse);
361    }
362
363    /**
364     * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br>
365     * shorthand for {@link #addImport(String)} with clazz.getName()
366     *
367     * @param clazz the class to import
368     * @return this, the {@link CompilationUnit}
369     * @throws IllegalArgumentException if clazz is an anonymous or local class
370     */
371    public CompilationUnit addImport(Class<?> clazz) {
372        if (clazz.isArray()) {
373            return addImport(clazz.getComponentType());
374        }
375        if (ClassUtils.isPrimitiveOrWrapper(clazz) || JAVA_LANG.equals(clazz.getPackage().getName()))
376            return this;
377        else if (clazz.isAnonymousClass() || clazz.isLocalClass())
378            throw new IllegalArgumentException(clazz.getName() + " is an anonymous or local class therefore it can't be added with addImport");
379        return addImport(clazz.getCanonicalName());
380    }
381
382    /**
383     * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br>
384     * <b>This method check if no import with the same name is already in the list</b>
385     *
386     * @param name the import name
387     * @param isStatic is it an "import static"
388     * @param isAsterisk does the import end with ".*"
389     * @return this, the {@link CompilationUnit}
390     */
391    public CompilationUnit addImport(String nameboolean isStaticboolean isAsterisk) {
392        if (name == null) {
393            return this;
394        }
395        final StringBuilder i = new StringBuilder("import ");
396        if (isStatic) {
397            i.append("static ");
398        }
399        i.append(name);
400        if (isAsterisk) {
401            i.append(".*");
402        }
403        i.append(";");
404        return addImport(parseImport(i.toString()));
405    }
406
407    /**
408     * Add a public class to the types of this compilation unit
409     *
410     * @param name the class name
411     * @return the newly created class
412     */
413    public ClassOrInterfaceDeclaration addClass(String name) {
414        return addClass(nameModifier.Keyword.PUBLIC);
415    }
416
417    /**
418     * Add a class to the types of this compilation unit
419     *
420     * @param name the class name
421     * @param modifiers the modifiers (like Modifier.PUBLIC)
422     * @return the newly created class
423     */
424    public ClassOrInterfaceDeclaration addClass(String nameModifier.Keyword... modifiers) {
425        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(createModifierList(modifiers), falsename);
426        getTypes().add(classOrInterfaceDeclaration);
427        return classOrInterfaceDeclaration;
428    }
429
430    /**
431     * Add a public interface class to the types of this compilation unit
432     *
433     * @param name the interface name
434     * @return the newly created class
435     */
436    public ClassOrInterfaceDeclaration addInterface(String name) {
437        return addInterface(nameModifier.Keyword.PUBLIC);
438    }
439
440    /**
441     * Add an interface to the types of this compilation unit
442     *
443     * @param name the interface name
444     * @param modifiers the modifiers (like Modifier.PUBLIC)
445     * @return the newly created class
446     */
447    public ClassOrInterfaceDeclaration addInterface(String nameModifier.Keyword... modifiers) {
448        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(createModifierList(modifiers), truename);
449        getTypes().add(classOrInterfaceDeclaration);
450        return classOrInterfaceDeclaration;
451    }
452
453    /**
454     * Add a public enum to the types of this compilation unit
455     *
456     * @param name the enum name
457     * @return the newly created class
458     */
459    public EnumDeclaration addEnum(String name) {
460        return addEnum(nameModifier.Keyword.PUBLIC);
461    }
462
463    /**
464     * Add an enum to the types of this compilation unit
465     *
466     * @param name the enum name
467     * @param modifiers the modifiers (like Modifier.PUBLIC)
468     * @return the newly created class
469     */
470    public EnumDeclaration addEnum(String nameModifier.Keyword... modifiers) {
471        EnumDeclaration enumDeclaration = new EnumDeclaration(createModifierList(modifiers), name);
472        getTypes().add(enumDeclaration);
473        return enumDeclaration;
474    }
475
476    /**
477     * Add a public annotation declaration to the types of this compilation unit
478     *
479     * @param name the annotation name
480     * @return the newly created class
481     */
482    public AnnotationDeclaration addAnnotationDeclaration(String name) {
483        return addAnnotationDeclaration(nameModifier.Keyword.PUBLIC);
484    }
485
486    /**
487     * Add an annotation declaration to the types of this compilation unit
488     *
489     * @param name the annotation name
490     * @param modifiers the modifiers (like Modifier.PUBLIC)
491     * @return the newly created class
492     */
493    public AnnotationDeclaration addAnnotationDeclaration(String nameModifier.Keyword... modifiers) {
494        AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(createModifierList(modifiers), name);
495        getTypes().add(annotationDeclaration);
496        return annotationDeclaration;
497    }
498
499    /**
500     * Try to get a top level class declaration by its name
501     *
502     * @param className the class name (case-sensitive)
503     */
504    public Optional<ClassOrInterfaceDeclarationgetClassByName(String className) {
505        return getTypes().stream().filter(type -> type.getNameAsString().equals(className) && type instanceof ClassOrInterfaceDeclaration && !((ClassOrInterfaceDeclarationtype).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclarationt);
506    }
507    
508    /**
509     * Try to get a locally class declaration by its name (top level or inner class)
510     *
511     * @param className the class name (case-sensitive)
512     */
513    public Optional<ClassOrInterfaceDeclarationgetLocaleDeclarationFromClassname(String className) {
514        return findAll(ClassOrInterfaceDeclaration.class).stream().filter(cid->cid.getNameAsString().equals(className)).findFirst();
515    }
516
517    /**
518     * Try to get a top level interface declaration by its name
519     *
520     * @param interfaceName the interface name (case-sensitive)
521     */
522    public Optional<ClassOrInterfaceDeclarationgetInterfaceByName(String interfaceName) {
523        return getTypes().stream().filter(type -> type.getNameAsString().equals(interfaceName) && type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclarationtype).isInterface()).findFirst().map(t -> (ClassOrInterfaceDeclarationt);
524    }
525
526    /**
527     * Try to get a top level enum declaration by its name
528     *
529     * @param enumName the enum name (case-sensitive)
530     */
531    public Optional<EnumDeclarationgetEnumByName(String enumName) {
532        return getTypes().stream().filter(type -> type.getNameAsString().equals(enumName) && type instanceof EnumDeclaration).findFirst().map(t -> (EnumDeclarationt);
533    }
534
535    /**
536     * @return the name that the primary type in this file should have, according to the filename in {@link Storage#getFileName()}.
537     * Empty if no file information is present (when this compilation unit wasn't parsed from a file.)
538     */
539    public Optional<StringgetPrimaryTypeName() {
540        return getStorage().map(Storage::getFileName).map(Utils::removeFileExtension);
541    }
542
543    /**
544     * @return the type whose name corresponds to the file name.
545     * Empty if no file information is present (when this compilation unit wasn't parsed from a file.)
546     * If for some strange reason there are multiple types of this name, the first one is returned.
547     */
548    public Optional<TypeDeclaration<?>> getPrimaryType() {
549        return getPrimaryTypeName().flatMap(name -> getTypes().stream().filter(t -> t.getNameAsString().equals(name)).findFirst());
550    }
551
552    /**
553     * Try to get a top level annotation type declaration by its name
554     *
555     * @param annotationName the annotation name (case-sensitive)
556     */
557    public Optional<AnnotationDeclarationgetAnnotationDeclarationByName(String annotationName) {
558        return getTypes().stream().filter(type -> type.getNameAsString().equals(annotationName) && type instanceof AnnotationDeclaration).findFirst().map(t -> (AnnotationDeclarationt);
559    }
560
561    @Override
562    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
563    public boolean remove(Node node) {
564        if (node == null)
565            return false;
566        for (int i = 0i < imports.size(); i++) {
567            if (imports.get(i) == node) {
568                imports.remove(i);
569                return true;
570            }
571        }
572        if (module != null) {
573            if (node == module) {
574                removeModule();
575                return true;
576            }
577        }
578        if (packageDeclaration != null) {
579            if (node == packageDeclaration) {
580                removePackageDeclaration();
581                return true;
582            }
583        }
584        for (int i = 0i < types.size(); i++) {
585            if (types.get(i) == node) {
586                types.remove(i);
587                return true;
588            }
589        }
590        return super.remove(node);
591    }
592
593    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
594    public CompilationUnit removePackageDeclaration() {
595        return setPackageDeclaration((PackageDeclarationnull);
596    }
597
598    /**
599     * @return the module declared in this compilation unit.
600     */
601    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
602    public Optional<ModuleDeclarationgetModule() {
603        return Optional.ofNullable(module);
604    }
605
606    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
607    public CompilationUnit setModule(final ModuleDeclaration module) {
608        if (module == this.module) {
609            return (CompilationUnit) this;
610        }
611        notifyPropertyChange(ObservableProperty.MODULE, this.modulemodule);
612        if (this.module != null)
613            this.module.setParentNode(null);
614        this.module = module;
615        setAsParentNodeOf(module);
616        return this;
617    }
618
619    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
620    public CompilationUnit removeModule() {
621        return setModule((ModuleDeclarationnull);
622    }
623
624    /**
625     * @return information about where this compilation unit was loaded from, or empty if it wasn't loaded from a file.
626     */
627    public Optional<StoragegetStorage() {
628        return Optional.ofNullable(storage);
629    }
630
631    public CompilationUnit setStorage(Path path) {
632        this.storage = new Storage(this, path);
633        return this;
634    }
635
636    public CompilationUnit setStorage(Path pathCharset charset) {
637        this.storage = new Storage(this, pathcharset);
638        return this;
639    }
640
641    /**
642     * Create (or overwrite) a module declaration in this compilation unit with name "name".
643     *
644     * @return the module
645     */
646    public ModuleDeclaration setModule(String name) {
647        final ModuleDeclaration module = new ModuleDeclaration(parseName(name), false);
648        setModule(module);
649        return module;
650    }
651
652    /**
653     * Recalculates the ranges of all nodes by looking at the sizes of the tokens.
654     * This is useful when you have manually inserted or deleted tokens and still want to use the ranges.
655     */
656    public void recalculatePositions() {
657        if (!getTokenRange().isPresent()) {
658            throw new IllegalStateException("Can't recalculate positions without tokens.");
659        }
660        Position cursor = Position.HOME;
661        for (JavaToken t : getTokenRange().get()) {
662            int tokenLength = t.getKind() == EOF.getKind() ? 0 : t.getText().length() - 1;
663            t.setRange(range(cursorcursor.right(tokenLength)));
664            if (t.getCategory().isEndOfLine()) {
665                cursor = cursor.nextLine();
666            } else {
667                cursor = cursor.right(tokenLength + 1);
668            }
669        }
670    }
671
672    /**
673     * Information about where this compilation unit was loaded from.
674     * This class only stores the absolute location.
675     * For more flexibility use SourceRoot.
676     */
677    public static class Storage {
678
679        private final CompilationUnit compilationUnit;
680
681        private final Path path;
682
683        private final Charset encoding;
684
685        private Storage(CompilationUnit compilationUnitPath path) {
686            this.compilationUnit = compilationUnit;
687            this.path = path.toAbsolutePath();
688            this.encoding = UTF8;
689        }
690
691        private Storage(CompilationUnit compilationUnitPath pathCharset encoding) {
692            this.compilationUnit = compilationUnit;
693            this.path = path.toAbsolutePath();
694            this.encoding = encoding;
695        }
696
697        /**
698         * @return the path to the source for this CompilationUnit
699         */
700        public Path getPath() {
701            return path;
702        }
703
704        /**
705         * @return the CompilationUnit this Storage is about.
706         */
707        public CompilationUnit getCompilationUnit() {
708            return compilationUnit;
709        }
710
711        /**
712         * @return the encoding used to read the file.
713         */
714        public Charset getEncoding() {
715            return encoding;
716        }
717
718        /**
719         * @return the source root directory, calculated from the path of this compiation unit, and the package
720         * declaration of this compilation unit. If the package declaration is invalid (when it does not match the end
721         * of the path) a RuntimeException is thrown.
722         */
723        public Path getSourceRoot() {
724            final Optional<StringpkgAsString = compilationUnit.getPackageDeclaration().map(NodeWithName::getNameAsString);
725            return pkgAsString.map(p -> Paths.get(CodeGenerationUtils.packageToPath(p))).map(pkg -> subtractPaths(getDirectory(), pkg)).orElse(getDirectory());
726        }
727
728        public String getFileName() {
729            return path.getFileName().toString();
730        }
731
732        public Path getDirectory() {
733            return path.getParent();
734        }
735
736        /**
737         * Saves the compilation unit to its original location
738         */
739        public void save() {
740            save(cu -> new PrettyPrinter().print(cu));
741        }
742
743        /**
744         * Saves a compilation unit to its original location with formatting according to the function passed as a
745         * parameter.
746         *
747         * @param makeOutput a function that formats the compilation unit
748         */
749        public void save(Function<CompilationUnitStringmakeOutput) {
750            save(makeOutputencoding);
751        }
752
753        /**
754         * Saves a compilation unit to its original location with formatting and encoding according to the function and
755         * encoding passed as a parameter.
756         *
757         * @param makeOutput a function that formats the compilation unit
758         * @param encoding the encoding to use for the saved file
759         */
760        public void save(Function<CompilationUnitStringmakeOutputCharset encoding) {
761            try {
762                Files.createDirectories(path.getParent());
763                final String code = makeOutput.apply(getCompilationUnit());
764                Files.write(pathcode.getBytes(encoding));
765            } catch (IOException e) {
766                throw new RuntimeException(e);
767            }
768        }
769
770        public ParseResult<CompilationUnitreparse(JavaParser javaParser) {
771            try {
772                return javaParser.parse(ParseStart.COMPILATION_UNITprovider(getPath()));
773            } catch (IOException e) {
774                throw new RuntimeException(e);
775            }
776        }
777    }
778
779    @Override
780    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
781    public CompilationUnit clone() {
782        return (CompilationUnitaccept(new CloneVisitor(), null);
783    }
784
785    @Override
786    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
787    public CompilationUnitMetaModel getMetaModel() {
788        return JavaParserMetaModel.compilationUnitMetaModel;
789    }
790
791    @Override
792    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
793    public boolean replace(Node nodeNode replacementNode) {
794        if (node == null)
795            return false;
796        for (int i = 0i < imports.size(); i++) {
797            if (imports.get(i) == node) {
798                imports.set(i, (ImportDeclarationreplacementNode);
799                return true;
800            }
801        }
802        if (module != null) {
803            if (node == module) {
804                setModule((ModuleDeclarationreplacementNode);
805                return true;
806            }
807        }
808        if (packageDeclaration != null) {
809            if (node == packageDeclaration) {
810                setPackageDeclaration((PackageDeclarationreplacementNode);
811                return true;
812            }
813        }
814        for (int i = 0i < types.size(); i++) {
815            if (types.get(i) == node) {
816                types.set(i, (TypeDeclarationreplacementNode);
817                return true;
818            }
819        }
820        return super.replace(nodereplacementNode);
821    }
822}
823
MembersX
CompilationUnit:addType
CompilationUnit:Storage:encoding
CompilationUnit:getImports
CompilationUnit:remove
CompilationUnit:isImplicitImport
CompilationUnit:setModule:Block:module
CompilationUnit:replace
CompilationUnit:isImplicitImport:Block:importPackageName
CompilationUnit:setType
CompilationUnit:getComments:Block:comments
CompilationUnit:setPackageDeclaration
CompilationUnit:addClass
CompilationUnit:getInterfaceByName
CompilationUnit:Storage:getDirectory
CompilationUnit:setModule
CompilationUnit:Storage:Storage
CompilationUnit:JAVA_LANG
CompilationUnit:Storage:path
CompilationUnit:getPrimaryType
CompilationUnit:getImport
CompilationUnit:accept
CompilationUnit:removeModule
CompilationUnit:Storage:getEncoding
CompilationUnit:removePackageDeclaration
CompilationUnit:Storage:getPath
CompilationUnit:Storage:reparse
CompilationUnit:addAnnotationDeclaration:Block:annotationDeclaration
CompilationUnit:getAllComments:Block:comments
CompilationUnit:addClass:Block:classOrInterfaceDeclaration
CompilationUnit:getStorage
CompilationUnit:recalculatePositions:Block:Block:tokenLength
CompilationUnit:packageDeclaration
CompilationUnit:setType:Block:copy
CompilationUnit:Storage:getSourceRoot
CompilationUnit:getPackageDeclaration
CompilationUnit:Storage:getFileName
CompilationUnit:setImports
CompilationUnit:types
CompilationUnit:addInterface:Block:classOrInterfaceDeclaration
CompilationUnit:getPrimaryTypeName
CompilationUnit:getModule
CompilationUnit:setImport
CompilationUnit:addInterface
CompilationUnit:Storage:save:Block:Block:code
CompilationUnit:addImport
CompilationUnit:addEnum
CompilationUnit:getClassByName
CompilationUnit:setStorage
CompilationUnit:getComments
CompilationUnit:Storage:compilationUnit
CompilationUnit:CompilationUnit
CompilationUnit:recalculatePositions
CompilationUnit:getAllComments
CompilationUnit:addType:Block:copy
CompilationUnit:addImport:Block:i
CompilationUnit:getMetaModel
CompilationUnit:getEnumByName
CompilationUnit:recalculatePositions:Block:cursor
CompilationUnit:module
CompilationUnit:getLocaleDeclarationFromClassname
CompilationUnit:storage
CompilationUnit:clone
CompilationUnit:setTypes
CompilationUnit:addEnum:Block:enumDeclaration
CompilationUnit:getAnnotationDeclarationByName
CompilationUnit:getTypes
CompilationUnit:isImplicitImport:Block:Block:Block:currentPackageName
CompilationUnit:addAnnotationDeclaration
CompilationUnit:getType
CompilationUnit:Storage:getSourceRoot:Block:pkgAsString
CompilationUnit:Storage:save
CompilationUnit:imports
CompilationUnit:getImportPackageName
CompilationUnit:Storage:getCompilationUnit
Members
X