Skip to content

Commit

Permalink
Add the option to use an alternative compiler for compiling classes i…
Browse files Browse the repository at this point in the history
…n JavaBuilder
  • Loading branch information
testforstephen committed May 27, 2024
1 parent 6eb38a2 commit 6860972
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,24 @@

package org.eclipse.jdt.apt.core.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath;
import org.eclipse.jdt.apt.core.internal.util.FactoryPathUtil;
import org.eclipse.jdt.apt.core.internal.util.TestCodeUtil;
import org.eclipse.jdt.apt.core.util.AptConfig;
import org.eclipse.jdt.core.ICompilationUnit;
Expand Down Expand Up @@ -208,6 +213,45 @@ public void processAnnotations(BuildContext[] allfiles) {
}
}

@Override
public String[] getAnnotationProcessorPaths(IJavaProject project, boolean isTest) {
List<String> processorPaths = new ArrayList<>();
FactoryPath factoryPath = FactoryPathUtil.getFactoryPath(project);
if (factoryPath == null) {
return super.getAnnotationProcessorPaths(project, isTest);
}

factoryPath.getEnabledContainers().keySet().forEach(container -> {
if (container instanceof JarFactoryContainer jarContainer) {
if (jarContainer.exists()) {
processorPaths.add(jarContainer.getJarFile().getAbsolutePath());
}
}
});

if (!processorPaths.isEmpty()) {
return processorPaths.toArray(new String[processorPaths.size()]);
}

return super.getAnnotationProcessorPaths(project, isTest);
}

@Override
public String[] getGeneratedSourcePaths(IJavaProject project, boolean isTest) {
AptProject aptProject = AptPlugin.getAptProject(project);
if (aptProject == null) {
return null;
}

GeneratedSourceFolderManager generatedSourceFolderManager = aptProject.getGeneratedSourceFolderManager(isTest);
if (generatedSourceFolderManager == null) {
return null;
}

IFolder folder = generatedSourceFolderManager.getFolder();
return folder == null ? null : new String[] { folder.getLocation().toOSString() };
}

