Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,4 @@ public void setup() {
public void jarIOBenchmark() {
JavaSourceSet.build("main", classpath);
}

@Benchmark
public void classgraphBenchmark() {
//noinspection deprecation
JavaSourceSet.build("main", classpath, new JavaTypeCache(), false);
}
}
3 changes: 2 additions & 1 deletion rewrite-core/src/main/java/org/openrewrite/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ public Path getRelativePath(@Nullable Path relativeTo) {
}

public EncodingDetectingInputStream getSource(ExecutionContext ctx) {
return new EncodingDetectingInputStream(source.get(), ParsingExecutionContextView.view(ctx).getCharset());
Charset charset = ParsingExecutionContextView.view(ctx).getCharset();
return new EncodingDetectingInputStream(source.get(), charset != null ? charset : StandardCharsets.UTF_8);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,8 @@ public ReloadableJava11Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<String, List<JavaFileObject>> listCache = new HashMap<>();

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -396,19 +398,51 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
String key = location.getName() + ':' + packageName + ':' + kinds + ':' + recurse;
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location)) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava17Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,51 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava21Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,51 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ReloadableJava25Parser build() {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<ListCacheKey, List<JavaFileObject>> listCache = new HashMap<>();

private record ListCacheKey(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) {}

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -367,20 +371,51 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
super.setLocationFromPaths(location, paths);
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
if (StandardLocation.CLASS_PATH.equals(location)) {
ListCacheKey key = new ListCacheKey(location, packageName, kinds, recurse);
List<JavaFileObject> cached = listCache.get(key);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH.equals(location) && !classByteClasspath.isEmpty()) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return classByteClasspath.isEmpty() ? listed :
Stream.concat(classByteClasspath.stream()
result = Stream.concat(classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(key, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ public void reset(Collection<URI> uris) {

private static class ByteArrayCapableJavacFileManager extends JavacFileManager {
private final List<PackageAwareJavaFileObject> classByteClasspath;
private final IdentityHashMap<JavaFileObject, String> inferBinaryNameCache = new IdentityHashMap<>();
private final HashMap<String, List<JavaFileObject>> listCache = new HashMap<>();

public ByteArrayCapableJavacFileManager(Context context,
boolean register,
Expand All @@ -331,20 +333,46 @@ public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof PackageAwareJavaFileObject) {
return ((PackageAwareJavaFileObject) file).getClassName();
}
return super.inferBinaryName(location, file);
String cached = inferBinaryNameCache.get(file);
if (cached != null) {
return cached;
}
String result = super.inferBinaryName(location, file);
if (result != null) {
inferBinaryNameCache.put(file, result);
}
return result;
}

@Override
public void flush() {
super.flush();
inferBinaryNameCache.clear();
listCache.clear();
}

@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
String cacheKey = location.getName() + ':' + packageName + ':' + kinds + ':' + recurse;
List<JavaFileObject> cached = listCache.get(cacheKey);
if (cached != null) {
return cached;
}
List<JavaFileObject> result;
if (StandardLocation.CLASS_PATH == location) {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
return Stream.concat(
result = Stream.concat(
classByteClasspath.stream()
.filter(jfo -> jfo.getPackage().equals(packageName)),
StreamSupport.stream(listed.spliterator(), false)
).collect(toList());
} else {
Iterable<JavaFileObject> listed = super.list(location, packageName, kinds, recurse);
result = listed instanceof List ? (List<JavaFileObject>) listed :
StreamSupport.stream(listed.spliterator(), false).collect(toList());
}
return super.list(location, packageName, kinds, recurse);
listCache.put(cacheKey, result);
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public static SourceSpec<?> sourceSet(SourceSpec<?> sourceSpec, String sourceSet

public static UncheckedConsumer<List<SourceFile>> addTypesToSourceSet(String sourceSetName, List<String> extendsFrom, List<Path> classpath) {
return sourceFiles -> {
JavaSourceSet sourceSet = JavaSourceSet.build(sourceSetName, classpath, new JavaTypeCache(), false);
JavaSourceSet sourceSet = JavaSourceSet.build(sourceSetName, classpath);

for (int i = 0; i < sourceFiles.size(); i++) {
SourceFile sourceFile = sourceFiles.get(i);
Expand Down
13 changes: 7 additions & 6 deletions rewrite-java/src/main/java/org/openrewrite/java/JavaParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -366,21 +366,22 @@ default Path sourcePathFromSourceText(Path prefix, String sourceCode) {
return resolveSourcePathFromSourceText(prefix, sourceCode);
}

Pattern SOURCE_PATH_PACKAGE_PATTERN = Pattern.compile("^package\\s+([^;]+);");
Pattern SOURCE_PATH_CLASS_PATTERN = Pattern.compile("(class|interface|enum|record)\\s*(<[^>]*>)?\\s+(\\w+)");
Pattern SOURCE_PATH_PUBLIC_CLASS_PATTERN = Pattern.compile("public\\s+" + SOURCE_PATH_CLASS_PATTERN.pattern());

static Path resolveSourcePathFromSourceText(Path prefix, String sourceCode) {
Pattern packagePattern = Pattern.compile("^package\\s+([^;]+);");
Pattern classPattern = Pattern.compile("(class|interface|enum|record)\\s*(<[^>]*>)?\\s+(\\w+)");
Pattern publicClassPattern = Pattern.compile("public\\s+" + classPattern.pattern());

Function<String, @Nullable String> simpleName = sourceStr -> {
Matcher classMatcher = publicClassPattern.matcher(sourceStr);
Matcher classMatcher = SOURCE_PATH_PUBLIC_CLASS_PATTERN.matcher(sourceStr);
if (classMatcher.find()) {
return classMatcher.group(3);
}
classMatcher = classPattern.matcher(sourceStr);
classMatcher = SOURCE_PATH_CLASS_PATTERN.matcher(sourceStr);
return classMatcher.find() ? classMatcher.group(3) : null;
};

Matcher packageMatcher = packagePattern.matcher(sourceCode);
Matcher packageMatcher = SOURCE_PATH_PACKAGE_PATTERN.matcher(sourceCode);
String pkg = packageMatcher.find() ? packageMatcher.group(1).replace('.', '/') + "/" : "";

String className = Optional.ofNullable(simpleName.apply(sourceCode))
Expand Down
Loading