Skip to content

Commit

Permalink
Merge pull request #46585 from stuartwdouglas/stuartwdouglas/kotlin-s…
Browse files Browse the repository at this point in the history
…ource-file-detection

Use source file mapping for all compilation providers
  • Loading branch information
geoand authored Mar 3, 2025
2 parents 503e496 + c61a3e2 commit 95c58a8
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.objectweb.asm.ClassReader;

import io.quarkus.paths.PathCollection;

public interface CompilationProvider extends Closeable {
Expand All @@ -28,7 +32,18 @@ default Set<String> handledSourcePaths() {

void compile(Set<File> files, Context context);

Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath);
default Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
Path sourceFilePath;
final RuntimeUpdatesClassVisitor visitor = new RuntimeUpdatesClassVisitor(sourcePaths, classesPath);
try (final InputStream inputStream = Files.newInputStream(classFilePath)) {
final ClassReader reader = new ClassReader(inputStream);
reader.accept(visitor, 0);
sourceFilePath = visitor.getSourceFileForClass(classFilePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
return sourceFilePath;
}

@Override
default void close() throws IOException {
Expand Down Expand Up @@ -159,5 +174,7 @@ public boolean ignoreModuleInfo() {
public File getGeneratedSourcesDirectory() {
return generatedSourcesDirectory;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
Expand All @@ -20,14 +16,10 @@
import javax.tools.ToolProvider;

import org.jboss.logging.Logger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;

import io.quarkus.deployment.dev.filesystem.QuarkusFileManager;
import io.quarkus.deployment.dev.filesystem.ReloadableFileManager;
import io.quarkus.deployment.dev.filesystem.StaticFileManager;
import io.quarkus.gizmo.Gizmo;
import io.quarkus.paths.PathCollection;

public class JavaCompilationProvider implements CompilationProvider {

Expand Down Expand Up @@ -115,20 +107,6 @@ public void compile(Set<File> filesToCompile, CompilationProvider.Context contex
}
}

@Override
public Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
Path sourceFilePath;
final RuntimeUpdatesClassVisitor visitor = new RuntimeUpdatesClassVisitor(sourcePaths, classesPath);
try (final InputStream inputStream = Files.newInputStream(classFilePath)) {
final ClassReader reader = new ClassReader(inputStream);
reader.accept(visitor, 0);
sourceFilePath = visitor.getSourceFileForClass(classFilePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
return sourceFilePath;
}

@Override
public void close() throws IOException {
if (this.fileManager != null) {
Expand All @@ -154,36 +132,4 @@ private String extractCompilationErrorMessage(final DiagnosticCollector<JavaFile
diagnosticsCollector.getDiagnostics().forEach(diagnostic -> builder.append("\n").append(diagnostic));
return String.format("\u001B[91mCompilation Failed:%s\u001b[0m", builder);
}

private static class RuntimeUpdatesClassVisitor extends ClassVisitor {
private final PathCollection sourcePaths;
private final String classesPath;
private String sourceFile;

public RuntimeUpdatesClassVisitor(PathCollection sourcePaths, String classesPath) {
super(Gizmo.ASM_API_VERSION);
this.sourcePaths = sourcePaths;
this.classesPath = classesPath;
}

@Override
public void visitSource(String source, String debug) {
this.sourceFile = source;
}

public Path getSourceFileForClass(final Path classFilePath) {
for (Path sourcesDir : sourcePaths) {
final Path classesDir = Paths.get(classesPath);
final StringBuilder sourceRelativeDir = new StringBuilder();
sourceRelativeDir.append(classesDir.relativize(classFilePath.getParent()));
sourceRelativeDir.append(File.separator);
sourceRelativeDir.append(sourceFile);
final Path sourceFilePath = sourcesDir.resolve(Path.of(sourceRelativeDir.toString()));
if (Files.exists(sourceFilePath)) {
return sourceFilePath;
}
}
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.quarkus.deployment.dev;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.objectweb.asm.ClassVisitor;

import io.quarkus.gizmo.Gizmo;
import io.quarkus.paths.PathCollection;

public class RuntimeUpdatesClassVisitor extends ClassVisitor {
private final PathCollection sourcePaths;
private final String classesPath;
private String sourceFile;

public RuntimeUpdatesClassVisitor(PathCollection sourcePaths, String classesPath) {
super(Gizmo.ASM_API_VERSION);
this.sourcePaths = sourcePaths;
this.classesPath = classesPath;
}

@Override
public void visitSource(String source, String debug) {
this.sourceFile = source;
}

public Path getSourceFileForClass(final Path classFilePath) {
for (Path sourcesDir : sourcePaths) {
final Path classesDir = Paths.get(classesPath);
final StringBuilder sourceRelativeDir = new StringBuilder();
sourceRelativeDir.append(classesDir.relativize(classFilePath.getParent()));
sourceRelativeDir.append(File.separator);
sourceRelativeDir.append(sourceFile);
final Path sourceFilePath = sourcesDir.resolve(Path.of(sourceRelativeDir.toString()));
if (Files.exists(sourceFilePath)) {
return sourceFilePath;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.quarkus.kotlin.deployment;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -22,7 +21,6 @@
import org.jetbrains.kotlin.config.Services;

import io.quarkus.deployment.dev.CompilationProvider;
import io.quarkus.paths.PathCollection;

public class KotlinCompilationProvider implements CompilationProvider {

Expand Down Expand Up @@ -103,12 +101,6 @@ public void compile(Set<File> filesToCompile, Context context) {
}
}

@Override
public Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
// return same class so it is not removed
return classFilePath;
}

private static class SimpleKotlinCompilerMessageCollector implements MessageCollector {

private final List<String> errors = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@ protected void testDevMode() throws Exception {
ImmutableMap.of("return \"hello\"", "return \"" + uuid + "\""));

assertUpdatedResponseContains("/hello", uuid);

delete("src/main/kotlin/org/acme/GreetingResource.kt");

assertStatusCode("/hello", 404);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.wildfly.common.Assert;

import io.quarkus.gradle.BuildResult;
import io.quarkus.gradle.QuarkusGradleWrapperTestBase;
Expand Down Expand Up @@ -180,6 +181,12 @@ protected void replace(String srcFile, Map<String, String> tokens) {
}
}

protected void delete(String srcFile) {
final File source = new File(getProjectDir(), srcFile);
assertThat(source).exists();
Assert.assertTrue(source.delete());
}

protected void assertUpdatedResponseContains(String path, String value) {
assertUpdatedResponseContains(path, value, devModeTimeoutSeconds(), TimeUnit.SECONDS);
}
Expand All @@ -198,4 +205,11 @@ protected void assertUpdatedResponseContains(String path, String value, long wai
.pollDelay(100, TimeUnit.MILLISECONDS)
.atMost(waitAtMost, timeUnit).until(() -> getHttpResponse(path, waitAtMost, timeUnit).contains(value));
}

protected void assertStatusCode(String path, int code) {
await()
.pollDelay(100, TimeUnit.MILLISECONDS)
.atMost(devModeTimeoutSeconds(), TimeUnit.SECONDS)
.until(() -> Assert.assertTrue(devModeClient.getStrictHttpResponse(path, code)));
}
}

0 comments on commit 95c58a8

Please sign in to comment.