@Override
public void reconcile(ReconcileContext context){
final ICompilationUnit workingCopy = context.getWorkingCopy();
Expand Down
1 change: 1 addition & 0 deletions org.eclipse.jdt.core.tests.builder/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Bundle-SymbolicName: org.eclipse.jdt.core.tests.builder; singleton:=true
Bundle-Version: 3.12.400.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Fragment-Host: org.eclipse.jdt.core
Export-Package: org.eclipse.jdt.core.tests.builder
Require-Bundle: org.junit;bundle-version="3.8.1",
org.eclipse.jdt.core;bundle-version="[3.36.0,4.0.0)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,21 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.builder.AbstractImageBuilder;

/**
* Basic tests of the image builder.
Expand Down Expand Up @@ -687,4 +696,70 @@ public void testBug549942() throws JavaModelException {
org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.MAX_AT_ONCE = save;
}
}

public void testCustomCompiler() throws JavaModelException {
final String CUSTOM_COMPILER_KEY = AbstractImageBuilder.class.getSimpleName() + ".compiler";
final String CUSTOM_COMPILER_VALUE = MockCompiler.class.getName();
try {
System.setProperty(CUSTOM_COMPILER_KEY, CUSTOM_COMPILER_VALUE);
IPath projectPath = env.addProject("Project"); //$NON-NLS-1$
env.addExternalJars(projectPath, Util.getJavaClassLibs());

// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$

IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$

IPath path = env.addClass(root, "p1", "Hello", //$NON-NLS-1$ //$NON-NLS-2$
"package p1;\n"+ //$NON-NLS-1$
"public class Hello {\n"+ //$NON-NLS-1$
" public static void main(String args[]) {\n"+ //$NON-NLS-1$
" System.out.println(\"Hello world\");\n"+ //$NON-NLS-1$
" }\n"+ //$NON-NLS-1$
"}\n" //$NON-NLS-1$
);

fullBuild(projectPath);

Problem[] problems = allSortedProblems(new IPath[] {path});

expectingProblemsFor(
path,
"Problem : Compilation error from MockCompiler [ resource : </Project/src/p1/Hello.java> range : <0,1> category : <60> severity : <2>]"
);
} finally {
System.clearProperty(CUSTOM_COMPILER_KEY);
}
}

public static class MockCompiler extends org.eclipse.jdt.internal.compiler.Compiler {
private CompilerConfiguration compilerConfig;

public MockCompiler(INameEnvironment environment, IErrorHandlingPolicy policy, CompilerConfiguration compilerConfig,
ICompilerRequestor requestor, IProblemFactory problemFactory) {
super(environment, policy, compilerConfig.getOptions(), requestor, problemFactory);
this.compilerConfig = compilerConfig;
}

@Override
public void compile(ICompilationUnit[] sourceUnits) {
for (int i = 0; i < sourceUnits.length; i++) {
ICompilationUnit in = sourceUnits[i];
CompilationResult result = new CompilationResult(in, i, sourceUnits.length, Integer.MAX_VALUE);
if (i == 0) {
CategorizedProblem problem = new DefaultProblem(in.getFileName(),
"Compilation error from MockCompiler",
0,
new String[0],
ProblemSeverities.Error,
0, 0, 0, 0);
result.problems = new CategorizedProblem[] { problem };
result.problemCount = result.problems.length;
}

this.requestor.acceptResult(result);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,31 @@ public void processAnnotations(BuildContext[] files) {
// do nothing by default
}

/**
* Returns where to find annotation processors. If this is not specified,
* then the class path is searched for processors.
*
* @param project the project to participate in
* @param isTest whether the annotation processor path is for test code
* @return the annotation processor paths
* @since 3.38
*/
public String[] getAnnotationProcessorPaths(IJavaProject project, boolean isTest) {
return null;
}

/**
* Returns the locations to place the generated source files.
*
* @param project the project to participate in
* @param isTest whether the generated source paths are for test code
* @return the locations to place the generated source files
* @since 3.38
*/
public String[] getGeneratedSourcePaths(IJavaProject project, boolean isTest) {
return null;
}

/**
* Returns whether this participant is interested in post processing of generated bytecode.
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*******************************************************************************
* 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.core.compiler;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

/**
* @since 3.38
*/
public class CompilerConfiguration {
List<String> sourcepaths;
List<String> moduleSourcepaths;
List<String> classpaths;
List<String> modulepaths;
Map<File, File> sourceOutputMapping;
CompilerOptions options;
// Location to search for annotation processors.
List<String> annotationProcessorPaths;
// Locations to place generated source files.
List<String> generatedSourcePaths;

public List<String> getClasspaths() {
return this.classpaths;
}

public void setClasspaths(List<String> classpaths) {
this.classpaths = classpaths;
}

public List<String> getModulepaths() {
return this.modulepaths;
}

public void setModulepaths(List<String> modulepaths) {
this.modulepaths = modulepaths;
}

public List<String> getSourcepaths() {
return this.sourcepaths;
}

public void setSourcepaths(List<String> sourcepaths) {
this.sourcepaths = sourcepaths;
}

public List<String> getModuleSourcepaths() {
return this.moduleSourcepaths;
}

public void setModuleSourcepaths(List<String> moduleSourcepaths) {
this.moduleSourcepaths = moduleSourcepaths;
}

public Map<File, File> getSourceOutputMapping() {
return this.sourceOutputMapping;
}

public void setSourceOutputMapping(Map<File, File> sourceOutputMapping) {
this.sourceOutputMapping = sourceOutputMapping;
}

public CompilerOptions getOptions() {
return this.options;
}

public void setOptions(CompilerOptions options) {
this.options = options;
}

public List<String> getAnnotationProcessorPaths() {
return this.annotationProcessorPaths;
}

public void setAnnotationProcessorPaths(List<String> annotationProcessorPaths) {
this.annotationProcessorPaths = annotationProcessorPaths;
}

public List<String> getGeneratedSourcePaths() {
return this.generatedSourcePaths;
}

public void setGeneratedSourcePaths(List<String> generatedSourcePaths) {
this.generatedSourcePaths = generatedSourcePaths;
}
}
Loading

0 comments on commit 6860972

Please sign in to comment.