JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/utils/SourceRoot.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 */
21
22package com.github.javaparser.utils;
23
24import com.github.javaparser.JavaParser;
25import com.github.javaparser.ParseProblemException;
26import com.github.javaparser.ParseResult;
27import com.github.javaparser.ParserConfiguration;
28import com.github.javaparser.ast.CompilationUnit;
29import com.github.javaparser.printer.PrettyPrinter;
30
31import java.io.IOException;
32import java.nio.charset.Charset;
33import java.nio.file.FileVisitResult;
34import java.nio.file.Files;
35import java.nio.file.Path;
36import java.nio.file.SimpleFileVisitor;
37import java.nio.file.attribute.BasicFileAttributes;
38import java.util.ArrayList;
39import java.util.List;
40import java.util.Map;
41import java.util.concurrent.ConcurrentHashMap;
42import java.util.concurrent.ForkJoinPool;
43import java.util.concurrent.RecursiveAction;
44import java.util.function.Function;
45import java.util.regex.Pattern;
46import java.util.stream.Collectors;
47
48import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
49import static com.github.javaparser.Providers.provider;
50import static com.github.javaparser.utils.CodeGenerationUtils.*;
51import static com.github.javaparser.utils.Utils.assertNotNull;
52import static java.nio.file.FileVisitResult.*;
53
54/**
55 * A collection of Java source files located in one directory and its subdirectories on the file system. The root directory
56 * corresponds to the root of the package structure of the source files within. Files can be parsed and written back one
57 * by one or all together. <b>Note that</b> the internal cache used is thread-safe.
58 * <ul>
59 * <li>methods called "tryToParse..." will return their result inside a "ParseResult", which supports parse successes and failures.</li>
60 * <li>methods called "parse..." will return "CompilationUnit"s. If a file fails to parse, an exception is thrown.</li>
61 * <li>methods ending in "...Parallelized" will speed up parsing by using multiple threads.</li>
62 * </ul>
63 */
64public class SourceRoot {
65    @FunctionalInterface
66    public interface Callback {
67        enum Result {
68            SAVE, DONT_SAVE, TERMINATE
69        }
70
71        /**
72         * @param localPath the path to the file that was parsed, relative to the source root path.
73         * @param absolutePath the absolute path to the file that was parsed.
74         * @param result the result of of parsing the file.
75         */
76        Result process(Path localPathPath absolutePathParseResult<CompilationUnitresult);
77    }
78
79    private final Path root;
80    private final Map<PathParseResult<CompilationUnit>> cache = new ConcurrentHashMap<>();
81    private ParserConfiguration parserConfiguration = new ParserConfiguration();
82    private Function<CompilationUnitStringprinter = new PrettyPrinter()::print;
83    private static final Pattern JAVA_IDENTIFIER = Pattern.compile("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*");
84
85    /**
86     * @param root the root directory of a set of source files. It corresponds to the root of the package structure of the
87     * source files within, like "javaparser/javaparser-core/src/main/java"
88     */
89    public SourceRoot(Path root) {
90        assertNotNull(root);
91        if (!Files.isDirectory(root)) {
92            throw new IllegalArgumentException("Only directories are allowed as root path: " + root);
93        }
94        this.root = root.normalize();
95        Log.info("New source root at \"%s\"", () -> this.root);
96    }
97
98    /**
99     * @param root the root directory of a set of source files. It corresponds to the root of the package structure of the
100     * source files within, like "javaparser/javaparser-core/src/main/java"
101     */
102    public SourceRoot(Path rootParserConfiguration parserConfiguration) {
103        this(root);
104        setParserConfiguration(parserConfiguration);
105    }
106
107    /**
108     * Tries to parse a .java files under the source root and returns the ParseResult. It keeps track of the parsed file
109     * so you can write it out with the saveAll() call. Note that the cache grows with every file parsed, so if you
110     * don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is useful) you
111     * might want to use the parse method with a callback.
112     *
113     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
114     */
115    public ParseResult<CompilationUnittryToParse(String startPackageString filenameParserConfiguration configuration) throws IOException {
116        assertNotNull(startPackage);
117        assertNotNull(filename);
118        final Path relativePath = fileInPackageRelativePath(startPackagefilename);
119        if (cache.containsKey(relativePath)) {
120            Log.trace("Retrieving cached %s", () -> relativePath);
121            return cache.get(relativePath);
122        }
123        final Path path = root.resolve(relativePath);
124        Log.trace("Parsing %s", () -> path);
125        final ParseResult<CompilationUnitresult = new JavaParser(configuration)
126                .parse(COMPILATION_UNITprovider(pathconfiguration.getCharacterEncoding()));
127        result.getResult().ifPresent(cu -> cu.setStorage(pathconfiguration.getCharacterEncoding()));
128        cache.put(relativePathresult);
129        return result;
130    }
131
132    /**
133     * Tries to parse a .java files under the source root and returns the ParseResult. It keeps track of the parsed file
134     * so you can write it out with the saveAll() call. Note that the cache grows with every file parsed, so if you
135     * don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is useful) you
136     * might want to use the parse method with a callback.
137     *
138     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
139     */
140    public ParseResult<CompilationUnittryToParse(String startPackageString filename) throws IOException {
141        return tryToParse(startPackagefilenameparserConfiguration);
142    }
143
144    /**
145     * Tries to parse all .java files in a package recursively, and returns all files ever parsed with this source root.
146     * It keeps track of all parsed files so you can write them out with a single saveAll() call. Note that the cache
147     * grows with every file parsed, so if you don't need saveAll(), or you don't ask SourceRoot to parse files multiple
148     * times (where the cache is useful) you might want to use the parse method with a callback.
149     *
150     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
151     */
152    public List<ParseResult<CompilationUnit>> tryToParse(String startPackage) throws IOException {
153        assertNotNull(startPackage);
154        logPackage(startPackage);
155        final Path path = packageAbsolutePath(rootstartPackage);
156        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
157            @Override
158            public FileVisitResult visitFile(Path fileBasicFileAttributes attrs) throws IOException {
159                if (!attrs.isDirectory() && file.toString().endsWith(".java")) {
160                    Path relative = root.relativize(file.getParent());
161                    tryToParse(relative.toString(), file.getFileName().toString());
162                }
163                return CONTINUE;
164            }
165
166            @Override
167            public FileVisitResult preVisitDirectory(Path dirBasicFileAttributes attrs) throws IOException {
168                return isSensibleDirectoryToEnter(dir) ? CONTINUE : SKIP_SUBTREE;
169            }
170        });
171        return getCache();
172    }
173
174    private static boolean isSensibleDirectoryToEnter(Path dir) throws IOException {
175        final String dirToEnter = dir.getFileName().toString();
176        // Don't enter directories that cannot be packages.
177        final boolean directoryIsAValidJavaIdentifier = JAVA_IDENTIFIER.matcher(dirToEnter).matches();
178        // Don't enter directories that are hidden, assuming that people don't store source files in hidden directories.
179        if (Files.isHidden(dir) || !directoryIsAValidJavaIdentifier) {
180            Log.trace("Not processing directory \"%s\"", () -> dirToEnter);
181            return false;
182        }
183        return true;
184    }
185
186    /**
187     * Tries to parse all .java files under the source root recursively, and returns all files ever parsed with this
188     * source root. It keeps track of all parsed files so you can write them out with a single saveAll() call. Note that
189     * the cache grows with every file parsed, so if you don't need saveAll(), or you don't ask SourceRoot to parse
190     * files multiple times (where the cache is useful) you might want to use the parse method with a callback.
191     */
192    public List<ParseResult<CompilationUnit>> tryToParse() throws IOException {
193        return tryToParse("");
194    }
195
196    /**
197     * Tries to parse all .java files in a package recursively using multiple threads, and returns all files ever parsed
198     * with this source root. A new thread is forked each time a new directory is visited and is responsible for parsing
199     * all .java files in that directory. <b>Note that</b> to ensure thread safety, a new parser instance is created for
200     * every file with the internal parser's (i.e. {@link #setParserConfiguration(ParserConfiguration)}) configuration.
201     * It keeps track of all parsed files so you can write them out with a single saveAll() call.
202     * Note that the cache grows with every file parsed,
203     * so if you don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is
204     * useful) you might want to use the parse method with a callback.
205     *
206     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
207     */
208    public List<ParseResult<CompilationUnit>> tryToParseParallelized(String startPackage) {
209        assertNotNull(startPackage);
210        logPackage(startPackage);
211        final Path path = packageAbsolutePath(rootstartPackage);
212        ParallelParse parse = new ParallelParse(path, (fileattrs) -> {
213            if (!attrs.isDirectory() && file.toString().endsWith(".java")) {
214                Path relative = root.relativize(file.getParent());
215                try {
216                    tryToParse(
217                            relative.toString(),
218                            file.getFileName().toString(),
219                            parserConfiguration);
220                } catch (IOException e) {
221                    Log.error(e);
222                }
223            }
224            return CONTINUE;
225        });
226        ForkJoinPool pool = new ForkJoinPool();
227        pool.invoke(parse);
228        return getCache();
229    }
230
231    /**
232     * Tries to parse all .java files under the source root recursively using multiple threads, and returns all files
233     * ever parsed with this source root. A new thread is forked each time a new directory is visited and is responsible
234     * for parsing all .java files in that directory. <b>Note that</b> to ensure thread safety, a new parser instance is
235     * created for every file with the internal (i.e. {@link #setParserConfiguration(ParserConfiguration)}) configuration. It keeps track of
236     * all parsed files so you can write them out with a single saveAll() call. Note that the cache grows with every
237     * file parsed, so if you don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the
238     * cache is useful) you might want to use the parse method with a callback.
239     */
240    public List<ParseResult<CompilationUnit>> tryToParseParallelized() {
241        return tryToParseParallelized("");
242    }
243
244    /**
245     * Parses a .java files under the source root and returns its CompilationUnit. It keeps track of the parsed file so
246     * you can write it out with the saveAll() call. Note that the cache grows with every file parsed, so if you don't
247     * need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is useful) you might
248     * want to use the parse method with a callback.
249     *
250     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
251     * @throws ParseProblemException when something went wrong.
252     */
253    public CompilationUnit parse(String startPackageString filename) {
254        assertNotNull(startPackage);
255        assertNotNull(filename);
256        try {
257            final ParseResult<CompilationUnitresult = tryToParse(startPackagefilename);
258            if (result.isSuccessful()) {
259                return result.getResult().get();
260            }
261            throw new ParseProblemException(result.getProblems());
262        } catch (IOException e) {
263            throw new ParseProblemException(e);
264        }
265    }
266
267    private FileVisitResult callback(Path absolutePathParserConfiguration configurationCallback callback) throws IOException {
268        Path localPath = root.relativize(absolutePath);
269        Log.trace("Parsing %s", () -> localPath);
270        ParseResult<CompilationUnitresult = new JavaParser(configuration).parse(COMPILATION_UNITprovider(absolutePathconfiguration.getCharacterEncoding()));
271        result.getResult().ifPresent(cu -> cu.setStorage(absolutePathconfiguration.getCharacterEncoding()));
272        switch (callback.process(localPathabsolutePathresult)) {
273            case SAVE:
274                result.getResult().ifPresent(cu -> save(cuabsolutePath));
275            case DONT_SAVE:
276                return CONTINUE;
277            case TERMINATE:
278                return TERMINATE;
279            default:
280                throw new AssertionError("Return an enum defined in SourceRoot.Callback.Result");
281        }
282    }
283
284    /**
285     * Locates the .java file with the provided package and file name, parses it and passes it to the
286     * callback. In comparison to the other parse methods, this is much more memory efficient, but saveAll() won't work.
287     *
288     * @param startPackage The package containing the file
289     * @param filename The name of the file
290     */
291    public SourceRoot parse(String startPackageString filenameParserConfiguration configurationCallback
292            callback) throws IOException {
293        assertNotNull(startPackage);
294        assertNotNull(filename);
295        assertNotNull(configuration);
296        assertNotNull(callback);
297        callback(fileInPackageAbsolutePath(rootstartPackagefilename), configurationcallback);
298        return this;
299    }
300
301    /**
302     * Parses the provided .java file and passes it to the callback. In comparison to the other parse methods, this
303     * makes is much more memory efficient., but saveAll() won't work.
304     */
305    public SourceRoot parse(String startPackageString filenameCallback callback) throws IOException {
306        parse(startPackagefilenameparserConfigurationcallback);
307        return this;
308    }
309
310    /**
311     * Tries to parse all .java files in a package recursively and passes them one by one to the callback. In comparison
312     * to the other parse methods, this is much more memory efficient, but saveAll() won't work.
313     *
314     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
315     */
316    public SourceRoot parse(String startPackageParserConfiguration configurationCallback callback) throws IOException {
317        assertNotNull(startPackage);
318        assertNotNull(configuration);
319        assertNotNull(callback);
320        logPackage(startPackage);
321        final Path path = packageAbsolutePath(rootstartPackage);
322        if (Files.exists(path)) {
323            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
324                @Override
325                public FileVisitResult visitFile(Path absolutePathBasicFileAttributes attrs) throws IOException {
326                    if (!attrs.isDirectory() && absolutePath.toString().endsWith(".java")) {
327                        return callback(absolutePathconfigurationcallback);
328                    }
329                    return CONTINUE;
330                }
331
332                @Override
333                public FileVisitResult preVisitDirectory(Path dirBasicFileAttributes attrs) throws IOException {
334                    return isSensibleDirectoryToEnter(dir) ? CONTINUE : SKIP_SUBTREE;
335                }
336            });
337        }
338        return this;
339    }
340
341    public SourceRoot parse(String startPackageCallback callback) throws IOException {
342        parse(startPackageparserConfigurationcallback);
343        return this;
344    }
345
346    private void logPackage(String startPackage) {
347        if (startPackage.isEmpty()) {
348            return;
349        }
350        Log.info("Parsing package \"%s\"", () -> startPackage);
351    }
352
353    /**
354     * Tries to parse all .java files in a package recursively using multiple threads, and passes them one by one to the
355     * callback. A new thread is forked each time a new directory is visited and is responsible for parsing all .java
356     * files in that directory. <b>Note that</b> the provided {@link Callback} code must be made thread-safe. <b>Note
357     * that</b> to ensure thread safety, a new parser instance is created for every file with the provided {@link
358     * ParserConfiguration}. In comparison to the other parse methods, this is much more memory efficient, but saveAll()
359     * won't work.
360     *
361     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
362     */
363    public SourceRoot parseParallelized(String startPackageParserConfiguration configurationCallback callback) {
364        assertNotNull(startPackage);
365        assertNotNull(configuration);
366        assertNotNull(callback);
367        logPackage(startPackage);
368        final Path path = packageAbsolutePath(rootstartPackage);
369        if (Files.exists(path)) {
370            ParallelParse parse = new ParallelParse(path, (absolutePathattrs) -> {
371                if (!attrs.isDirectory() && absolutePath.toString().endsWith(".java")) {
372                    try {
373                        return callback(absolutePathconfigurationcallback);
374                    } catch (IOException e) {
375                        Log.error(e);
376                    }
377                }
378                return CONTINUE;
379            });
380            ForkJoinPool pool = new ForkJoinPool();
381            pool.invoke(parse);
382        }
383        return this;
384    }
385
386    /**
387     * Tries to parse all .java files in a package recursively using multiple threads, and passes them one by one to the
388     * callback. A new thread is forked each time a new directory is visited and is responsible for parsing all .java
389     * files in that directory. <b>Note that</b> the provided {@link Callback} code must be made thread-safe. <b>Note
390     * that</b> to ensure thread safety, a new parser instance is created for every file. In comparison to the other
391     * parse methods, this is much more memory efficient, but saveAll() won't work.
392     *
393     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
394     */
395    public SourceRoot parseParallelized(String startPackageCallback callback) throws IOException {
396        return parseParallelized(startPackage, this.parserConfigurationcallback);
397    }
398
399    /**
400     * Tries to parse all .java files recursively using multiple threads, and passes them one by one to the callback. A
401     * new thread is forked each time a new directory is visited and is responsible for parsing all .java files in that
402     * directory. <b>Note that</b> the provided {@link Callback} code must be made thread-safe. <b>Note that</b> to
403     * ensure thread safety, a new parser instance is created for every file. In comparison to the other parse methods,
404     * this is much more memory efficient, but saveAll() won't work.
405     */
406    public SourceRoot parseParallelized(Callback callback) throws IOException {
407        return parseParallelized("", this.parserConfigurationcallback);
408    }
409
410    /**
411     * Add a newly created Java file to the cache of this source root. It will be saved when saveAll is called.
412     *
413     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
414     */
415    public SourceRoot add(String startPackageString filenameCompilationUnit compilationUnit) {
416        assertNotNull(startPackage);
417        assertNotNull(filename);
418        assertNotNull(compilationUnit);
419        Log.trace("Adding new file %s.%s", () -> startPackage, () -> filename);
420        final Path path = fileInPackageRelativePath(startPackagefilename);
421        final ParseResult<CompilationUnitparseResult = new ParseResult<>(
422                compilationUnit,
423                new ArrayList<>(),
424                null);
425        cache.put(pathparseResult);
426        return this;
427    }
428
429    /**
430     * Add a newly created Java file to the cache of this source root. It will be saved when saveAll is called. It needs
431     * to have its path set.
432     */
433    public SourceRoot add(CompilationUnit compilationUnit) {
434        assertNotNull(compilationUnit);
435        if (compilationUnit.getStorage().isPresent()) {
436            final Path path = compilationUnit.getStorage().get().getPath();
437            Log.trace("Adding new file %s", () -> path);
438            final ParseResult<CompilationUnitparseResult = new ParseResult<>(
439                    compilationUnit,
440                    new ArrayList<>(),
441                    null);
442            cache.put(pathparseResult);
443        } else {
444            throw new AssertionError("Files added with this method should have their path set.");
445        }
446        return this;
447    }
448
449    /**
450     * Save the given compilation unit to the given path.
451     * @param cu the compilation unit
452     * @param path the path of the java file
453     */
454    private SourceRoot save(CompilationUnit cuPath path) {
455        return save(cupathparserConfiguration.getCharacterEncoding());
456    }
457
458    /**
459     * Save the given compilation unit to the given path.
460     * @param cu the compilation unit
461     * @param path the path of the java file
462     * @param encoding  the encoding to use while saving the file
463     */
464    private SourceRoot save(CompilationUnit cuPath pathCharset encoding) {
465        assertNotNull(cu);
466        assertNotNull(path);
467        cu.setStorage(pathencoding);
468        cu.getStorage().get().save(printer);
469        return this;
470    }
471
472    /**
473     * Save all previously parsed files back to a new path.
474     * @param root the root of the java packages
475     * @param encoding the encoding to use while saving the file
476     */
477    public SourceRoot saveAll(Path rootCharset encoding) {
478        assertNotNull(root);
479        Log.info("Saving all files (%s) to %s"cache::size, () -> root);
480        for (Map.Entry<PathParseResult<CompilationUnit>> cu : cache.entrySet()) {
481            final Path path = root.resolve(cu.getKey());
482            if (cu.getValue().getResult().isPresent()) {
483                Log.trace("Saving %s", () -> path);
484                save(cu.getValue().getResult().get(), pathencoding);
485            }
486        }
487        return this;
488    }
489
490    /**
491     * Save all previously parsed files back to a new path.
492     * @param root the root of the java packages
493     */
494    public SourceRoot saveAll(Path root) {
495        return saveAll(rootparserConfiguration.getCharacterEncoding());
496    }
497
498    /**
499     * Save all previously parsed files back to where they were found.
500     */
501    public SourceRoot saveAll() {
502        return saveAll(root);
503    }
504
505    /**
506     * Save all previously parsed files back to where they were found, with the given encoding.
507     * @param encoding the encoding to use.
508     */
509    public SourceRoot saveAll(Charset encoding) {
510        return saveAll(rootencoding);
511    }
512
513    /**
514     * The Java files that have been parsed by this source root object, or have been added manually.
515     */
516    public List<ParseResult<CompilationUnit>> getCache() {
517        return new ArrayList<>(cache.values());
518    }
519
520    /**
521     * The CompilationUnits of the Java files that have been parsed succesfully by this source root object, or have been
522     * added manually.
523     */
524    public List<CompilationUnitgetCompilationUnits() {
525        return cache.values().stream()
526                .filter(ParseResult::isSuccessful)
527                .map(p -> p.getResult().get())
528                .collect(Collectors.toList());
529    }
530
531    /**
532     * The path that was passed in the constructor.
533     */
534    public Path getRoot() {
535        return root;
536    }
537
538    public ParserConfiguration getParserConfiguration() {
539        return parserConfiguration;
540    }
541
542    /**
543     * Set the parser configuration that is used for parsing when no configuration is passed to a method.
544     */
545    public SourceRoot setParserConfiguration(ParserConfiguration parserConfiguration) {
546        assertNotNull(parserConfiguration);
547        this.parserConfiguration = parserConfiguration;
548        return this;
549    }
550
551    /**
552     * Set the printing function that transforms compilation units into a string to save.
553     */
554    public SourceRoot setPrinter(Function<CompilationUnitStringprinter) {
555        assertNotNull(printer);
556        this.printer = printer;
557        return this;
558    }
559
560    /**
561     * Get the printing function.
562     */
563    public Function<CompilationUnitStringgetPrinter() {
564        return printer;
565    }
566
567    /**
568     * Executes a recursive file tree walk using threads. A new thread is invoked for each new directory discovered
569     * during the walk. For each file visited, the user-provided {@link VisitFileCallback} is called with the current
570     * path and file attributes. Any shared resources accessed in a {@link VisitFileCallback} should be made
571     * thread-safe.
572     */
573    private static class ParallelParse extends RecursiveAction {
574
575        private static final long serialVersionUID = 1L;
576        private final Path path;
577        private final VisitFileCallback callback;
578
579        ParallelParse(Path pathVisitFileCallback callback) {
580            this.path = path;
581            this.callback = callback;
582        }
583
584        @Override
585        protected void compute() {
586            final List<ParallelParsewalks = new ArrayList<>();
587            try {
588                Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
589                    @Override
590                    public FileVisitResult preVisitDirectory(Path dirBasicFileAttributes attrs) throws IOException {
591                        if (!SourceRoot.isSensibleDirectoryToEnter(dir)) {
592                            return SKIP_SUBTREE;
593                        }
594                        if (!dir.equals(ParallelParse.this.path)) {
595                            ParallelParse w = new ParallelParse(dircallback);
596                            w.fork();
597                            walks.add(w);
598                            return SKIP_SUBTREE;
599                        } else {
600                            return CONTINUE;
601                        }
602                    }
603
604                    @Override
605                    public FileVisitResult visitFile(Path fileBasicFileAttributes attrs) {
606                        return callback.process(fileattrs);
607                    }
608                });
609            } catch (IOException e) {
610                Log.error(e);
611            }
612
613            for (ParallelParse w : walks) {
614                w.join();
615            }
616        }
617
618        interface VisitFileCallback {
619            FileVisitResult process(Path fileBasicFileAttributes attrs);
620        }
621    }
622
623    @Override
624    public String toString() {
625        return "SourceRoot at " + root;
626    }
627}
628
MembersX
SourceRoot:Callback:Result:SAVE
SourceRoot:ParallelParse:compute
SourceRoot:tryToParseParallelized:Block:path
SourceRoot:ParallelParse:compute:Block:Block:preVisitDirectory:Block:Block:w
SourceRoot:ParallelParse:VisitFileCallback:process
SourceRoot:tryToParseParallelized:Block:Block:Block:relative
SourceRoot:getCompilationUnits
SourceRoot:callback:Block:localPath
SourceRoot:setParserConfiguration
SourceRoot:tryToParse
SourceRoot:tryToParseParallelized:Block:pool
SourceRoot:logPackage
SourceRoot:tryToParse:Block:relativePath
SourceRoot:getRoot
SourceRoot:callback:Block:result
SourceRoot:tryToParseParallelized
SourceRoot:parse:Block:Block:result
SourceRoot:Callback:process
SourceRoot:JAVA_IDENTIFIER
SourceRoot:getParserConfiguration
SourceRoot:tryToParse:Block:visitFile:Block:Block:relative
SourceRoot:SourceRoot
SourceRoot:parserConfiguration
SourceRoot:printer
SourceRoot:ParallelParse:compute:Block:Block:visitFile
SourceRoot:parse
SourceRoot:setPrinter
SourceRoot:ParallelParse:ParallelParse
SourceRoot:isSensibleDirectoryToEnter
SourceRoot:saveAll:Block:Block:path
SourceRoot:tryToParseParallelized:Block:parse
SourceRoot:tryToParse:Block:preVisitDirectory
SourceRoot:parse:Block:Block:visitFile
SourceRoot:parseParallelized
SourceRoot:add:Block:Block:path
SourceRoot:Callback:Result:DONT_SAVE
SourceRoot:parse:Block:Block:preVisitDirectory
SourceRoot:tryToParse:Block:visitFile
SourceRoot:parse:Block:path
SourceRoot:tryToParse:Block:result
SourceRoot:isSensibleDirectoryToEnter:Block:dirToEnter
SourceRoot:getPrinter
SourceRoot:save
SourceRoot:ParallelParse:callback
SourceRoot:ParallelParse:serialVersionUID
SourceRoot:isSensibleDirectoryToEnter:Block:directoryIsAValidJavaIdentifier
SourceRoot:cache
SourceRoot:ParallelParse:compute:Block:Block:preVisitDirectory
SourceRoot:add:Block:Block:parseResult
SourceRoot:ParallelParse:compute:Block:walks
SourceRoot:add:Block:path
SourceRoot:toString
SourceRoot:parseParallelized:Block:Block:pool
SourceRoot:ParallelParse:path
SourceRoot:parseParallelized:Block:path
SourceRoot:getCache
SourceRoot:tryToParse:Block:path
SourceRoot:Callback:Result:TERMINATE
SourceRoot:callback
SourceRoot:add
SourceRoot:add:Block:parseResult
SourceRoot:root
SourceRoot:parseParallelized:Block:Block:parse
SourceRoot:saveAll
Members
X