Skip to content

Commit 1b4c900

Browse files
stuartwdouglasgsmet
authored andcommitted
Use source file mapping for all compilation providers
All compilation providers should be setting the source file attribute for use in debugging, there is no need to limit this to Java. This should allow for deletions of Kotlin classes to be handled correctly. (cherry picked from commit c61a3e2)
1 parent 07c6be8 commit 1b4c900

File tree

6 files changed

+80
-63
lines changed

6 files changed

+80
-63
lines changed

core/deployment/src/main/java/io/quarkus/deployment/dev/CompilationProvider.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
import java.io.Closeable;
44
import java.io.File;
55
import java.io.IOException;
6+
import java.io.InputStream;
67
import java.nio.charset.Charset;
78
import java.nio.charset.StandardCharsets;
9+
import java.nio.file.Files;
810
import java.nio.file.Path;
911
import java.util.Collections;
1012
import java.util.HashMap;
1113
import java.util.List;
1214
import java.util.Map;
1315
import java.util.Set;
1416

17+
import org.objectweb.asm.ClassReader;
18+
1519
import io.quarkus.paths.PathCollection;
1620

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

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

31-
Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath);
35+
default Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
36+
Path sourceFilePath;
37+
final RuntimeUpdatesClassVisitor visitor = new RuntimeUpdatesClassVisitor(sourcePaths, classesPath);
38+
try (final InputStream inputStream = Files.newInputStream(classFilePath)) {
39+
final ClassReader reader = new ClassReader(inputStream);
40+
reader.accept(visitor, 0);
41+
sourceFilePath = visitor.getSourceFileForClass(classFilePath);
42+
} catch (IOException e) {
43+
throw new RuntimeException(e);
44+
}
45+
return sourceFilePath;
46+
}
3247

3348
@Override
3449
default void close() throws IOException {
@@ -159,5 +174,7 @@ public boolean ignoreModuleInfo() {
159174
public File getGeneratedSourcesDirectory() {
160175
return generatedSourcesDirectory;
161176
}
177+
162178
}
179+
163180
}

core/deployment/src/main/java/io/quarkus/deployment/dev/JavaCompilationProvider.java

-54
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@
22

33
import java.io.File;
44
import java.io.IOException;
5-
import java.io.InputStream;
65
import java.nio.charset.Charset;
7-
import java.nio.file.Files;
8-
import java.nio.file.Path;
9-
import java.nio.file.Paths;
106
import java.util.List;
117
import java.util.Set;
128
import java.util.function.BiConsumer;
@@ -20,14 +16,10 @@
2016
import javax.tools.ToolProvider;
2117

2218
import org.jboss.logging.Logger;
23-
import org.objectweb.asm.ClassReader;
24-
import org.objectweb.asm.ClassVisitor;
2519

2620
import io.quarkus.deployment.dev.filesystem.QuarkusFileManager;
2721
import io.quarkus.deployment.dev.filesystem.ReloadableFileManager;
2822
import io.quarkus.deployment.dev.filesystem.StaticFileManager;
29-
import io.quarkus.gizmo.Gizmo;
30-
import io.quarkus.paths.PathCollection;
3123

3224
public class JavaCompilationProvider implements CompilationProvider {
3325

@@ -115,20 +107,6 @@ public void compile(Set<File> filesToCompile, CompilationProvider.Context contex
115107
}
116108
}
117109

