|
4 | 4 | import java.io.File; |
5 | 5 | import java.io.IOException; |
6 | 6 | import java.nio.file.Path; |
| 7 | +import java.util.ArrayList; |
7 | 8 | import java.util.Collection; |
| 9 | +import java.util.Collections; |
| 10 | +import java.util.HashMap; |
8 | 11 | import java.util.Iterator; |
| 12 | +import java.util.List; |
| 13 | +import java.util.Map; |
| 14 | +import java.util.Objects; |
9 | 15 | import java.util.ServiceLoader; |
10 | 16 | import java.util.Set; |
11 | 17 | import javax.tools.FileObject; |
12 | 18 | import javax.tools.JavaFileObject; |
13 | 19 | import javax.tools.StandardJavaFileManager; |
| 20 | +import javax.tools.StandardLocation; |
14 | 21 |
|
15 | | -class HideModuleInfo implements StandardJavaFileManager { |
| 22 | +class FileManagerWrapper implements StandardJavaFileManager { |
16 | 23 | private final StandardJavaFileManager delegate; |
17 | 24 |
|
18 | | - HideModuleInfo(StandardJavaFileManager delegate) { |
| 25 | + FileManagerWrapper(StandardJavaFileManager delegate) { |
19 | 26 | this.delegate = delegate; |
20 | 27 | } |
21 | 28 |
|
@@ -135,10 +142,70 @@ public ClassLoader getClassLoader(Location location) { |
135 | 142 | return delegate.getClassLoader(location); |
136 | 143 | } |
137 | 144 |
|
| 145 | + // Cache calls to list(...) |
| 146 | + static class Key { |
| 147 | + final Location location; |
| 148 | + final String packageName; |
| 149 | + final JavaFileObject.Kind kind; |
| 150 | + final boolean recurse; |
| 151 | + |
| 152 | + Key(Location location, String packageName, JavaFileObject.Kind kind, boolean recurse) { |
| 153 | + this.location = location; |
| 154 | + this.packageName = packageName; |
| 155 | + this.kind = kind; |
| 156 | + this.recurse = recurse; |
| 157 | + } |
| 158 | + |
| 159 | + @Override |
| 160 | + public boolean equals(Object candidate) { |
| 161 | + if (!(candidate instanceof Key)) return false; |
| 162 | + var that = (Key) candidate; |
| 163 | + |
| 164 | + return Objects.equals(this.location, that.location) |
| 165 | + && Objects.equals(this.packageName, that.packageName) |
| 166 | + && Objects.equals(this.kind, that.kind) |
| 167 | + && Objects.equals(this.recurse, that.recurse); |
| 168 | + } |
| 169 | + |
| 170 | + @Override |
| 171 | + public int hashCode() { |
| 172 | + return Objects.hash(location, packageName, kind, recurse); |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + // Store previous calls to list, because listing directories and .jar files is expensive |
| 177 | + private Map<Key, List<JavaFileObject>> cache = new HashMap<>(); |
| 178 | + |
| 179 | + private List<JavaFileObject> loadCache(Key key) { |
| 180 | + try { |
| 181 | + var list = new ArrayList<JavaFileObject>(); |
| 182 | + var it = |
| 183 | + removeModuleInfoInvariant( |
| 184 | + delegate.list(key.location, key.packageName, Collections.singleton(key.kind), key.recurse)); |
| 185 | + for (var file : it) list.add(file); |
| 186 | + return list; |
| 187 | + } catch (IOException e) { |
| 188 | + throw new RuntimeException(e); |
| 189 | + } |
| 190 | + } |
| 191 | + |
138 | 192 | @Override |
139 | 193 | public Iterable<JavaFileObject> list( |
140 | 194 | Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { |
141 | | - return removeModuleInfoInvariant(delegate.list(location, packageName, kinds, recurse)); |
| 195 | + // If search source path, skip cache |
| 196 | + // TODO does this actually do anything? |
| 197 | + if (location == StandardLocation.SOURCE_PATH |
| 198 | + || location == StandardLocation.MODULE_SOURCE_PATH |
| 199 | + || location == StandardLocation.SOURCE_OUTPUT) |
| 200 | + return removeModuleInfoInvariant(delegate.list(location, packageName, kinds, recurse)); |
| 201 | + |
| 202 | + // Search for each kind separately to improve cacheability |
| 203 | + var result = new ArrayList<JavaFileObject>(); |
| 204 | + for (var kind : kinds) { |
| 205 | + var list = cache.computeIfAbsent(new Key(location, packageName, kind, recurse), this::loadCache); |
| 206 | + result.addAll(list); |
| 207 | + } |
| 208 | + return result; |
142 | 209 | } |
143 | 210 |
|
144 | 211 | @Override |
|
0 commit comments