summaryrefslogtreecommitdiff
path: root/src/main/java/org/javacs/InferSourcePath.java
blob: f1fd1d2fb24e617b562685d451ecab4836d53728 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package org.javacs;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.stream.Stream;

class InferSourcePath {

    static Stream<Path> allJavaFiles(Path dir) {
        var match = FileSystems.getDefault().getPathMatcher("glob:*.java");

        try {
            return Files.walk(dir).filter(java -> match.matches(java.getFileName()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static Set<Path> sourcePath(Path workspaceRoot) {
        LOG.info("Searching for source roots in " + workspaceRoot);

        class SourcePaths implements Consumer<Path> {
            int certaintyThreshold = 10;
            Map<Path, Integer> sourceRoots = new HashMap<>();

            boolean alreadyKnown(Path java) {
                for (var root : sourceRoots.keySet()) {
                    if (java.startsWith(root) && sourceRoots.get(root) > certaintyThreshold) return true;
                }
                return false;
            }

            Optional<Path> infer(Path java) {
                var packageName = Objects.toString(Parser.parse(java).getPackageName(), "");
                var packagePath = packageName.replace('.', File.separatorChar);
                var dir = java.getParent();
                if (packagePath.isEmpty()) {
                    LOG.warning("Ignoring file with missing package declaration " + java);
                    return Optional.empty();
                } else if (!dir.endsWith(packagePath)) {
                    LOG.warning("Java source file " + java + " is not in " + packagePath);
                    return Optional.empty();
                } else {
                    var up = Paths.get(packagePath).getNameCount();
                    var truncate = dir;
                    for (int i = 0; i < up; i++) truncate = truncate.getParent();
                    return Optional.of(truncate);
                }
            }

            @Override
            public void accept(Path java) {
                if (java.getFileName().toString().equals("module-info.java")) return;

                if (!alreadyKnown(java)) {
                    infer(java)
                            .ifPresent(
                                    root -> {
                                        var count = sourceRoots.getOrDefault(root, 0);
                                        sourceRoots.put(root, count + 1);
                                    });
                }
            }
        }
        var checker = new SourcePaths();
        allJavaFiles(workspaceRoot).forEach(checker);
        return checker.sourceRoots.keySet();
    }

    private static final Logger LOG = Logger.getLogger("main");
}