package jetbrains.mps.build.mps.util; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SNode; import java.util.List; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.ISelector; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.make.dependencies.graph.Graph; import java.util.Map; import java.util.LinkedHashMap; import jetbrains.mps.make.dependencies.graph.IVertex; import jetbrains.mps.make.dependencies.graph.Graphs; import jetbrains.mps.util.GraphUtil; import java.util.ArrayList; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.Set; import java.util.HashSet; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.internal.collections.runtime.ITranslator2; import java.util.LinkedHashSet; import jetbrains.mps.build.mps.behavior.BuildMps_DevKit__BehaviorDescriptor; public class MPSModulesPartitioner { private final SNode project; private final List<SNode> modules; private List<MPSModulesPartitioner.Chunk> chunks; private boolean useMeta; private Iterable<SNode> external; public MPSModulesPartitioner(SNode project) { this(project, ListSequence.fromList(Sequence.fromIterable(getModules(project)).sort(new ISelector<SNode, String>() { public String select(SNode it) { return SPropertyOperations.getString(it, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); } }, true).toListSequence()).asUnmodifiable()); } public MPSModulesPartitioner(SNode project, List<SNode> modules) { this.project = project; this.modules = modules; } public void buildChunks() { Graph<MPSModulesPartitioner.Node> graph = new Graph<MPSModulesPartitioner.Node>(); final Map<SNode, MPSModulesPartitioner.Node> map = new LinkedHashMap<SNode, MPSModulesPartitioner.Node>(); for (SNode module : modules) { MPSModulesPartitioner.Node decorator = new MPSModulesPartitioner.Node(module); map.put(module, decorator); graph.add(decorator); } for (MPSModulesPartitioner.Node node : graph.getData()) { node.fill(map); } IVertex[] vertices = graph.getData().toArray(new IVertex[graph.getNVertexes()]); useMeta = false; int[][] greater_or_eq = Graphs.graphToIntInt(vertices, false, true); useMeta = true; int[][] strictly_greater = Graphs.graphToIntInt(vertices, true, true); int[] partition = GraphUtil.partition(greater_or_eq, strictly_greater); this.chunks = ListSequence.fromList(new ArrayList<MPSModulesPartitioner.Chunk>()); for (int i = 0; i < vertices.length; i++) { SNode m = ((MPSModulesPartitioner.Node) vertices[i]).module; int pindex = partition[i]; boolean conflicting = pindex < 0; if (conflicting) { pindex = -1 - pindex; } while (ListSequence.fromList(chunks).count() <= pindex) { ListSequence.fromList(chunks).addElement(new MPSModulesPartitioner.Chunk()); } SetSequence.fromSet(ListSequence.fromList(chunks).getElement(pindex).getModules()).addElement(m); if (conflicting) { ListSequence.fromList(chunks).getElement(pindex).setBootstrap(m, true); } } for (MPSModulesPartitioner.Chunk c : chunks) { Set<MPSModulesPartitioner.Node> chunkNodes = SetSequence.fromSetWithValues(new HashSet<MPSModulesPartitioner.Node>(), SetSequence.fromSet(c.getModules()).select(new ISelector<SNode, MPSModulesPartitioner.Node>() { public MPSModulesPartitioner.Node select(SNode it) { return map.get(it); } })); for (SNode confl : ListSequence.fromListWithValues(new ArrayList<SNode>(), c.getConflicting())) { if (SetSequence.fromSet(map.get(confl).metaDependencies).intersect(SetSequence.fromSet(chunkNodes)).isEmpty()) { c.setBootstrap(confl, false); } } } } public void buildExternalDependencies() { // Though we don't care about RT dependencies to generate a module, we need runtimeClosure() here due to // module compilation/reload Generate task does in addition to M2M, M2T transformations. this.external = Sequence.fromIterable(new MPSModulesClosure(modules, new MPSModulesClosure.ModuleDependenciesOptions().trackDevkits()).generationDependenciesClosure().runtimeClosure().getAllModules()).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { // FIXME exclusion of generator modules here is due to the fact ModuleMiner (which eventually takes whatever we specify in <library file>) // is not ready yet to read generator modules (it's JavaModuleFacet of Language-loaded Generator that discovers -generator.jar) // However, the way forward is to be explicit about generator modules (need to produce META-INF/module.xml first, though) return !(SNodeOperations.isInstanceOf(it, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4c6db07d2e56a8b4L, "jetbrains.mps.build.mps.structure.BuildMps_Generator"))) && SNodeOperations.getContainingRoot(it) != SNodeOperations.getContainingRoot(MPSModulesPartitioner.this.project); } }); } public List<MPSModulesPartitioner.Chunk> getChunks() { return chunks; } public Iterable<SNode> getExternal() { return external; } public static Iterable<SNode> getModules(SNode project) { return Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x668c6cfbafacf6f2L, "parts")), MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x14d3fb6fb843ebddL, "jetbrains.mps.build.mps.structure.BuildMps_Group"))).translate(new ITranslator2<SNode, SNode>() { public Iterable<SNode> translate(SNode it) { return SLinkOperations.getChildren(it, MetaAdapterFactory.getContainmentLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x14d3fb6fb843ebddL, 0x14d3fb6fb843ebdeL, "modules")); } }).concat(Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x668c6cfbafacf6f2L, "parts")), MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d333ebL, "jetbrains.mps.build.mps.structure.BuildMps_AbstractModule")))); } private class Node implements IVertex { private SNode module; private Set<MPSModulesPartitioner.Node> dependencyNodes = SetSequence.fromSet(new LinkedHashSet<MPSModulesPartitioner.Node>()); private Set<MPSModulesPartitioner.Node> metaDependencies = SetSequence.fromSet(new LinkedHashSet<MPSModulesPartitioner.Node>()); public Node(SNode module) { this.module = module; } @Override public Set<? extends IVertex> getNexts() { return (useMeta ? metaDependencies : dependencyNodes); } public void fill(Map<SNode, MPSModulesPartitioner.Node> map) { if (SNodeOperations.isInstanceOf(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module"))) { MPSModulesClosure closure = new MPSModulesClosure(SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module")), new MPSModulesClosure.ModuleDependenciesOptions()).generationDependenciesClosure(); for (SNode q : Sequence.fromIterable(closure.getAllModules())) { MPSModulesPartitioner.Node node = map.get(q); if (node != null) { SetSequence.fromSet(metaDependencies).addElement(node); } } closure = new MPSModulesClosure(SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x48e82d508331930cL, "jetbrains.mps.build.mps.structure.BuildMps_Module")), new MPSModulesClosure.ModuleDependenciesOptions().trackDevkits()).closure(); for (SNode q : Sequence.fromIterable(closure.getAllModules())) { MPSModulesPartitioner.Node node = map.get(q); if (node != null) { SetSequence.fromSet(dependencyNodes).addElement(node); } } } else if (SNodeOperations.isInstanceOf(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, "jetbrains.mps.build.mps.structure.BuildMps_DevKit"))) { SNode devkit = SNodeOperations.cast(module, MetaAdapterFactory.getConcept(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, "jetbrains.mps.build.mps.structure.BuildMps_DevKit")); Iterable<SNode> extended = SLinkOperations.collect(SLinkOperations.getChildren(devkit, MetaAdapterFactory.getContainmentLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2060eL, 0x4780308f5d23142L, "extends")), MetaAdapterFactory.getReferenceLink(0xcf935df46994e9cL, 0xa132fa109541cba3L, 0x4780308f5d2313aL, 0x4780308f5d2313bL, "devkit")); for (SNode q : Sequence.fromIterable(BuildMps_DevKit__BehaviorDescriptor.getExportedModules_id6qlcPcvboVF.invoke(devkit)).concat(Sequence.fromIterable(extended))) { MPSModulesPartitioner.Node node = map.get(q); if (node != null) { SetSequence.fromSet(dependencyNodes).addElement(node); } } } } } public static class Chunk { private final Set<SNode> modules; private final Set<SNode> conflicting; public Chunk() { this.modules = SetSequence.fromSet(new LinkedHashSet<SNode>()); this.conflicting = SetSequence.fromSet(new HashSet<SNode>()); } public Set<SNode> getModules() { return modules; } public Set<SNode> getConflicting() { return conflicting; } public boolean isConflicting(SNode mod) { return SetSequence.fromSet(conflicting).contains(mod); } public boolean isBootstrap() { return SetSequence.fromSet(conflicting).isNotEmpty(); } public void setBootstrap(SNode module, boolean flag) { if (flag) { SetSequence.fromSet(conflicting).addElement(module); } else { SetSequence.fromSet(conflicting).removeElement(module); } } } }