diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 52c769b62f39..34d856f83505 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -21,6 +21,7 @@ import org.jetbrains.jps.idea.IdeaProjectLoader; import org.jetbrains.jps.idea.SystemOutErrorReporter; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.artifacts.ArtifactSourceTimestampStorage; +import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootDescriptor; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.fs.RootDescriptor; @@ -31,7 +32,6 @@ import org.jetbrains.jps.incremental.storage.Timestamps; import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; -import org.jetbrains.jps.model.artifact.JpsArtifactService; import org.jetbrains.jps.model.java.JpsJavaLibraryType; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsOrderRootType; @@ -618,10 +618,10 @@ final class BuildSession implements Runnable, CanceledStatus { final Timestamps timestamps = pd.timestamps.getStorage(); Set artifacts = new HashSet(); if (artifactNames.isEmpty() && buildType == BuildType.PROJECT_REBUILD) { - artifacts.addAll(JpsArtifactService.getInstance().getArtifacts(pd.jpsProject)); + artifacts.addAll(JpsBuilderArtifactService.getInstance().getArtifacts(pd.jpsModel, false)); } else { - for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(pd.jpsProject)) { + for (JpsArtifact artifact : JpsBuilderArtifactService.getInstance().getArtifacts(pd.jpsModel, false)) { if (artifactNames.contains(artifact.getName()) && !StringUtil.isEmpty(artifact.getOutputPath())) { artifacts.add(artifact); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactRootsIndex.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactRootsIndex.java index 09710f334ae4..0512266cfff9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactRootsIndex.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactRootsIndex.java @@ -13,7 +13,6 @@ import org.jetbrains.jps.incremental.artifacts.instructions.*; import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; -import org.jetbrains.jps.model.artifact.JpsArtifactService; import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; import java.io.File; @@ -30,7 +29,7 @@ public class ArtifactRootsIndex { myRootToDescriptorMap = new MultiMap(); myInstructions = new HashMap(); ArtifactsBuildData data = manager.getArtifactsBuildData(); - for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(model.getProject())) { + for (JpsArtifact artifact : JpsBuilderArtifactService.getInstance().getArtifacts(model, true)) { int artifactId = data.getArtifactId(artifact); ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(rootsIndex, project.getIgnoredFilePatterns(), artifactId, artifact.getName()); final JpsCompositePackagingElement rootElement = artifact.getRootElement(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java index 353b7bf33334..b3aa5697420d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java @@ -15,8 +15,8 @@ import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.messages.BuildMessage; import org.jetbrains.jps.incremental.messages.CompilerMessage; import org.jetbrains.jps.incremental.messages.ProgressMessage; +import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; -import org.jetbrains.jps.model.artifact.JpsArtifactService; import java.io.File; import java.io.IOException; @@ -35,14 +35,17 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { @Override public void build(CompileContext context) throws ProjectBuildException { Set affected = new HashSet(); - for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(context.getProjectDescriptor().jpsProject)) { + JpsBuilderArtifactService artifactService = JpsBuilderArtifactService.getInstance(); + JpsModel model = context.getProjectDescriptor().jpsModel; + for (JpsArtifact artifact : artifactService.getArtifacts(model, false)) { if (context.getScope().isAffected(artifact)) { affected.add(artifact); } } + affected.addAll(artifactService.getSyntheticArtifacts(model)); final Set toBuild = ArtifactSorter.addIncludedArtifacts(affected); - final ArtifactSorter sorter = new ArtifactSorter(context.getProjectDescriptor().jpsModel); + final ArtifactSorter sorter = new ArtifactSorter(model); final Map selfIncludingNameMap = sorter.getArtifactToSelfIncludingNameMap(); for (JpsArtifact artifact : sorter.getArtifactsSortedByInclusion()) { context.checkCanceled(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java new file mode 100644 index 000000000000..a4079dc2bc19 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsBuilderArtifactService.java @@ -0,0 +1,22 @@ +package org.jetbrains.jps.incremental.artifacts; + +import org.jetbrains.jps.incremental.artifacts.impl.JpsBuilderArtifactServiceImpl; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; + +import java.util.Collection; + +/** + * @author nik + */ +public abstract class JpsBuilderArtifactService { + private static JpsBuilderArtifactService ourInstance = new JpsBuilderArtifactServiceImpl(); + + public static JpsBuilderArtifactService getInstance() { + return ourInstance; + } + + public abstract Collection getArtifacts(JpsModel model, boolean includeSynthetic); + + public abstract Collection getSyntheticArtifacts(JpsModel model); +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java new file mode 100644 index 000000000000..6179e3840d5e --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/JpsSyntheticArtifactProvider.java @@ -0,0 +1,15 @@ +package org.jetbrains.jps.incremental.artifacts; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; + +import java.util.List; + +/** + * @author nik + */ +public abstract class JpsSyntheticArtifactProvider { + @NotNull + public abstract List createArtifacts(@NotNull JpsModel model); +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java index 70103e226bcf..c498350ee48a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java @@ -24,10 +24,9 @@ import com.intellij.util.graph.GraphGenerator; import gnu.trove.TIntArrayList; import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService; import org.jetbrains.jps.model.JpsModel; -import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.artifact.JpsArtifact; -import org.jetbrains.jps.model.artifact.JpsArtifactService; import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement; import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; @@ -147,7 +146,7 @@ public class ArtifactSorter { } private GraphGenerator createArtifactsGraph() { - return GraphGenerator.create(CachingSemiGraph.create(new ArtifactsGraph(myModel.getProject()))); + return GraphGenerator.create(CachingSemiGraph.create(new ArtifactsGraph(myModel))); } private static void processIncludedArtifacts(JpsArtifact artifact, final Consumer consumer) { @@ -169,8 +168,8 @@ public class ArtifactSorter { private static class ArtifactsGraph implements GraphGenerator.SemiGraph { private final Set myArtifactNodes; - public ArtifactsGraph(final JpsProject project) { - myArtifactNodes = new LinkedHashSet(JpsArtifactService.getInstance().getArtifacts(project)); + public ArtifactsGraph(final JpsModel model) { + myArtifactNodes = new LinkedHashSet(JpsBuilderArtifactService.getInstance().getArtifacts(model, true)); } @Override diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java new file mode 100644 index 000000000000..6bf73a502630 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsBuilderArtifactServiceImpl.java @@ -0,0 +1,52 @@ +package org.jetbrains.jps.incremental.artifacts.impl; + +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService; +import org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; +import org.jetbrains.jps.model.artifact.impl.JpsArtifactKind; +import org.jetbrains.jps.model.impl.JpsElementCollectionImpl; +import org.jetbrains.jps.model.impl.JpsElementCollectionKind; +import org.jetbrains.jps.service.JpsServiceManager; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author nik + */ +public class JpsBuilderArtifactServiceImpl extends JpsBuilderArtifactService { + private static final JpsElementCollectionKind SYNTHETIC_ARTIFACTS = new JpsElementCollectionKind(JpsArtifactKind.INSTANCE); + + @Override + public Collection getArtifacts(JpsModel model, boolean includeSynthetic) { + List artifacts = JpsArtifactService.getInstance().getArtifacts(model.getProject()); + if (!includeSynthetic) { + return artifacts; + } + return ContainerUtil.concat(artifacts, getSyntheticArtifacts(model)); + } + + public List getSyntheticArtifacts(final JpsModel model) { + JpsElementCollectionImpl artifactsCollection = model.getProject().getContainer().getChild(SYNTHETIC_ARTIFACTS); + if (artifactsCollection == null) { + List artifactList = computeSyntheticArtifacts(model); + artifactsCollection = model.getProject().getContainer().setChild(SYNTHETIC_ARTIFACTS); + for (JpsArtifact artifact : artifactList) { + artifactsCollection.addChild(artifact); + } + } + return artifactsCollection.getElements(); + } + + private static List computeSyntheticArtifacts(JpsModel model) { + List artifacts = new ArrayList(); + for (JpsSyntheticArtifactProvider provider : JpsServiceManager.getInstance().getExtensions(JpsSyntheticArtifactProvider.class)) { + artifacts.addAll(provider.createArtifacts(model)); + } + return artifacts; + } +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java index 46fd347ed472..25538d309082 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java @@ -16,6 +16,8 @@ public abstract class JpsArtifactService { return JpsServiceManager.getInstance().getService(JpsArtifactService.class); } + public abstract JpsArtifact createArtifact(String name, JpsCompositePackagingElement rootElement, JpsArtifactType type); + public abstract List getArtifacts(@NotNull JpsProject project); public abstract JpsArtifact addArtifact(@NotNull JpsProject project, diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java index 9ea13f9adfbd..bee3a0b15f4c 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java @@ -10,6 +10,10 @@ import org.jetbrains.jps.service.JpsServiceManager; * @author nik */ public abstract class JpsPackagingElementFactory { + public abstract JpsCompositePackagingElement getOrCreateDirectory(@NotNull JpsCompositePackagingElement root, @NotNull String path); + + public abstract JpsCompositePackagingElement getOrCreateArchive(@NotNull JpsCompositePackagingElement root, @NotNull String path); + public static JpsPackagingElementFactory getInstance() { return JpsServiceManager.getInstance().getService(JpsPackagingElementFactory.class); } diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java new file mode 100644 index 000000000000..a8cce1f73c09 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaDependenciesEnumerator.java @@ -0,0 +1,23 @@ +package org.jetbrains.jps.model.java; + +import org.jetbrains.jps.model.module.JpsDependenciesEnumerator; + +/** + * @author nik + */ +public interface JpsJavaDependenciesEnumerator extends JpsDependenciesEnumerator { + JpsJavaDependenciesEnumerator productionOnly(); + JpsJavaDependenciesEnumerator compileOnly(); + JpsJavaDependenciesEnumerator runtimeOnly(); + JpsJavaDependenciesEnumerator exportedOnly(); + + JpsJavaDependenciesEnumerator withoutLibraries(); + JpsJavaDependenciesEnumerator withoutDepModules(); + JpsJavaDependenciesEnumerator withoutSdk(); + JpsJavaDependenciesEnumerator withoutModuleSourceEntries(); + + @Override + JpsJavaDependenciesEnumerator recursively(); + + JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java index 32d2bb317fe4..2a36b5075713 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java @@ -25,6 +25,12 @@ public abstract class JpsJavaExtensionService { return JpsServiceManager.getInstance().getService(JpsJavaExtensionService.class); } + public static JpsJavaDependenciesEnumerator dependencies(JpsModule module) { + return getInstance().enumerateDependencies(module); + } + + protected abstract JpsJavaDependenciesEnumerator enumerateDependencies(JpsModule module); + @NotNull public abstract JpsJavaProjectExtension getOrCreateProjectExtension(@NotNull JpsProject project); diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java new file mode 100644 index 000000000000..aa7d98280b9b --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependenciesEnumerator.java @@ -0,0 +1,18 @@ +package org.jetbrains.jps.model.module; + +import org.jetbrains.jps.model.library.JpsLibrary; + +import java.util.Set; + +/** + * @author nik + */ +public interface JpsDependenciesEnumerator { + JpsDependenciesEnumerator withoutLibraries(); + JpsDependenciesEnumerator withoutDepModules(); + JpsDependenciesEnumerator withoutSdk(); + JpsDependenciesEnumerator withoutModuleSourceEntries(); + JpsDependenciesEnumerator recursively(); + Set getModules(); + Set getLibraries(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java index 373784efe42e..75bdfdab51bb 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java +++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsDependencyElement.java @@ -7,4 +7,6 @@ import org.jetbrains.jps.model.JpsCompositeElement; */ public interface JpsDependencyElement extends JpsCompositeElement { void remove(); + + JpsModule getContainingModule(); } diff --git a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java index e99e0a175a64..0e9692e5b44c 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java +++ b/jps/model-api/src/org/jetbrains/jps/model/module/JpsModule.java @@ -64,4 +64,9 @@ public interface JpsModule extends JpsNamedElement, JpsReferenceableElement getModuleType(); + + @NotNull + JpsElementProperties getProperties(); } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java index 257280671159..2bfd2817d455 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java @@ -25,10 +25,15 @@ public class JpsArtifactServiceImpl extends JpsArtifactService { @Override public JpsArtifact addArtifact(@NotNull JpsProject project, @NotNull String name, @NotNull JpsCompositePackagingElement rootElement, @NotNull JpsArtifactType type) { - JpsArtifact artifact = new JpsArtifactImpl(name, rootElement, type); + JpsArtifact artifact = createArtifact(name, rootElement, type); return project.getContainer().getOrSetChild(JpsArtifactKind.ARTIFACT_COLLECTION_KIND).addChild(artifact); } + @Override + public JpsArtifact createArtifact(String name, JpsCompositePackagingElement rootElement, JpsArtifactType type) { + return new JpsArtifactImpl(name, rootElement, type); + } + @Override public JpsArtifactReference createReference(@NotNull String artifactName) { return new JpsArtifactReferenceImpl(artifactName); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java index 62c0de6379cc..a293c948c020 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java @@ -35,6 +35,16 @@ public class JpsPackagingElementFactoryImpl extends JpsPackagingElementFactory { return root; } + @Override + public JpsCompositePackagingElement getOrCreateDirectory(@NotNull JpsCompositePackagingElement root, @NotNull String path) { + return getOrCreateDirectoryOrArchive(root, path, true); + } + + @Override + public JpsCompositePackagingElement getOrCreateArchive(@NotNull JpsCompositePackagingElement root, @NotNull String path) { + return getOrCreateDirectoryOrArchive(root, path, false); + } + @NotNull private JpsCompositePackagingElement getOrCreateDirectoryOrArchive(@NotNull JpsCompositePackagingElement root, @NotNull @NonNls String path, final boolean directory) { diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java new file mode 100644 index 000000000000..f323389083cd --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaDependenciesEnumeratorImpl.java @@ -0,0 +1,84 @@ +package org.jetbrains.jps.model.java.impl; + +import org.jetbrains.jps.model.java.*; +import org.jetbrains.jps.model.module.JpsDependencyElement; +import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.impl.JpsDependenciesEnumeratorBase; + +import java.util.Collection; + +/** + * @author nik + */ +public class JpsJavaDependenciesEnumeratorImpl extends JpsDependenciesEnumeratorBase implements JpsJavaDependenciesEnumerator { + private boolean myProductionOnly; + private boolean myRuntimeOnly; + private boolean myCompileOnly; + private boolean myExportedOnly; + private JpsJavaClasspathKind myClasspathKind; + + public JpsJavaDependenciesEnumeratorImpl(Collection rootModules) { + super(rootModules); + } + + @Override + public JpsJavaDependenciesEnumerator productionOnly() { + myProductionOnly = true; + return this; + } + + @Override + public JpsJavaDependenciesEnumerator compileOnly() { + myCompileOnly = true; + return this; + } + + @Override + public JpsJavaDependenciesEnumerator runtimeOnly() { + myRuntimeOnly = true; + return this; + } + + @Override + public JpsJavaDependenciesEnumerator exportedOnly() { + myExportedOnly = true; + return this; + } + + @Override + public JpsJavaDependenciesEnumerator includedIn(JpsJavaClasspathKind classpathKind) { + myClasspathKind = classpathKind; + return this; + } + + @Override + protected JpsJavaDependenciesEnumeratorImpl self() { + return this; + } + + @Override + protected boolean shouldProcess(JpsDependencyElement element) { + boolean exported = false; + JpsJavaDependencyExtension extension = JpsJavaExtensionService.getInstance().getDependencyExtension(element); + if (extension != null) { + exported = extension.isExported(); + JpsJavaDependencyScope scope = extension.getScope(); + if (myCompileOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE) && !scope.isIncludedIn(JpsJavaClasspathKind.TEST_COMPILE) + || myRuntimeOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME) && !scope.isIncludedIn(JpsJavaClasspathKind.TEST_RUNTIME) + || myClasspathKind != null && !scope.isIncludedIn(myClasspathKind)) { + return false; + } + if (myProductionOnly) { + if (!scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE) && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME) + || myCompileOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_COMPILE) + || myRuntimeOnly && !scope.isIncludedIn(JpsJavaClasspathKind.PRODUCTION_RUNTIME)) { + return false; + } + } + } + if (!exported) { + if (myExportedOnly) return false; + } + return true; + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java index d1b084eaa6b0..4af61797e0c5 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java @@ -12,6 +12,7 @@ import org.jetbrains.jps.model.module.JpsModuleReference; import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -136,4 +137,9 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService { public JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference) { return new JpsTestModuleOutputPackagingElementImpl(moduleReference); } + + @Override + protected JpsJavaDependenciesEnumerator enumerateDependencies(JpsModule module) { + return new JpsJavaDependenciesEnumeratorImpl(Collections.singletonList(module)); + } } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java new file mode 100644 index 000000000000..3c830e37e5be --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependenciesEnumeratorBase.java @@ -0,0 +1,159 @@ +package org.jetbrains.jps.model.module.impl; + +import com.intellij.util.CollectConsumer; +import com.intellij.util.Consumer; +import com.intellij.util.Processor; +import gnu.trove.THashSet; +import org.jetbrains.jps.model.library.JpsLibrary; +import org.jetbrains.jps.model.module.*; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * @author nik + */ +public abstract class JpsDependenciesEnumeratorBase implements JpsDependenciesEnumerator { + private boolean myWithoutSdk; + private boolean myWithoutLibraries; + protected boolean myWithoutDepModules; + private boolean myWithoutModuleSourceEntries; + protected boolean myRecursively; + protected final Collection myRootModules; + + protected JpsDependenciesEnumeratorBase(Collection rootModules) { + myRootModules = rootModules; + } + + @Override + public Self withoutLibraries() { + myWithoutLibraries = true; + return self(); + } + + @Override + public Self withoutDepModules() { + myWithoutDepModules = true; + return self(); + } + + @Override + public Self withoutSdk() { + myWithoutSdk = true; + return self(); + } + + @Override + public Self withoutModuleSourceEntries() { + myWithoutModuleSourceEntries = true; + return self(); + } + + @Override + public Self recursively() { + myRecursively = true; + return self(); + } + + protected abstract Self self(); + + @Override + public Set getModules() { + Set result = new HashSet(); + processModules(new CollectConsumer(result)); + return result; + } + + public void processModules(final Consumer consumer) { + processDependencies(new Processor() { + @Override + public boolean process(JpsDependencyElement dependencyElement) { + if (myRecursively && dependencyElement instanceof JpsModuleSourceDependency) { + consumer.consume(dependencyElement.getContainingModule()); + } + else if (!myRecursively && dependencyElement instanceof JpsModuleDependency) { + JpsModule module = ((JpsModuleDependency)dependencyElement).getModule(); + if (module != null) { + consumer.consume(module); + } + } + return true; + } + }); + } + + private boolean processDependencies(Processor processor) { + THashSet processed = new THashSet(); + for (JpsModule module : myRootModules) { + if (!doProcessDependencies(module, processor, processed)) { + return false; + } + } + return true; + } + + private boolean doProcessDependencies(JpsModule module, Processor processor, Set processed) { + if (!processed.add(module)) return true; + + for (JpsDependencyElement element : module.getDependenciesList().getDependencies()) { + if (myWithoutSdk && element instanceof JpsSdkDependency + || myWithoutLibraries && element instanceof JpsLibraryDependency + || myWithoutModuleSourceEntries && element instanceof JpsModuleSourceDependency) continue; + if (myWithoutDepModules) { + if (!myRecursively && element instanceof JpsModuleDependency) continue; + if (element instanceof JpsModuleSourceDependency && !isEnumerationRootModule(module)) continue; + } + if (shouldProcess(element)) { + + } + + if (element instanceof JpsModuleDependency) { + if (myRecursively) { + JpsModule depModule = ((JpsModuleDependency)element).getModule(); + if (depModule != null) { + doProcessDependencies(module, processor, processed); + continue; + } + } + if (myWithoutDepModules) continue; + } + + if (!processor.process(element)) { + return false; + } + } + + return true; + } + + protected boolean shouldProcess(JpsDependencyElement element) { + return true; + } + + private boolean isEnumerationRootModule(JpsModule module) { + return myRootModules.contains(module); + } + + @Override + public Set getLibraries() { + Set libraries = new HashSet(); + processLibraries(new CollectConsumer(libraries)); + return libraries; + } + + public void processLibraries(final Consumer consumer) { + processDependencies(new Processor() { + @Override + public boolean process(JpsDependencyElement dependencyElement) { + if (dependencyElement instanceof JpsLibraryDependency) { + JpsLibrary library = ((JpsLibraryDependency)dependencyElement).getLibrary(); + if (library != null) { + consumer.consume(library); + } + } + return true; + } + }); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java index 9d8d6c758cd9..5c9b558ae0d9 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsDependencyElementBase.java @@ -19,4 +19,13 @@ public abstract class JpsDependencyElementBase i return new JpsModuleImpl(this); } + @Override + @NotNull + public JpsElementProperties getProperties() { + return myContainer.getChild(TYPED_DATA_KIND).getProperties(); + } + @NotNull @Override public JpsUrlList getContentRootsList() { @@ -168,4 +174,9 @@ public class JpsModuleImpl extends JpsNamedCompositeElementBase i JpsModel model = getModel(); return model != null ? model.getProject() : null; } + + @Override + public JpsModuleType getModuleType() { + return myContainer.getChild(TYPED_DATA_KIND).getType(); + } } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java index 62bc082bd393..c17a1e8d860b 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsSdkDependencyImpl.java @@ -44,16 +44,11 @@ public class JpsSdkDependencyImpl extends JpsDependencyElementBase + diff --git a/plugins/devkit/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider b/plugins/devkit/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider new file mode 100644 index 000000000000..2f9541888d19 --- /dev/null +++ b/plugins/devkit/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider @@ -0,0 +1 @@ +org.jetbrains.jps.devkit.builder.JpsPluginSyntheticArtifactProvider \ No newline at end of file diff --git a/plugins/devkit/jps-plugin/src/META-INF/org.jetbrains.jps.model.serialization.JpsModelLoaderExtension b/plugins/devkit/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelLoaderExtension similarity index 100% rename from plugins/devkit/jps-plugin/src/META-INF/org.jetbrains.jps.model.serialization.JpsModelLoaderExtension rename to plugins/devkit/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelLoaderExtension diff --git a/plugins/devkit/jps-plugin/src/org/jetbrains/jps/devkit/builder/JpsPluginSyntheticArtifactProvider.java b/plugins/devkit/jps-plugin/src/org/jetbrains/jps/devkit/builder/JpsPluginSyntheticArtifactProvider.java new file mode 100644 index 000000000000..cba7665a1587 --- /dev/null +++ b/plugins/devkit/jps-plugin/src/org/jetbrains/jps/devkit/builder/JpsPluginSyntheticArtifactProvider.java @@ -0,0 +1,142 @@ +/* + * 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 org.jetbrains.jps.devkit.builder; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.FileUtil; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.JpsPathUtil; +import org.jetbrains.jps.devkit.model.JpsIdeaSdkProperties; +import org.jetbrains.jps.devkit.model.JpsIdeaSdkType; +import org.jetbrains.jps.devkit.model.JpsPluginModuleProperties; +import org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider; +import org.jetbrains.jps.model.JpsElementProperties; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.DirectoryArtifactType; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory; +import org.jetbrains.jps.model.java.JpsJavaClasspathKind; +import org.jetbrains.jps.model.java.JpsJavaDependenciesEnumerator; +import org.jetbrains.jps.model.java.JpsJavaExtensionService; +import org.jetbrains.jps.model.java.JpsJavaModuleType; +import org.jetbrains.jps.model.library.JpsLibrary; +import org.jetbrains.jps.model.library.JpsOrderRootType; +import org.jetbrains.jps.model.library.JpsTypedLibrary; +import org.jetbrains.jps.model.module.JpsModule; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public class JpsPluginSyntheticArtifactProvider extends JpsSyntheticArtifactProvider { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.devkit.builder.JpsPluginSyntheticArtifactProvider"); + + @NotNull + @Override + public List createArtifacts(@NotNull JpsModel model) { + List artifacts = new ArrayList(); + for (JpsModule module : model.getProject().getModules()) { + JpsElementProperties properties = module.getProperties(); + if (properties instanceof JpsPluginModuleProperties) { + artifacts.add(createArtifact(module, (JpsPluginModuleProperties)properties)); + } + } + return artifacts; + } + + private static JpsArtifact createArtifact(JpsModule module, JpsPluginModuleProperties properties) { + JpsPackagingElementFactory factory = JpsPackagingElementFactory.getInstance(); + JpsCompositePackagingElement root = factory.createArtifactRoot(); + String pluginXmlUrl = properties.getPluginXmlUrl(); + if (pluginXmlUrl != null) { + String pluginXmlPath = JpsPathUtil.urlToPath(pluginXmlUrl); + JpsCompositePackagingElement metaInfDir = factory.getOrCreateDirectory(root, "META-INF"); + metaInfDir.addChild(factory.createFileCopy(pluginXmlPath, null)); + File pluginXmlFile = JpsPathUtil.urlToFile(pluginXmlUrl); + if (pluginXmlFile.exists()) { + try { + Element rootElement = JDOMUtil.loadDocument(pluginXmlFile).getRootElement(); + for (Element dependsElement : JDOMUtil.getChildren(rootElement, "depends")) { + String relativePath = dependsElement.getAttributeValue("config-file"); + if (relativePath != null) { + File dependencyFile = new File(pluginXmlFile.getParent(), FileUtil.toSystemDependentName(relativePath)); + String dependencyPath = FileUtil.toSystemIndependentName(dependencyFile.getAbsolutePath()); + metaInfDir.addChild(factory.createFileCopy(dependencyPath, null)); + } + } + } + catch (JDOMException e) { + LOG.info(e); + } + catch (IOException e) { + LOG.info(e); + } + } + } + + JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(module).recursively().includedIn( + JpsJavaClasspathKind.PRODUCTION_RUNTIME); + JpsCompositePackagingElement classesDir = factory.getOrCreateDirectory(root, "classes"); + for (JpsModule depModule : enumerator.getModules()) { + if (depModule.getModuleType().equals(JpsJavaModuleType.INSTANCE)) { + classesDir.addChild(JpsJavaExtensionService.getInstance().createProductionModuleOutput(depModule.createReference())); + } + } + classesDir.addChild(JpsJavaExtensionService.getInstance().createProductionModuleOutput(module.createReference())); + + for (JpsLibrary library : enumerator.getLibraries()) { + JpsCompositePackagingElement parent; + if (hasDirsOnly(library)) { + parent = classesDir; + } + else { + parent = factory.getOrCreateDirectory(root, "lib"); + } + parent.addChild(factory.createLibraryElement(library.createReference())); + } + + String name = module.getName() + ":plugin"; + JpsArtifact artifact = JpsArtifactService.getInstance().createArtifact(name, root, DirectoryArtifactType.INSTANCE); + + JpsTypedLibrary sdk = module.getSdk(JpsIdeaSdkType.INSTANCE); + if (sdk != null) { + String sandboxHome = sdk.getProperties().getSandboxHome(); + if (sandboxHome != null) { + artifact.setOutputPath(sandboxHome + "/plugins/" + module.getName()); + } + } + return artifact; + } + + private static boolean hasDirsOnly(JpsLibrary library) { + List files = library.getFiles(JpsOrderRootType.COMPILED); + for (File file : files) { + if (!file.isDirectory()) { + return false; + } + } + return true; + } +} diff --git a/plugins/devkit/src/build/PluginBuildParticipant.java b/plugins/devkit/src/build/PluginBuildParticipant.java index 0d2f3b3866e5..174dd1749ce4 100644 --- a/plugins/devkit/src/build/PluginBuildParticipant.java +++ b/plugins/devkit/src/build/PluginBuildParticipant.java @@ -107,12 +107,14 @@ public class PluginBuildParticipant extends BuildParticipant { if (domElement instanceof IdeaPlugin) { for(Dependency dependency: ((IdeaPlugin)domElement).getDependencies()) { final String file = dependency.getConfigFile().getValue(); - final VirtualFile virtualFile = configFile.getVirtualFile(); - assert virtualFile != null; - final VirtualFile parent = virtualFile.getParent(); - assert parent != null; - final String url = parent.getUrl(); - factory.addFileCopy(root, "META-INF/", VfsUtil.urlToPath(url) + "/" + file); + if (file != null) { + final VirtualFile virtualFile = configFile.getVirtualFile(); + assert virtualFile != null; + final VirtualFile parent = virtualFile.getParent(); + assert parent != null; + final String url = parent.getUrl(); + factory.addFileCopy(root, "META-INF/", VfsUtil.urlToPath(url) + "/" + file); + } } } }