package org.jetbrains.jps.incremental;
import org.jetbrains.jps.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: 9/17/11
*/
public class IncProjectBuilder {
private final Project myProject;
private final String myProjectName;
private final BuilderRegistry myBuilderRegistry;
private ProjectChunks myProductionChunks;
private ProjectChunks myTestChunks;
private final List<MessageHandler> myMessageHandlers = new ArrayList<MessageHandler>();
public IncProjectBuilder(Project project, String projectName, BuilderRegistry builderRegistry) {
myProject = project;
myProjectName = projectName;
myBuilderRegistry = builderRegistry;
myProductionChunks = new ProjectChunks(project, ClasspathKind.PRODUCTION_COMPILE);
myTestChunks = new ProjectChunks(project, ClasspathKind.TEST_COMPILE);
}
public void addMessageHandler(MessageHandler handler) {
myMessageHandlers.add(handler);
}
public void build(CompileScope scope, final boolean isMake) {
final CompileContext context = new CompileContext(scope, myProjectName, isMake, new MessageHandler() {
public void processMessage(BuildMessage msg) {
for (MessageHandler h : myMessageHandlers) {
h.processMessage(msg);
}
}
});
try {
if (!isMake) {
context.getBuildDataManager().clean();
}
for (Module module : scope.getAffectedModules()) {
//context.processMessage(new ProgressMessage("Cleaning module " + module.getName()));
//myProject.cleanModule(module);
}
runTasks(context, myBuilderRegistry.getBeforeTasks());
context.setCompilingTests(false);
buildChunks(context, myProductionChunks);
context.setCompilingTests(true);
buildChunks(context, myTestChunks);
runTasks(context, myBuilderRegistry.getAfterTasks());
}
catch (ProjectBuildException e) {
context.processMessage(new ProgressMessage(e.getMessage()));
}
finally {
context.getBuildDataManager().close();
}
}
private void runTasks(CompileContext context, final List<BuildTask> tasks) throws ProjectBuildException {
for (BuildTask task : tasks) {
task.build(context);
}
}
private void buildChunks(CompileContext context, ProjectChunks chunks) throws ProjectBuildException {
final CompileScope scope = context.getScope();
for (ModuleChunk chunk : chunks.getChunkList()) {
if (scope.isAffected(chunk)) {
buildChunk(context, chunk);
}
}
}
private void buildChunk(CompileContext context, ModuleChunk chunk) throws ProjectBuildException{
try {
for (BuilderCategory category : BuilderCategory.values()) {
runBuilders(context, chunk, myBuilderRegistry.getBuilders(category));
}
}
finally {
context.clearFileCache();
}
}
private void runBuilders(CompileContext context, ModuleChunk chunk, List<Builder> builders) throws ProjectBuildException {
boolean nextPassRequired;
do {
nextPassRequired = false;
for (Builder builder : builders) {
//final String sourcesKind = context.isCompilingTests() ? "test" : "production";
//context.processMessage(new ProgressMessage("Compiling " + chunk.getName() + "[" + sourcesKind+"]; Compiler: " + builder.getDescription()));
final Builder.ExitCode buildResult = builder.build(context, chunk);
if (buildResult == Builder.ExitCode.ABORT) {
throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop");
}
if (buildResult == Builder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
nextPassRequired = true;
}
}
}
while (nextPassRequired);
}
}