118-
@Override
119-
public Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
120-
Path sourceFilePath;
121-
final RuntimeUpdatesClassVisitor visitor = new RuntimeUpdatesClassVisitor(sourcePaths, classesPath);
122-
try (final InputStream inputStream = Files.newInputStream(classFilePath)) {
123-
final ClassReader reader = new ClassReader(inputStream);
124-
reader.accept(visitor, 0);
125-
sourceFilePath = visitor.getSourceFileForClass(classFilePath);
126-
} catch (IOException e) {
127-
throw new RuntimeException(e);
128-
}
129-
return sourceFilePath;
130-
}
131-
132110
@Override
133111
public void close() throws IOException {
134112
if (this.fileManager != null) {
@@ -154,36 +132,4 @@ private String extractCompilationErrorMessage(final DiagnosticCollector<JavaFile
154132
diagnosticsCollector.getDiagnostics().forEach(diagnostic -> builder.append("\n").append(diagnostic));
155133
return String.format("\u001B[91mCompilation Failed:%s\u001b[0m", builder);
156134
}
157-
158-
private static class RuntimeUpdatesClassVisitor extends ClassVisitor {
159-
private final PathCollection sourcePaths;
160-
private final String classesPath;
161-
private String sourceFile;
162-
163-
public RuntimeUpdatesClassVisitor(PathCollection sourcePaths, String classesPath) {
164-
super(Gizmo.ASM_API_VERSION);
165-
this.sourcePaths = sourcePaths;
166-
this.classesPath = classesPath;
167-
}
168-
169-
@Override
170-
public void visitSource(String source, String debug) {
171-
this.sourceFile = source;
172-
}
173-
174-
public Path getSourceFileForClass(final Path classFilePath) {
175-
for (Path sourcesDir : sourcePaths) {
176-
final Path classesDir = Paths.get(classesPath);
177-
final StringBuilder sourceRelativeDir = new StringBuilder();
178-
sourceRelativeDir.append(classesDir.relativize(classFilePath.getParent()));
179-
sourceRelativeDir.append(File.separator);
180-
sourceRelativeDir.append(sourceFile);
181-
final Path sourceFilePath = sourcesDir.resolve(Path.of(sourceRelativeDir.toString()));
182-
if (Files.exists(sourceFilePath)) {
183-
return sourceFilePath;
184-
}
185-
}
186-
return null;
187-
}
188-
}
189135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.quarkus.deployment.dev;
2+
3+
import java.io.File;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
7+
8+
import org.objectweb.asm.ClassVisitor;
9+
10+
import io.quarkus.gizmo.Gizmo;
11+
import io.quarkus.paths.PathCollection;
12+
13+
public class RuntimeUpdatesClassVisitor extends ClassVisitor {
14+
private final PathCollection sourcePaths;
15+
private final String classesPath;
16+
private String sourceFile;
17+
18+
public RuntimeUpdatesClassVisitor(PathCollection sourcePaths, String classesPath) {
19+
super(Gizmo.ASM_API_VERSION);
20+
this.sourcePaths = sourcePaths;
21+
this.classesPath = classesPath;
22+
}
23+
24+
@Override
25+
public void visitSource(String source, String debug) {
26+
this.sourceFile = source;
27+
}
28+
29+
public Path getSourceFileForClass(final Path classFilePath) {
30+
for (Path sourcesDir : sourcePaths) {
31+
final Path classesDir = Paths.get(classesPath);
32+
final StringBuilder sourceRelativeDir = new StringBuilder();
33+
sourceRelativeDir.append(classesDir.relativize(classFilePath.getParent()));
34+
sourceRelativeDir.append(File.separator);
35+
sourceRelativeDir.append(sourceFile);
36+
final Path sourceFilePath = sourcesDir.resolve(Path.of(sourceRelativeDir.toString()));
37+
if (Files.exists(sourceFilePath)) {
38+
return sourceFilePath;
39+
}
40+
}
41+
return null;
42+
}
43+
}

extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinCompilationProvider.java

-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.quarkus.kotlin.deployment;
22

33
import java.io.File;
4-
import java.nio.file.Path;
54
import java.util.ArrayList;
65
import java.util.Collection;
76
import java.util.Collections;
@@ -22,7 +21,6 @@
2221
import org.jetbrains.kotlin.config.Services;
2322

2423
import io.quarkus.deployment.dev.CompilationProvider;
25-
import io.quarkus.paths.PathCollection;
2624

2725
public class KotlinCompilationProvider implements CompilationProvider {
2826

@@ -103,12 +101,6 @@ public void compile(Set<File> filesToCompile, Context context) {
103101
}
104102
}
105103

106-
@Override
107-
public Path getSourcePath(Path classFilePath, PathCollection sourcePaths, String classesPath) {
108-
// return same class so it is not removed
109-
return classFilePath;
110-
}
111-
112104
private static class SimpleKotlinCompilerMessageCollector implements MessageCollector {
113105

114106
private final List<String> errors = new ArrayList<>();

integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/BasicKotlinApplicationModuleDevModeTest.java

+5
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@ protected void testDevMode() throws Exception {
2323
ImmutableMap.of("return \"hello\"", "return \"" + uuid + "\""));
2424

2525
assertUpdatedResponseContains("/hello", uuid);
26+
27+
delete("src/main/kotlin/org/acme/GreetingResource.kt");
28+
29+
assertStatusCode("/hello", 404);
30+
2631
}
2732
}

integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/QuarkusDevGradleTestBase.java

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.apache.commons.io.FileUtils;
2424
import org.junit.jupiter.api.Test;
25+
import org.wildfly.common.Assert;
2526

2627
import io.quarkus.gradle.BuildResult;
2728
import io.quarkus.gradle.QuarkusGradleWrapperTestBase;
@@ -180,6 +181,12 @@ protected void replace(String srcFile, Map<String, String> tokens) {
180181
}
181182
}
182183

184+
protected void delete(String srcFile) {
185+
final File source = new File(getProjectDir(), srcFile);
186+
assertThat(source).exists();
187+
Assert.assertTrue(source.delete());
188+
}
189+
183190
protected void assertUpdatedResponseContains(String path, String value) {
184191
assertUpdatedResponseContains(path, value, devModeTimeoutSeconds(), TimeUnit.SECONDS);
185192
}
@@ -198,4 +205,11 @@ protected void assertUpdatedResponseContains(String path, String value, long wai
198205
.pollDelay(100, TimeUnit.MILLISECONDS)
199206
.atMost(waitAtMost, timeUnit).until(() -> getHttpResponse(path, waitAtMost, timeUnit).contains(value));
200207
}
208+
209+
protected void assertStatusCode(String path, int code) {
210+
await()
211+
.pollDelay(100, TimeUnit.MILLISECONDS)
212+
.atMost(devModeTimeoutSeconds(), TimeUnit.SECONDS)
213+
.until(() -> Assert.assertTrue(devModeClient.getStrictHttpResponse(path, code)));
214+
}
201215
}

0 commit comments

Comments
 (0)