Skip to content

Commit

Permalink
refresh javac output to make sure Java project system recognize the o…
Browse files Browse the repository at this point in the history
…utput changes
  • Loading branch information
testforstephen committed Jun 26, 2024
1 parent 11c20af commit 585db98
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.builder.SourceFile;

import com.sun.tools.javac.api.MultiTaskListener;
import com.sun.tools.javac.comp.*;
import com.sun.tools.javac.comp.CompileStates.CompileState;
import com.sun.tools.javac.main.JavaCompiler;
Expand Down Expand Up @@ -100,6 +101,12 @@ public void compile(ICompilationUnit[] sourceUnits) {
return true;
})
.collect(Collectors.groupingBy(this::computeOutputDirectory));

// Register listener to intercept intermediate results from Javac task.
JavacTaskListener resultListener = new JavacTaskListener(this.compilerConfig, outputSourceMapping);
MultiTaskListener mtl = MultiTaskListener.instance(javacContext);
mtl.add(resultListener);

for (Entry<File, List<ICompilationUnit>> outputSourceSet : outputSourceMapping.entrySet()) {
var outputFile = outputSourceSet.getKey();
JavacUtils.configureJavacContext(javacContext, this.compilerConfig, javaProject, outputFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ public record JavacConfig(
* The compiler options used to control the compilation behavior.
* See {@link org.eclipse.jdt.internal.compiler.impl.CompilerOptions} for a list of available options.
*/
CompilerOptions compilerOptions) {
CompilerOptions compilerOptions,
/**
* A reference to the original config
*/
CompilerConfiguration originalConfig) {

static JavacConfig createFrom(CompilerConfiguration config) {
return new JavacConfig(
Expand All @@ -68,6 +72,7 @@ static JavacConfig createFrom(CompilerConfiguration config) {
config.annotationProcessorPaths().stream().map(URI::getPath).collect(Collectors.toList()),
config.generatedSourcePaths().stream().map(IContainer::getRawLocation).filter(path -> path != null).map(IPath::toOSString).collect(Collectors.toList()),
config.sourceOutputMapping().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getRawLocation().toFile(), e -> e.getValue().getRawLocation().toFile())),
config.compilerOptions());
config.compilerOptions(),
config);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2024 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.jdt.internal.javac;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import javax.lang.model.element.TypeElement;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;

import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.code.Symbol.ClassSymbol;

public class JavacTaskListener implements TaskListener {
private Map<ICompilationUnit, IContainer> sourceOutputMapping = new HashMap<>();

public JavacTaskListener(JavacConfig config, Map<File, List<ICompilationUnit>> outputSourceMapping) {
Map<File, IContainer> outputs = config.originalConfig().sourceOutputMapping().values().stream()
.distinct().filter(container -> container.getRawLocation() != null)
.collect(Collectors.toMap(container -> container.getRawLocation().toFile(), container -> container));
for (Entry<File, List<ICompilationUnit>> entry : outputSourceMapping.entrySet()) {
if (outputs.containsKey(entry.getKey())) {
IContainer currentOutput = outputs.get(entry.getKey());
entry.getValue().forEach(cu -> sourceOutputMapping.put(cu, currentOutput));
}
}
}

@Override
public void finished(TaskEvent e) {
if (e.getKind() == TaskEvent.Kind.GENERATE) {
if (e.getSourceFile() instanceof JavacFileObject sourceFile) {
ICompilationUnit originalUnit = sourceFile.getOriginalUnit();
IContainer outputDir = this.sourceOutputMapping.get(originalUnit);
if (outputDir != null) {
TypeElement element = e.getTypeElement();
if (element instanceof ClassSymbol clazz) {
String fileName = clazz.flatName().toString().replace('.', File.separatorChar);
IPath filePath = new Path(fileName);
IFile classFile = outputDir.getFile(filePath.addFileExtension(SuffixConstants.EXTENSION_class));
try {
// refresh the class file to make sure it is visible in the Eclipse workspace
classFile.refreshLocal(IResource.DEPTH_ZERO, null);
} catch (CoreException e1) {
// TODO error handling
}
}
}
}
}
}
}

0 comments on commit 585db98

Please sign in to comment.