From 499c926f24d20ac60d6f07d755b8993045f68c01 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Thu, 10 Oct 2024 12:54:33 +0800 Subject: [PATCH] Compile the generated sources into the expected target directory (#879) --- .../jdt/internal/javac/JavacCompiler.java | 2 + .../jdt/internal/javac/JavacTaskListener.java | 96 ++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java index 93e0d2320d3..cdeb5fb73f4 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java @@ -134,6 +134,7 @@ public void finished(TaskEvent e) { for (Entry> outputSourceSet : outputSourceMapping.entrySet()) { // Configure Javac to generate the class files in a mapped temporary location var outputDir = JavacClassFile.getMappedTempOutput(outputSourceSet.getKey()).toFile(); + javacListener.setOutputDir(outputSourceSet.getKey()); JavacUtils.configureJavacContext(javacContext, this.compilerConfig, javaProject, outputDir, true); JavaCompiler javac = new JavaCompiler(javacContext) { boolean isInGeneration = false; @@ -197,6 +198,7 @@ public int errorCount() { // TODO fail ILog.get().error("compilation failed", e); } + for (int i = 0; i < sourceUnits.length; i++) { ICompilationUnit in = sourceUnits[i]; CompilationResult result = new CompilationResult(in, i, sourceUnits.length, Integer.MAX_VALUE); diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacTaskListener.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacTaskListener.java index 0ff518ed46b..c2aae1ba041 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacTaskListener.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacTaskListener.java @@ -13,6 +13,11 @@ package org.eclipse.jdt.internal.javac; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -26,10 +31,16 @@ import javax.tools.JavaFileObject; import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; @@ -48,13 +59,15 @@ import com.sun.tools.javac.code.Type.UnknownType; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; -import com.sun.tools.javac.tree.JCTree.JCModuleDecl; import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCModuleDecl; public class JavacTaskListener implements TaskListener { private Map sourceOutputMapping = new HashMap<>(); private Map results = new HashMap<>(); private UnusedProblemFactory problemFactory; + private JavacConfig config; + private IContainer outputDir; private final Map fileObjectToCUMap; private static final Set PRIMITIVE_TYPES = new HashSet(Arrays.asList( "byte", @@ -71,6 +84,7 @@ public class JavacTaskListener implements TaskListener { public JavacTaskListener(JavacConfig config, Map> outputSourceMapping, IProblemFactory problemFactory, Map fileObjectToCUMap) { + this.config = config; this.problemFactory = new UnusedProblemFactory(problemFactory, config.compilerOptions()); this.fileObjectToCUMap = fileObjectToCUMap; for (Entry> entry : outputSourceMapping.entrySet()) { @@ -81,7 +95,18 @@ public JavacTaskListener(JavacConfig config, Map generatedSourcePaths = this.config.originalConfig().generatedSourcePaths(); + if (generatedSourcePaths == null || generatedSourcePaths.isEmpty()) { + return false; + } + + URI uri = file.toUri(); + if (uri != null && uri.getPath() != null) { + File ioFile = new File(uri.getPath()); + Path fileIOPath = ioFile.toPath(); + return generatedSourcePaths.stream().anyMatch(container -> { + IPath location = container.getRawLocation(); + if (location != null) { + Path locationIOPath = location.toPath(); + return fileIOPath.startsWith(locationIOPath); + } + return false; + }); + } + return false; + } + + private void writeClassFile(ClassSymbol clazz) throws CoreException { + if (this.outputDir == null) { + return; + } + + String qualifiedName = clazz.flatName().toString().replace('.', '/'); + IPath filePath = new org.eclipse.core.runtime.Path(qualifiedName); + IContainer fileFolder = this.outputDir; + if (filePath.segmentCount() > 1) { + fileFolder = createFolder(filePath.removeLastSegments(1), this.outputDir); + filePath = new org.eclipse.core.runtime.Path(filePath.lastSegment()); + } + + IFile classFile = fileFolder.getFile(filePath.addFileExtension(SuffixConstants.EXTENSION_class)); + File tmpJavacClassFile = JavacClassFile.computeMappedTempClassFile(this.outputDir, qualifiedName); + if (tmpJavacClassFile == null || !tmpJavacClassFile.exists()) { + return; + } + + try { + byte[] bytes = Files.readAllBytes(tmpJavacClassFile.toPath()); + classFile.write(bytes, true, true, false, null); + tmpJavacClassFile.delete(); + } catch (IOException e) { + // ignore + } + } + + private IContainer createFolder(IPath packagePath, IContainer outputFolder) throws CoreException { + if (packagePath.isEmpty()) { + return outputFolder; + } + + IFolder folder = outputFolder.getFolder(packagePath); + if (!folder.exists()) { + createFolder(packagePath.removeLastSegments(1), outputFolder); + folder.create(IResource.FORCE | IResource.DERIVED, true, null); + } + return folder; + } + + public void setOutputDir(IContainer outputDir) { + this.outputDir = outputDir; + } + public Map getResults() { return this.results; }