external compiler: gwt

This commit is contained in:
nik
2012-10-08 11:21:43 +04:00
parent 404eddadcb
commit 07f910b71d
42 changed files with 516 additions and 259 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jps.builders;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import java.io.File;
import java.util.Collection;
@@ -22,7 +23,7 @@ public abstract class AdditionalRootsProviderService<R extends BuildRootDescript
}
@NotNull
public List<R> getAdditionalRoots(@NotNull BuildTarget<R> target, File dataStorageRoot) {
public List<R> getAdditionalRoots(@NotNull BuildTarget<R> target, BuildDataPaths dataPaths) {
return Collections.emptyList();
}
}
@@ -2,6 +2,7 @@ package org.jetbrains.jps.builders;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.model.JpsModel;
@@ -32,7 +33,10 @@ public abstract class BuildTarget<R extends BuildRootDescriptor> {
}
@NotNull
public abstract List<R> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex);
public abstract List<R> computeRootDescriptors(JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths);
@Nullable
public abstract BuildRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex);
@@ -15,7 +15,7 @@ public abstract class BuildTargetType<T extends BuildTarget<?>> {
myTypeId = typeId;
}
public String getTypeId() {
public final String getTypeId() {
return myTypeId;
}
@@ -0,0 +1,39 @@
package org.jetbrains.jps.builders.impl;
import com.intellij.util.PathUtilRt;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import java.io.File;
/**
* @author nik
*/
public class BuildDataPathsImpl implements BuildDataPaths {
private final File myDataStorageRoot;
public BuildDataPathsImpl(File dataStorageRoot) {
myDataStorageRoot = dataStorageRoot;
}
@Override
public File getDataStorageRoot() {
return myDataStorageRoot;
}
@Override
public File getTargetsDataRoot() {
return new File(myDataStorageRoot, "targets");
}
@Override
public File getTargetTypeDataRoot(BuildTargetType<?> targetType) {
return new File(getTargetsDataRoot(), targetType.getTypeId());
}
@Override
public File getTargetDataRoot(BuildTarget<?> target) {
return new File(getTargetTypeDataRoot(target.getTargetType()), PathUtilRt.suggestFileName(target.getId(), true, true));
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.*;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.BuilderRegistry;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.indices.IgnoredFileIndex;
@@ -33,32 +34,30 @@ public class BuildRootIndexImpl implements BuildRootIndex {
private THashMap<File,List<BuildRootDescriptor>> myRootToDescriptor;
private ConcurrentMap<BuildRootDescriptor, FileFilter> myFileFilters;
public BuildRootIndexImpl(BuildTargetIndex targetIndex,
JpsModel model,
ModuleExcludeIndex index,
File dataStorageRoot, final IgnoredFileIndex ignoredFileIndex) {
public BuildRootIndexImpl(BuildTargetIndex targetIndex, JpsModel model, ModuleExcludeIndex index,
BuildDataPaths dataPaths, final IgnoredFileIndex ignoredFileIndex) {
myRootsByTarget = new HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>>();
myRootToDescriptor = new THashMap<File, List<BuildRootDescriptor>>(FileUtil.FILE_HASHING_STRATEGY);
myFileFilters = new ConcurrentHashMap<BuildRootDescriptor, FileFilter>();
final Iterable<AdditionalRootsProviderService> rootsProviders = JpsServiceManager.getInstance().getExtensions(AdditionalRootsProviderService.class);
for (BuildTargetType<?> targetType : BuilderRegistry.getInstance().getTargetTypes()) {
for (BuildTarget<?> target : targetIndex.getAllTargets(targetType)) {
addRoots(dataStorageRoot, rootsProviders, targetType, target, model, index, ignoredFileIndex);
addRoots(dataPaths, rootsProviders, targetType, target, model, index, ignoredFileIndex);
}
}
}
private <R extends BuildRootDescriptor> void addRoots(File dataStorageRoot, Iterable<AdditionalRootsProviderService> rootsProviders,
private <R extends BuildRootDescriptor> void addRoots(BuildDataPaths dataPaths, Iterable<AdditionalRootsProviderService> rootsProviders,
BuildTargetType<?> targetType, BuildTarget<R> target,
JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex) {
List<R> descriptors = target.computeRootDescriptors(model, index, ignoredFileIndex);
List<R> descriptors = target.computeRootDescriptors(model, index, ignoredFileIndex, dataPaths);
for (AdditionalRootsProviderService<?> provider : rootsProviders) {
if (provider.getTargetTypes().contains(targetType)) {
//noinspection unchecked
AdditionalRootsProviderService<R> providerService = (AdditionalRootsProviderService<R>)provider;
final List<R> additionalRoots = providerService.getAdditionalRoots(target, dataStorageRoot);
final List<R> additionalRoots = providerService.getAdditionalRoots(target, dataPaths);
if (!additionalRoots.isEmpty()) {
descriptors = new ArrayList<R>(descriptors);
descriptors.addAll(additionalRoots);
@@ -0,0 +1,19 @@
package org.jetbrains.jps.builders.storage;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.BuildTargetType;
import java.io.File;
/**
* @author nik
*/
public interface BuildDataPaths {
File getDataStorageRoot();
File getTargetsDataRoot();
File getTargetTypeDataRoot(BuildTargetType<?> targetType);
File getTargetDataRoot(BuildTarget<?> target);
}
@@ -11,9 +11,11 @@ import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.BuildTargetLoader;
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl;
import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.messages.BuildMessage;
@@ -55,17 +57,18 @@ public class BuildRunner {
public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException {
final JpsModel jpsModel = myModelLoader.loadModel();
BuildDataPaths dataPaths = new BuildDataPathsImpl(dataStorageRoot);
BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(jpsModel);
ModuleExcludeIndex index = new ModuleExcludeIndexImpl(jpsModel);
IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(jpsModel);
BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, jpsModel, index, dataStorageRoot, ignoredFileIndex);
BuildTargetsState targetsState = new BuildTargetsState(dataStorageRoot, jpsModel, buildRootIndex);
BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, jpsModel, index, dataPaths, ignoredFileIndex);
BuildTargetsState targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex);
ProjectTimestamps projectTimestamps = null;
BuildDataManager dataManager = null;
try {
projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState);
dataManager = new BuildDataManager(dataStorageRoot, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
if (dataManager.versionDiffers()) {
myForceCleanCaches = true;
msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Dependency data format has changed, project rebuild required"));
@@ -82,9 +85,9 @@ public class BuildRunner {
}
myForceCleanCaches = true;
FileUtil.delete(dataStorageRoot);
targetsState = new BuildTargetsState(dataStorageRoot, jpsModel, buildRootIndex);
targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex);
projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState);
dataManager = new BuildDataManager(dataStorageRoot, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY);
// second attempt succeded
msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Project rebuild forced: " + e.getMessage()));
}
@@ -18,7 +18,7 @@ public class BuilderRegistry {
static final BuilderRegistry ourInstance = new BuilderRegistry();
}
private final Map<BuilderCategory, List<ModuleLevelBuilder>> myModuleLevelBuilders = new HashMap<BuilderCategory, List<ModuleLevelBuilder>>();
private final List<TargetBuilder<?>> myTargetBuilders = new ArrayList<TargetBuilder<?>>();
private final List<TargetBuilder<?,?>> myTargetBuilders = new ArrayList<TargetBuilder<?,?>>();
private final Map<String, BuildTargetType<?>> myTargetTypes = new LinkedHashMap<String, BuildTargetType<?>>();
public static BuilderRegistry getInstance() {
@@ -79,7 +79,7 @@ public class BuilderRegistry {
return ContainerUtil.concat(myModuleLevelBuilders.values());
}
public List<TargetBuilder<?>> getTargetBuilders() {
public List<TargetBuilder<?,?>> getTargetBuilders() {
return myTargetBuilders;
}
}
@@ -20,7 +20,7 @@ public abstract class BuilderService {
}
@NotNull
public List<? extends TargetBuilder<?>> createBuilders() {
public List<? extends TargetBuilder<?,?>> createBuilders() {
return Collections.emptyList();
}
}
@@ -5,6 +5,7 @@ import com.intellij.openapi.util.io.FileSystemUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.BuildTarget;
@@ -131,17 +132,21 @@ public class FSOperations {
Timestamps timestamps, boolean forceMarkDirty,
@Nullable THashSet<File> currentFiles) throws IOException {
final ModuleExcludeIndex rootsIndex = context.getProjectDescriptor().getModuleExcludeIndex();
final Set<File> excludes = new HashSet<File>(rootsIndex.getModuleExcludes(target.getModule()));
for (JavaSourceRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) {
if (!rd.root.exists()) {
markDirtyFiles(context, target, timestamps, forceMarkDirty, currentFiles,
new HashSet<File>(rootsIndex.getModuleExcludes(target.getModule())));
}
static void markDirtyFiles(CompileContext context, BuildTarget<?> target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet<File> currentFiles, final Set<File> excludes) throws IOException {
for (BuildRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) {
if (!rd.getRootFile().exists()) {
continue;
}
context.getProjectDescriptor().fsState.clearRecompile(rd);
traverseRecursively(context, rd, rd.root, excludes, timestamps, forceMarkDirty, currentFiles);
traverseRecursively(context, rd, rd.getRootFile(), excludes, timestamps, forceMarkDirty, currentFiles);
}
}
private static void traverseRecursively(CompileContext context, final JavaSourceRootDescriptor rd, final File file, Set<File> excludes, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set<File> currentFiles) throws IOException {
private static void traverseRecursively(CompileContext context, final BuildRootDescriptor rd, final File file, Set<File> excludes, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set<File> currentFiles) throws IOException {
final File[] children = file.listFiles();
if (children != null) { // is directory
if (children.length > 0 && !JpsPathUtil.isUnder(excludes, file)) {
@@ -153,7 +158,7 @@ public class FSOperations {
else { // is file
boolean markDirty = forceDirty;
if (!markDirty) {
markDirty = tsStorage.getStamp(file, rd.target) != FileSystemUtil.lastModified(file);
markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file);
}
if (markDirty) {
// if it is full project rebuild, all storages are already completely cleared;
@@ -528,13 +528,19 @@ public class IncProjectBuilder {
buildModuleChunk(context, new ModuleChunk(Collections.singleton(moduleBuildTarget)));
}
else {
buildTarget(target, context);
try {
buildTarget(target, context);
}
catch (IOException e) {
throw new ProjectBuildException(e);
}
}
}
private void buildTarget(BuildTarget<?> target, CompileContext context) throws ProjectBuildException {
List<TargetBuilder<?>> builders = BuilderRegistry.getInstance().getTargetBuilders();
for (TargetBuilder<?> builder : builders) {
private void buildTarget(BuildTarget<?> target, CompileContext context) throws ProjectBuildException, IOException {
ensureFSStateInitialized(context, target);
List<TargetBuilder<?,?>> builders = BuilderRegistry.getInstance().getTargetBuilders();
for (TargetBuilder<?,?> builder : builders) {
buildTarget(target, context, builder);
updateDoneFraction(context, 1.0f / builders.size());
}
@@ -546,10 +552,17 @@ public class IncProjectBuilder {
context.setDone(processed / myTotalTargetsWork);
}
private static <B extends BuildTarget<?>> void buildTarget(B target, CompileContext context, TargetBuilder<?> builder) throws ProjectBuildException {
private static <R extends BuildRootDescriptor, T extends BuildTarget<R>> void buildTarget(final T target, final CompileContext context, TargetBuilder<?,?> builder)
throws ProjectBuildException, IOException {
if (builder.getTargetTypes().contains(target.getTargetType())) {
DirtyFilesHolder<R, T> holder = new DirtyFilesHolder<R, T>() {
@Override
public void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException {
context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor);
}
};
//noinspection unchecked
((TargetBuilder<B>)builder).build(target, context);
((TargetBuilder<R,T>)builder).build(target, context, holder);
context.checkCanceled();
}
}
@@ -952,6 +965,16 @@ public class IncProjectBuilder {
}
}
private static void ensureFSStateInitialized(CompileContext context, BuildTarget<?> target) throws IOException {
final ProjectDescriptor pd = context.getProjectDescriptor();
final Timestamps timestamps = pd.timestamps.getStorage();
final BuildTargetConfiguration configuration = pd.getTargetsState().getTargetConfiguration(target);
if (context.isProjectRebuild() || configuration.isTargetDirty() || context.getScope().isRecompilationForced(target)) {
FSOperations.markDirtyFiles(context, target, timestamps, true, null, Collections.<File>emptySet());
configuration.save();
}
}
private static void ensureFSStateInitialized(CompileContext context, ModuleChunk chunk) throws IOException {
final ProjectDescriptor pd = context.getProjectDescriptor();
final Timestamps timestamps = pd.timestamps.getStorage();
@@ -3,6 +3,7 @@ package org.jetbrains.jps.incremental;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTarget;
@@ -79,7 +80,10 @@ public class ModuleBuildTarget extends BuildTarget<JavaSourceRootDescriptor> {
@NotNull
@Override
public List<JavaSourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) {
public List<JavaSourceRootDescriptor> computeRootDescriptors(JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths) {
List<JavaSourceRootDescriptor> roots = new ArrayList<JavaSourceRootDescriptor>();
JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
@@ -1,26 +1,30 @@
package org.jetbrains.jps.incremental;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import java.io.IOException;
import java.util.Collection;
/**
* Use {@link BuilderService} to register implementations of this class
* @author nik
*/
public abstract class TargetBuilder<B extends BuildTarget<?>> extends Builder {
private final Collection<? extends BuildTargetType<? extends B>> myTargetTypes;
public abstract class TargetBuilder<R extends BuildRootDescriptor, T extends BuildTarget<R>> extends Builder {
private final Collection<? extends BuildTargetType<? extends T>> myTargetTypes;
protected TargetBuilder(Collection<? extends BuildTargetType<? extends B>> targetTypes) {
protected TargetBuilder(Collection<? extends BuildTargetType<? extends T>> targetTypes) {
myTargetTypes = targetTypes;
}
public Collection<? extends BuildTargetType<? extends B>> getTargetTypes() {
public Collection<? extends BuildTargetType<? extends T>> getTargetTypes() {
return myTargetTypes;
}
public abstract void build(@NotNull B target, @NotNull CompileContext context) throws ProjectBuildException;
public abstract void build(@NotNull T target, @NotNull CompileContext context, DirtyFilesHolder<R, T> holder)
throws ProjectBuildException, IOException;
}
@@ -6,20 +6,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry;
import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactUtil;
import org.jetbrains.jps.incremental.artifacts.instructions.*;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.artifact.JpsArtifact;
import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement;
import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement;
import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement;
import org.jetbrains.jps.model.module.JpsModule;
import java.io.PrintWriter;
import java.util.Collection;
@@ -61,18 +57,7 @@ public class ArtifactBuildTarget extends BuildTarget<ArtifactRootDescriptor> {
}
}
}
else if (element instanceof JpsProductionModuleOutputPackagingElement) {
JpsModule module = ((JpsProductionModuleOutputPackagingElement)element).getModuleReference().resolve();
if (module != null) {
dependencies.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION));
}
}
else if (element instanceof JpsTestModuleOutputPackagingElement) {
JpsModule module = ((JpsTestModuleOutputPackagingElement)element).getModuleReference().resolve();
if (module != null) {
dependencies.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST));
}
}
dependencies.addAll(LayoutElementBuildersRegistry.getInstance().getDependencies(element));
return true;
}
});
@@ -102,9 +87,12 @@ public class ArtifactBuildTarget extends BuildTarget<ArtifactRootDescriptor> {
@NotNull
@Override
public List<ArtifactRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) {
public List<ArtifactRootDescriptor> computeRootDescriptors(JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths) {
ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(index, ignoredFileIndex, this);
ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl();
ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(model, dataPaths);
String outputPath = StringUtil.notNullize(myArtifact.getOutputPath());
final CopyToDirectoryInstructionCreator instructionCreator = new CopyToDirectoryInstructionCreator(builder, outputPath);
LayoutElementBuildersRegistry.getInstance().generateInstructions(myArtifact, instructionCreator, context);
@@ -19,7 +19,7 @@ public class ArtifactBuilderService extends BuilderService {
@NotNull
@Override
public List<? extends TargetBuilder<?>> createBuilders() {
public List<? extends TargetBuilder<?,?>> createBuilders() {
return Collections.singletonList(new IncArtifactBuilder());
}
}
@@ -9,6 +9,7 @@ import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.*;
@@ -28,7 +29,7 @@ import java.util.*;
/**
* @author nik
*/
public class IncArtifactBuilder extends TargetBuilder<ArtifactBuildTarget> {
public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, ArtifactBuildTarget> {
public static final String BUILDER_NAME = "artifacts";
public IncArtifactBuilder() {
@@ -36,7 +37,9 @@ public class IncArtifactBuilder extends TargetBuilder<ArtifactBuildTarget> {
}
@Override
public void build(@NotNull ArtifactBuildTarget target, @NotNull CompileContext context) throws ProjectBuildException {
public void build(@NotNull ArtifactBuildTarget target,
@NotNull CompileContext context,
DirtyFilesHolder<ArtifactRootDescriptor, ArtifactBuildTarget> holder) throws ProjectBuildException {
JpsArtifact artifact = target.getArtifact();
if (StringUtil.isEmpty(artifact.getOutputPath())) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified"));
@@ -1,9 +1,14 @@
package org.jetbrains.jps.incremental.artifacts.builders;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator;
import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext;
import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
import java.util.Collection;
import java.util.Collections;
/**
* @author nik
*/
@@ -16,6 +21,10 @@ public abstract class LayoutElementBuilderService<E extends JpsPackagingElement>
public abstract void generateInstructions(E element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext);
public Collection<? extends BuildTarget<?>> getDependencies(@NotNull E element) {
return Collections.emptyList();
}
public final Class<E> getElementClass() {
return myElementClass;
}
@@ -4,6 +4,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ClassMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator;
import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext;
@@ -15,6 +21,8 @@ import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement;
import org.jetbrains.jps.service.JpsServiceManager;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -24,9 +32,9 @@ public class LayoutElementBuildersRegistry {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry");
private static class InstanceHolder {
static final LayoutElementBuildersRegistry ourInstance = new LayoutElementBuildersRegistry();
}
public static LayoutElementBuildersRegistry getInstance() {
return InstanceHolder.ourInstance;
}
@@ -53,16 +61,30 @@ public class LayoutElementBuildersRegistry {
generateInstructions(artifact.getRootElement(), creator, context);
}
public Collection<BuildTarget<?>> getDependencies(JpsPackagingElement element) {
LayoutElementBuilderService builder = getElementBuilder(element);
if (builder != null) {
//noinspection unchecked
return builder.getDependencies(element);
}
return Collections.emptyList();
}
private void generateInstructions(JpsPackagingElement layoutElement, ArtifactCompilerInstructionCreator instructionCreator,
ArtifactInstructionsBuilderContext builderContext) {
final LayoutElementBuilderService builder = myBuilders.get(layoutElement.getClass());
final LayoutElementBuilderService builder = getElementBuilder(layoutElement);
if (builder != null) {
//noinspection unchecked
builder.generateInstructions(layoutElement, instructionCreator, builderContext);
}
else {
}
private LayoutElementBuilderService<?> getElementBuilder(JpsPackagingElement layoutElement) {
final LayoutElementBuilderService<?> builder = myBuilders.get(layoutElement.getClass());
if (builder == null) {
LOG.error("Builder not found for artifact output layout element of class " + layoutElement.getClass());
}
return builder;
}
private void generateChildrenInstructions(JpsCompositePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator,
@@ -86,7 +108,7 @@ public class LayoutElementBuildersRegistry {
}
}
private static void generateModuleOutputInstructions(String outputUrl, ArtifactCompilerInstructionCreator creator) {
private static void generateModuleOutputInstructions(@Nullable String outputUrl, ArtifactCompilerInstructionCreator creator) {
if (outputUrl != null) {
creator.addDirectoryCopyInstructions(JpsPathUtil.urlToFile(outputUrl));
}
@@ -194,6 +216,15 @@ public class LayoutElementBuildersRegistry {
ArtifactInstructionsBuilderContext builderContext) {
generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator);
}
@Override
public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsProductionModuleOutputPackagingElement element) {
JpsModule module = element.getModuleReference().resolve();
if (module != null) {
return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION));
}
return Collections.emptyList();
}
}
private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService<JpsTestModuleOutputPackagingElement> {
@@ -207,6 +238,15 @@ public class LayoutElementBuildersRegistry {
ArtifactInstructionsBuilderContext builderContext) {
generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator);
}
@Override
public Collection<? extends BuildTarget<?>> getDependencies(@NotNull JpsTestModuleOutputPackagingElement element) {
JpsModule module = element.getModuleReference().resolve();
if (module != null) {
return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST));
}
return Collections.emptyList();
}
}
private class ComplexElementBuilder extends LayoutElementBuilderService<JpsComplexPackagingElement> {
@@ -1,5 +1,7 @@
package org.jetbrains.jps.incremental.artifacts.instructions;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.artifact.JpsArtifact;
/**
@@ -10,4 +12,8 @@ public interface ArtifactInstructionsBuilderContext {
boolean enterArtifact(JpsArtifact artifact);
void leaveArtifact(JpsArtifact artifact);
BuildDataPaths getDataPaths();
JpsModel getModel();
}
@@ -1,5 +1,7 @@
package org.jetbrains.jps.incremental.artifacts.instructions;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.artifact.JpsArtifact;
import java.util.HashSet;
@@ -10,11 +12,25 @@ import java.util.Set;
*/
public class ArtifactInstructionsBuilderContextImpl implements ArtifactInstructionsBuilderContext {
private final Set<JpsArtifact> myParentArtifacts;
private final JpsModel myModel;
private final BuildDataPaths myDataPaths;
public ArtifactInstructionsBuilderContextImpl() {
public ArtifactInstructionsBuilderContextImpl(JpsModel model, BuildDataPaths dataPaths) {
myModel = model;
myDataPaths = dataPaths;
myParentArtifacts = new HashSet<JpsArtifact>();
}
@Override
public JpsModel getModel() {
return myModel;
}
@Override
public BuildDataPaths getDataPaths() {
return myDataPaths;
}
@Override
public boolean enterArtifact(JpsArtifact artifact) {
return myParentArtifacts.add(artifact);
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.impl.BuildTargetChunk;
import org.jetbrains.jps.builders.java.dependencyView.Mappings;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.artifacts.ArtifactsBuildData;
import java.io.*;
@@ -20,7 +21,6 @@ import java.util.Map;
public class BuildDataManager implements StorageOwner {
private static final int VERSION = 12;
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
private static final String SRC_TO_OUTPUTS_STORAGE = "src-out";
private static final String SRC_TO_FORM_STORAGE = "src-form";
private static final String MAPPINGS_STORAGE = "mappings";
@@ -31,22 +31,22 @@ public class BuildDataManager implements StorageOwner {
private final ArtifactsBuildData myArtifactsBuildData;
private final ModuleOutputRootsLayout myOutputRootsLayout;
private final Mappings myMappings;
private final File myDataStorageRoot;
private final BuildDataPaths myDataPaths;
private final BuildTargetsState myTargetsState;
private final File myVersionFile;
public BuildDataManager(final File dataStorageRoot, BuildTargetsState targetsState, final boolean useMemoryTempCaches) throws IOException {
myDataStorageRoot = dataStorageRoot;
public BuildDataManager(final BuildDataPaths dataPaths, BuildTargetsState targetsState, final boolean useMemoryTempCaches) throws IOException {
myDataPaths = dataPaths;
myTargetsState = targetsState;
mySrcToFormMap = new SourceToFormMapping(new File(getSourceToFormsRoot(), "data"));
myOutputRootsLayout = new ModuleOutputRootsLayout(new File(getOutputsLayoutRoot(), "data"));
myMappings = new Mappings(getMappingsRoot(), useMemoryTempCaches);
myArtifactsBuildData = new ArtifactsBuildData(new File(dataStorageRoot, "artifacts"));
myVersionFile = new File(myDataStorageRoot, "version.dat");
myArtifactsBuildData = new ArtifactsBuildData(new File(dataPaths.getDataStorageRoot(), "artifacts"));
myVersionFile = new File(myDataPaths.getDataStorageRoot(), "version.dat");
}
private File getOutputsLayoutRoot() {
return new File(myDataStorageRoot, "output-roots");
return new File(myDataPaths.getDataStorageRoot(), "output-roots");
}
public SourceToOutputMappingImpl getSourceToOutputMap(final BuildTarget<?> target) throws IOException {
@@ -54,7 +54,7 @@ public class BuildDataManager implements StorageOwner {
synchronized (mySourceToOutputLock) {
mapping = mySourceToOutputs.get(target);
if (mapping == null) {
mapping = new SourceToOutputMappingImpl(new File(myTargetsState.getTargetDataRoot(target), "src-out" + File.separator + "data"));
mapping = new SourceToOutputMappingImpl(new File(myDataPaths.getTargetDataRoot(target), "src-out" + File.separator + "data"));
mySourceToOutputs.put(target, mapping);
}
}
@@ -204,16 +204,16 @@ public class BuildDataManager implements StorageOwner {
}
}
public File getSourceToFormsRoot() {
return new File(myDataStorageRoot, SRC_TO_FORM_STORAGE);
private File getSourceToFormsRoot() {
return new File(myDataPaths.getDataStorageRoot(), SRC_TO_FORM_STORAGE);
}
public File getMappingsRoot() {
return new File(myDataStorageRoot, MAPPINGS_STORAGE);
private File getMappingsRoot() {
return new File(myDataPaths.getDataStorageRoot(), MAPPINGS_STORAGE);
}
public File getDataStorageRoot() {
return myDataStorageRoot;
public BuildDataPaths getDataPaths() {
return myDataPaths;
}
private static void wipeStorage(File root, @Nullable AbstractStateStorage<?, ?> storage) {
@@ -75,6 +75,6 @@ public class BuildTargetConfiguration {
}
private File getConfigFile() {
return new File(myTargetsState.getTargetDataRoot(myTarget), "config.dat");
return new File(myTargetsState.getDataPaths().getTargetDataRoot(myTarget), "config.dat");
}
}
@@ -27,7 +27,7 @@ public class BuildTargetTypeState {
public BuildTargetTypeState(BuildTargetType<?> targetType, BuildTargetsState state) {
myTargetType = targetType;
myTargetsState = state;
myTargetsFile = new File(state.getTargetTypeDataRoot(targetType), "targets.dat");
myTargetsFile = new File(state.getDataPaths().getTargetTypeDataRoot(targetType), "targets.dat");
myConfigurations = new ConcurrentHashMap<BuildTarget<?>, BuildTargetConfiguration>();
myTargetIds = new HashMap<BuildTarget<?>, Integer>();
load();
@@ -2,12 +2,12 @@ package org.jetbrains.jps.incremental.storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.PathUtilRt;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.BuilderRegistry;
import org.jetbrains.jps.model.JpsModel;
@@ -20,14 +20,14 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class BuildTargetsState {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildTargetsState");
private final File myDataStorageRoot;
private final BuildDataPaths myDataPaths;
private AtomicInteger myMaxTargetId = new AtomicInteger(0);
private ConcurrentMap<BuildTargetType<?>, BuildTargetTypeState> myTypeStates = new ConcurrentHashMap<BuildTargetType<?>, BuildTargetTypeState>();
private JpsModel myModel;
private final BuildRootIndexImpl myBuildRootIndex;
public BuildTargetsState(File dataStorageRoot, JpsModel model, BuildRootIndexImpl buildRootIndex) {
myDataStorageRoot = dataStorageRoot;
public BuildTargetsState(BuildDataPaths dataPaths, JpsModel model, BuildRootIndexImpl buildRootIndex) {
myDataPaths = dataPaths;
myModel = model;
myBuildRootIndex = buildRootIndex;
File targetTypesFile = getTargetTypesFile();
@@ -49,16 +49,8 @@ public class BuildTargetsState {
}
}
public File getTargetTypeDataRoot(BuildTargetType<?> targetType) {
return new File(getTargetsDataRoot(), targetType.getTypeId());
}
public File getTargetsDataRoot() {
return new File(myDataStorageRoot, "targets");
}
private File getTargetTypesFile() {
return new File(getTargetsDataRoot(), "targetTypes.dat");
return new File(myDataPaths.getTargetsDataRoot(), "targetTypes.dat");
}
public void save() {
@@ -113,12 +105,8 @@ public class BuildTargetsState {
return myMaxTargetId.incrementAndGet();
}
public File getTargetDataRoot(BuildTarget<?> target) {
return new File(getTargetTypeDataRoot(target.getTargetType()), PathUtilRt.suggestFileName(target.getId(), true, true));
}
public void clean() {
FileUtil.delete(getTargetsDataRoot());
FileUtil.delete(myDataPaths.getTargetsDataRoot());
}
public JpsModel getModel() {
@@ -128,4 +116,8 @@ public class BuildTargetsState {
public BuildRootIndexImpl getBuildRootIndex() {
return myBuildRootIndex;
}
public BuildDataPaths getDataPaths() {
return myDataPaths;
}
}
@@ -6,6 +6,8 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.io.TestFileSystemBuilder;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.builders.impl.BuildRootIndexImpl;
@@ -125,10 +127,11 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(myModel);
ModuleExcludeIndex index = new ModuleExcludeIndexImpl(myModel);
IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(myModel);
BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, myModel, index, myDataStorageRoot, ignoredFileIndex);
BuildTargetsState targetsState = new BuildTargetsState(myDataStorageRoot, myModel, buildRootIndex);
BuildDataPaths dataPaths = new BuildDataPathsImpl(myDataStorageRoot);
BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, myModel, index, dataPaths, ignoredFileIndex);
BuildTargetsState targetsState = new BuildTargetsState(dataPaths, myModel, buildRootIndex);
ProjectTimestamps timestamps = new ProjectTimestamps(myDataStorageRoot, targetsState);
BuildDataManager dataManager = new BuildDataManager(myDataStorageRoot, targetsState, true);
BuildDataManager dataManager = new BuildDataManager(dataPaths, targetsState, true);
return new ProjectDescriptor(myModel, new BuildFSState(true), timestamps, dataManager, buildLoggingManager, index, targetsState,
targetIndex, buildRootIndex, ignoredFileIndex);
}
@@ -186,7 +189,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
return module;
}
protected void doRebuild() {
protected void rebuildAll() {
ProjectDescriptor descriptor = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new JavaBuilderLoggerImpl()));
try {
CompileScope scope = new CompileScopeImpl(true, BuilderRegistry.getInstance().getTargetTypes(), Collections.<BuildTarget<?>>emptySet(), Collections.<BuildTarget<?>,Set<File>>emptyMap());
@@ -39,7 +39,7 @@ abstract class JpsRebuildTestCase extends JpsBuildTestCase {
protected void rebuild() {
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath()))
doRebuild()
rebuildAll()
}
private File getOrCreateOutputDirectory() {
@@ -25,7 +25,7 @@ public class ResourceCopyingTest extends JpsBuildTestCase {
public void testSimple() {
String file = createFile("src/a.xml");
JpsModule m = addModule("m", PathUtil.getParentPath(file));
doRebuild();
rebuildAll();
assertOutput(m, fs().file("a.xml"));
}
public void testPackagePrefix() {
@@ -35,7 +35,7 @@ public class ResourceCopyingTest extends JpsBuildTestCase {
JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> typed = sourceRoot.asTyped(JavaSourceRootType.SOURCE);
assertNotNull(typed);
typed.getProperties().setData(new JavaSourceRootProperties("xxx"));
doRebuild();
rebuildAll();
assertOutput(m, fs().dir("xxx").file("a.xml"));
}
}
@@ -1,6 +1,8 @@
package org.jetbrains.jps.util;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.Set;
@@ -39,6 +41,23 @@ public class JpsPathUtil {
return url;
}
//todo[nik] copied from VfsUtil
@NotNull
public static String fixURLforIDEA(@NotNull String url ) {
int idx = url.indexOf(":/");
if( idx >= 0 && idx+2 < url.length() && url.charAt(idx+2) != '/' ) {
String prefix = url.substring(0, idx);
String suffix = url.substring(idx+2);
if (SystemInfoRt.isWindows) {
url = prefix+"://"+suffix;
} else {
url = prefix+":///"+suffix;
}
}
return url;
}
public static String pathToUrl(String path) {
return "file://" + path;
}
@@ -7,7 +7,9 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsElementFactory;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsModuleReference;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import java.util.List;
@@ -68,4 +70,13 @@ public class JpsFacetSerializer {
}
return null;
}
public static JpsModuleReference createModuleReference(String facetId) {
String moduleName = facetId.substring(0, facetId.indexOf('/'));
return JpsElementFactory.getInstance().createModuleReference(moduleName);
}
public static String getFacetId(final JpsModuleReference moduleReference, final String facetTypeId, final String facetName) {
return moduleReference.getModuleName() + "/" + facetTypeId + "/" + facetName;
}
}
@@ -22,8 +22,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.execution.ParametersListUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -254,64 +254,27 @@ public class ParametersList implements Cloneable {
}
/**
* <p>Joins list of parameters into single string, which may be then parsed back into list by {@link #parse(String)}.</p>
* <p/>
* <p>
* <strong>Conversion rules:</strong>
* <ul>
* <li>double quotes are escaped by backslash (<code>&#92;</code>);</li>
* <li>empty parameters parameters and parameters with spaces inside are surrounded with double quotes (<code>"</code>);</li>
* <li>parameters are separated by single whitespace.</li>
* </ul>
* </p>
* <p/>
* <p><strong>Examples:</strong></p>
* <p>
* <code>['a', 'b'] => 'a b'</code><br/>
* <code>['a="1 2"', 'b'] => '"a &#92;"1 2&#92;"" b'</code>
* </p>
*
* @param parameters a list of parameters to join.
* @return a string with parameters.
* @see ParametersListUtil#join(java.util.List)
*/
@NotNull
public static String join(@NotNull final List<String> parameters) {
return ParametersTokenizer.encode(parameters);
}
@NotNull
public static String join(final String... parameters) {
return ParametersTokenizer.encode(Arrays.asList(parameters));
return ParametersListUtil.join(parameters);
}
/**
* <p>Converts single parameter string (as created by {@link #join(java.util.List)}) into list of parameters.</p>
* <p/>
* <p>
* <strong>Conversion rules:</strong>
* <ul>
* <li>starting/whitespaces are trimmed;</li>
* <li>parameters are split by whitespaces, whitespaces itself are dropped</li>
* <li>parameters inside double quotes (<code>"a b"</code>) are kept as single one;</li>
* <li>double quotes are dropped, escaped double quotes (<code>&#92;"</code>) are un-escaped.</li>
* </ul>
* </p>
* <p/>
* <p><strong>Examples:</strong></p>
* <p>
* <code>' a b ' => ['a', 'b']</code><br/>
* <code>'a="1 2" b' => ['a=1 2', 'b']</code><br/>
* <code>'a " " b' => ['a', ' ', 'b']</code><br/>
* <code>'"a &#92;"1 2&#92;"" b' => ['a="1 2"', 'b']</code>
* </p>
*
* @param string parameter string to split.
* @return array of parameters.
* @see ParametersListUtil#join(java.util.List)
*/
@NotNull
public static String join(final String... parameters) {
return ParametersListUtil.join(parameters);
}
/**
* @see ParametersListUtil#parseToArray(String)
*/
@NotNull
public static String[] parse(@NotNull final String string) {
final List<String> params = ParametersTokenizer.decode(string);
return ArrayUtil.toStringArray(params);
return ParametersListUtil.parseToArray(string);
}
public String expandMacros(String text) {
@@ -356,84 +319,4 @@ public class ParametersList implements Cloneable {
return myParameters.toString();
}
private static class ParametersTokenizer {
private ParametersTokenizer() {
}
@NotNull
public static String encode(@NotNull final List<String> parameters) {
final StringBuilder buffer = new StringBuilder();
for (final String parameter : parameters) {
if (buffer.length() > 0) {
buffer.append(' ');
}
buffer.append(encode(parameter));
}
return buffer.toString();
}
@NotNull
public static String encode(@NotNull String parameter) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append(parameter);
StringUtil.escapeQuotes(builder);
if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0 || StringUtil.indexOf(builder, '|') >= 0) {
StringUtil.quote(builder);
}
return builder.toString();
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
@NotNull
public static List<String> decode(@NotNull String parameterString) {
parameterString = parameterString.trim();
final ArrayList<String> params = ContainerUtil.newArrayList();
final StringBuilder token = new StringBuilder(128);
boolean inQuotes = false;
boolean escapedQuote = false;
boolean nonEmpty = false;
for (int i = 0; i < parameterString.length(); i++) {
final char ch = parameterString.charAt(i);
if (ch == '\"') {
if (!escapedQuote) {
inQuotes = !inQuotes;
nonEmpty = true;
continue;
}
escapedQuote = false;
}
else if (Character.isWhitespace(ch)) {
if (!inQuotes) {
if (token.length() > 0 || nonEmpty) {
params.add(token.toString());
token.setLength(0);
nonEmpty = false;
}
continue;
}
}
else if (ch == '\\') {
if (i < parameterString.length() - 1 && parameterString.charAt(i + 1) == '"') {
escapedQuote = true;
continue;
}
}
token.append(ch);
}
if (token.length() > 0 || nonEmpty) {
params.add(token.toString());
}
return params;
}
}
}
@@ -0,0 +1,171 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.execution;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author nik
*/
public class ParametersListUtil {
/**
* <p>Joins list of parameters into single string, which may be then parsed back into list by {@link #parseToArray(String)}.</p>
* <p/>
* <p>
* <strong>Conversion rules:</strong>
* <ul>
* <li>double quotes are escaped by backslash (<code>&#92;</code>);</li>
* <li>empty parameters parameters and parameters with spaces inside are surrounded with double quotes (<code>"</code>);</li>
* <li>parameters are separated by single whitespace.</li>
* </ul>
* </p>
* <p/>
* <p><strong>Examples:</strong></p>
* <p>
* <code>['a', 'b'] => 'a b'</code><br/>
* <code>['a="1 2"', 'b'] => '"a &#92;"1 2&#92;"" b'</code>
* </p>
*
* @param parameters a list of parameters to join.
* @return a string with parameters.
*/
@NotNull
public static String join(@NotNull final List<String> parameters) {
return encode(parameters);
}
@NotNull
public static String join(final String... parameters) {
return encode(Arrays.asList(parameters));
}
/**
* @see #parse(String)
*/
@NotNull
public static String[] parseToArray(@NotNull final String string) {
final List<String> params = parse(string);
return ArrayUtil.toStringArray(params);
}
/**
* <p>Converts single parameter string (as created by {@link #join(java.util.List)}) into list of parameters.</p>
* <p/>
* <p>
* <strong>Conversion rules:</strong>
* <ul>
* <li>starting/whitespaces are trimmed;</li>
* <li>parameters are split by whitespaces, whitespaces itself are dropped</li>
* <li>parameters inside double quotes (<code>"a b"</code>) are kept as single one;</li>
* <li>double quotes are dropped, escaped double quotes (<code>&#92;"</code>) are un-escaped.</li>
* </ul>
* </p>
* <p/>
* <p><strong>Examples:</strong></p>
* <p>
* <code>' a b ' => ['a', 'b']</code><br/>
* <code>'a="1 2" b' => ['a=1 2', 'b']</code><br/>
* <code>'a " " b' => ['a', ' ', 'b']</code><br/>
* <code>'"a &#92;"1 2&#92;"" b' => ['a="1 2"', 'b']</code>
* </p>
*
* @param string parameter string to split.
* @return array of parameters.
*/
@NotNull
public static List<String> parse(@NotNull String parameterString) {
parameterString = parameterString.trim();
final ArrayList<String> params = ContainerUtilRt.newArrayList();
final StringBuilder token = new StringBuilder(128);
boolean inQuotes = false;
boolean escapedQuote = false;
boolean nonEmpty = false;
for (int i = 0; i < parameterString.length(); i++) {
final char ch = parameterString.charAt(i);
if (ch == '\"') {
if (!escapedQuote) {
inQuotes = !inQuotes;
nonEmpty = true;
continue;
}
escapedQuote = false;
}
else if (Character.isWhitespace(ch)) {
if (!inQuotes) {
if (token.length() > 0 || nonEmpty) {
params.add(token.toString());
token.setLength(0);
nonEmpty = false;
}
continue;
}
}
else if (ch == '\\') {
if (i < parameterString.length() - 1 && parameterString.charAt(i + 1) == '"') {
escapedQuote = true;
continue;
}
}
token.append(ch);
}
if (token.length() > 0 || nonEmpty) {
params.add(token.toString());
}
return params;
}
@NotNull
private static String encode(@NotNull final List<String> parameters) {
final StringBuilder buffer = new StringBuilder();
for (final String parameter : parameters) {
if (buffer.length() > 0) {
buffer.append(' ');
}
buffer.append(encode(parameter));
}
return buffer.toString();
}
@NotNull
private static String encode(@NotNull String parameter) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append(parameter);
StringUtil.escapeQuotes(builder);
if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0 || StringUtil.indexOf(builder, '|') >= 0) {
StringUtil.quote(builder);
}
return builder.toString();
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
}
@@ -5,6 +5,7 @@ import org.jetbrains.jps.builders.AdditionalRootsProviderService;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import java.io.File;
@@ -22,9 +23,9 @@ public class AndroidAdditionalRootProviderService extends AdditionalRootsProvide
@NotNull
@Override
public List<JavaSourceRootDescriptor> getAdditionalRoots(@NotNull BuildTarget<JavaSourceRootDescriptor> target, File dataStorageRoot) {
public List<JavaSourceRootDescriptor> getAdditionalRoots(@NotNull BuildTarget<JavaSourceRootDescriptor> target, BuildDataPaths dataPaths) {
ModuleBuildTarget buildTarget = (ModuleBuildTarget)target;
final File generatedSourcesRoot = AndroidJpsUtil.getGeneratedSourcesStorage(buildTarget.getModule(), dataStorageRoot);
final File generatedSourcesRoot = AndroidJpsUtil.getGeneratedSourcesStorage(buildTarget.getModule(), dataPaths);
final List<JavaSourceRootDescriptor> result = new ArrayList<JavaSourceRootDescriptor>();
addRoot(result, buildTarget, new File(generatedSourcesRoot, AndroidJpsUtil.AAPT_GENERATED_SOURCE_ROOT_NAME));
@@ -28,7 +28,7 @@ public class AndroidBuilderService extends BuilderService {
@NotNull
@Override
public List<? extends TargetBuilder<?>> createBuilders() {
public List<? extends TargetBuilder<?,?>> createBuilders() {
return Arrays.asList(new AndroidDexBuilder(),
new AndroidPackagingBuilder());
}
@@ -33,6 +33,8 @@ import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget;
import org.jetbrains.jps.android.model.JpsAndroidModuleExtension;
import org.jetbrains.jps.android.model.JpsAndroidSdkProperties;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.*;
@@ -53,7 +55,7 @@ import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidDexBuilder extends TargetBuilder<AndroidProjectBuildTarget> {
public class AndroidDexBuilder extends TargetBuilder<BuildRootDescriptor,AndroidProjectBuildTarget> {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.android.AndroidDexBuilder");
@NonNls private static final String BUILDER_NAME = "android-dex";
@@ -66,7 +68,8 @@ public class AndroidDexBuilder extends TargetBuilder<AndroidProjectBuildTarget>
}
@Override
public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context) throws ProjectBuildException {
public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context,
DirtyFilesHolder<BuildRootDescriptor, AndroidProjectBuildTarget> holder) throws ProjectBuildException {
if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.DEX && AndroidJpsUtil.isLightBuild(context)) {
return;
}
@@ -83,7 +86,7 @@ public class AndroidDexBuilder extends TargetBuilder<AndroidProjectBuildTarget>
}
private static void doBuild(CompileContext context) throws IOException, ProjectBuildException {
final File root = context.getProjectDescriptor().dataManager.getDataStorageRoot();
final File root = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
AndroidFileSetStorage dexStateStorage = null;
AndroidFileSetStorage proguardStateStorage = null;
@@ -16,6 +16,7 @@ import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.util.JpsPathUtil;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.ProjectPaths;
@@ -153,7 +154,7 @@ public class AndroidJpsUtil {
@NotNull
public static File getDirectoryForIntermediateArtifacts(@NotNull CompileContext context,
@NotNull JpsModule module) {
final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataStorageRoot(), ANDROID_STORAGE_DIR);
final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), ANDROID_STORAGE_DIR);
return new File(new File(androidStorage, INTERMEDIATE_ARTIFACTS_STORAGE), module.getName());
}
@@ -520,7 +521,7 @@ public class AndroidJpsUtil {
@NotNull
public static File getResourcesCacheDir(@NotNull CompileContext context, @NotNull JpsModule module) {
final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataStorageRoot(), ANDROID_STORAGE_DIR);
final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), ANDROID_STORAGE_DIR);
return new File(new File(androidStorage, RESOURCE_CACHE_STORAGE), module.getName());
}
@@ -585,19 +586,19 @@ public class AndroidJpsUtil {
@NotNull
public static File getGeneratedSourcesStorage(@NotNull JpsModule module, BuildDataManager dataManager) {
return getGeneratedSourcesStorage(module, dataManager.getDataStorageRoot());
return getGeneratedSourcesStorage(module, dataManager.getDataPaths());
}
@NotNull
public static File getGeneratedSourcesStorage(@NotNull JpsModule module, final File dataStorageRoot) {
final File androidStorageRoot = new File(dataStorageRoot, ANDROID_STORAGE_DIR);
public static File getGeneratedSourcesStorage(@NotNull JpsModule module, final BuildDataPaths dataPaths) {
final File androidStorageRoot = new File(dataPaths.getDataStorageRoot(), ANDROID_STORAGE_DIR);
final File generatedSourcesRoot = new File(androidStorageRoot, GENERATED_SOURCES_FOLDER_NAME);
return new File(generatedSourcesRoot, module.getName());
}
@NotNull
public static File getGeneratedResourcesStorage(@NotNull JpsModule module, BuildDataManager dataManager) {
final File dataStorageRoot = dataManager.getDataStorageRoot();
final File dataStorageRoot = dataManager.getDataPaths().getDataStorageRoot();
final File androidStorageRoot = new File(dataStorageRoot, ANDROID_STORAGE_DIR);
final File generatedSourcesRoot = new File(androidStorageRoot, GENERATED_RESOURCES_DIR_NAME);
return new File(generatedSourcesRoot, module.getName());
@@ -18,6 +18,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget;
import org.jetbrains.jps.android.model.JpsAndroidModuleExtension;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
@@ -38,7 +40,7 @@ import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidPackagingBuilder extends TargetBuilder<AndroidProjectBuildTarget> {
public class AndroidPackagingBuilder extends TargetBuilder<BuildRootDescriptor, AndroidProjectBuildTarget> {
@NonNls private static final String BUILDER_NAME = "android-packager";
@NonNls private static final String RELEASE_SUFFIX = ".release";
@NonNls private static final String UNSIGNED_SUFFIX = ".unsigned";
@@ -58,7 +60,8 @@ public class AndroidPackagingBuilder extends TargetBuilder<AndroidProjectBuildTa
}
@Override
public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context) throws ProjectBuildException {
public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context,
DirtyFilesHolder<BuildRootDescriptor, AndroidProjectBuildTarget> holder) throws ProjectBuildException {
if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.PACKAGING || AndroidJpsUtil.isLightBuild(context)) {
return;
}
@@ -123,7 +126,7 @@ public class AndroidPackagingBuilder extends TargetBuilder<AndroidProjectBuildTa
@NotNull Collection<JpsModule> modules,
@NotNull Map<JpsModule, AndroidFileSetState> module2state) throws IOException {
boolean success = true;
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot();
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
final AndroidFileSetStorage storage = new AndroidFileSetStorage(dataStorageRoot, "resource_caching");
try {
@@ -212,7 +215,7 @@ public class AndroidPackagingBuilder extends TargetBuilder<AndroidProjectBuildTa
@NotNull Map<JpsModule, File> manifestFiles) throws IOException {
boolean success = true;
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot();
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
final boolean releaseBuild = AndroidJpsUtil.isReleaseBuild(context);
AndroidFileSetStorage resourcesStorage = null;
AndroidFileSetStorage assetsStorage = null;
@@ -292,7 +295,7 @@ public class AndroidPackagingBuilder extends TargetBuilder<AndroidProjectBuildTa
private static boolean doPackaging(@NotNull CompileContext context, @NotNull Collection<JpsModule> modules) throws IOException {
final boolean release = AndroidJpsUtil.isReleaseBuild(context);
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot();
final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
boolean success = true;
@@ -162,7 +162,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder {
success = false;
}
final File dataStorageRoot = dataManager.getDataStorageRoot();
final File dataStorageRoot = dataManager.getDataPaths().getDataStorageRoot();
final AndroidAptStateStorage aptStorage = new AndroidAptStateStorage(dataStorageRoot);
try {
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.android.AndroidJpsUtil;
import org.jetbrains.jps.builders.*;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
@@ -81,7 +82,10 @@ public class AndroidProjectBuildTarget extends BuildTarget<BuildRootDescriptor>
@NotNull
@Override
public List<BuildRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) {
public List<BuildRootDescriptor> computeRootDescriptors(JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths) {
return Collections.emptyList();
}
@@ -32,6 +32,6 @@ public class JpsMavenJavaBuildingTest extends JpsBuildTestCase {
FileUtil.copyDir(srcDir, workDir);
addJdk("1.6");
loadProject(workDir.getAbsolutePath());
doRebuild();
rebuildAll();
}
}
@@ -16,5 +16,5 @@ public abstract class JpsUiDesignerExtensionService {
@Nullable
public abstract JpsUiDesignerConfiguration getUiDesignerConfiguration(@NotNull JpsProject project);
public abstract void setUiDesignerConfiguration(@NotNull JpsProject project, @Nullable JpsUiDesignerConfiguration configuration);
public abstract void setUiDesignerConfiguration(@NotNull JpsProject project, @NotNull JpsUiDesignerConfiguration configuration);
}
@@ -22,6 +22,9 @@ public class JpsUiDesignerConfigurationSerializer extends JpsProjectExtensionSer
@Override
public void loadExtension(@NotNull JpsProject element, @NotNull Element componentTag) {
JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState state = XmlSerializer.deserialize(componentTag, JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState.class);
if (state == null) {
state = new JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState();
}
JpsUiDesignerExtensionService.getInstance().setUiDesignerConfiguration(element, new JpsUiDesignerConfigurationImpl(state));
}
@@ -17,7 +17,7 @@ public class JpsUiDesignerExtensionServiceImpl extends JpsUiDesignerExtensionSer
}
@Override
public void setUiDesignerConfiguration(@NotNull JpsProject project, @Nullable JpsUiDesignerConfiguration configuration) {
public void setUiDesignerConfiguration(@NotNull JpsProject project, @NotNull JpsUiDesignerConfiguration configuration) {
project.getContainer().setChild(JpsUiDesignerConfigurationImpl.ROLE, configuration);
}
}