package jetbrains.mps.build.util; /*Generated by MPS */ import java.util.Collection; import org.jetbrains.mps.openapi.model.SNode; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.build.behavior.BuildMacro__BehaviorDescriptor; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.generator.template.TemplateQueryContext; import java.util.concurrent.ConcurrentMap; public final class MacroHelper { private final Collection<SNode> availableMacros = new ArrayList<SNode>(); private final Map<SNode, String> macroToName = new HashMap<SNode, String>(); private final Map<SNode, String> exportNames = new HashMap<SNode, String>(); private final Map<SNode, String> importNames = new HashMap<SNode, String>(); private final Map<SNode, String> depPrefixes = new HashMap<SNode, String>(); private final Set<String> usedNames = new HashSet<String>(); private final Set<String> usedExports = new HashSet<String>(); private final Set<String> usedPrefixes = new HashSet<String>(); private final SNode project; private final MacroHelper.MacroContext context; private MacroHelper(SNode project, MacroHelper.MacroContext context) { this.project = project; this.context = context; } public void init() { for (SNode m : SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x4df58c6f18f84a22L, "macros"))) { if (usedNames.contains(SPropertyOperations.getString(m, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")))) { context.reportProblem("duplicate macro name", m); } add(m, null, ((boolean) BuildMacro__BehaviorDescriptor.isPublic_id5FtnUVJQZyL.invoke(m) ? SPropertyOperations.getString(project, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")) + "." + SPropertyOperations.getString(m, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")) : null)); } for (SNode dep : SNodeOperations.ofConcept(SLinkOperations.getChildren(project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x4df58c6f18f84a25L, "dependencies")), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x454b730dd908c220L, "jetbrains.mps.build.structure.BuildProjectDependency"))) { SNode depProject = SLinkOperations.getTarget(dep, MetaAdapterFactory.getReferenceLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x454b730dd908c220L, 0x4df58c6f18f84a24L, "script")); MacroHelper depHelper = context.getMacros(depProject); if (depHelper == null) { continue; } for (SNode m : depHelper.getAvailableMacros()) { if (macroToName.containsKey(m)) { continue; } String exportName = depHelper.getExportName(m); if (exportName == null) { continue; } String depprefix = depPrefixes.get(dep); if (depprefix == null) { depprefix = makeUnique("import." + SPropertyOperations.getString(SLinkOperations.getTarget(dep, MetaAdapterFactory.getReferenceLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x454b730dd908c220L, 0x4df58c6f18f84a24L, "script")), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")), usedPrefixes); depPrefixes.put(dep, depprefix); } add(m, depprefix + "." + exportName, exportName); } } } private void add(SNode macro, String importName, String exportName) { SNode macroProject = SNodeOperations.as(SNodeOperations.getContainingRoot(macro), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, "jetbrains.mps.build.structure.BuildProject")); if (macroProject == null) { context.reportProblem("macro is defined outside of the project", macro); return; } String name = makeUnique((macroProject == project ? SPropertyOperations.getString(macro, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")) : macroProject + "." + SPropertyOperations.getString(macro, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))), usedNames); macroToName.put(macro, name); availableMacros.add(macro); if (importName != null) { importNames.put(macro, importName); } if (exportName != null) { exportName = makeUnique(exportName, usedExports); exportNames.put(macro, exportName); } } private static String makeUnique(String baseName, Set<String> usedNames) { String name = baseName; int i = 1; while (!(usedNames.add(name))) { name = baseName + i++; } return name; } public Collection<SNode> getAvailableMacros() { return availableMacros; } public Iterable<SNode> getVarsContainers() { return Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(this.project, MetaAdapterFactory.getContainmentLink(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, 0x4df58c6f18f84a25L, "dependencies")), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x454b730dd908c220L, "jetbrains.mps.build.structure.BuildProjectDependency"))).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return depPrefixes.containsKey(it); } }); } public Iterable<SNode> getMacrosToExport() { return Sequence.fromIterable(((Iterable<SNode>) availableMacros)).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return exportNames.containsKey(it); } }); } public Iterable<SNode> getMacrosToImport() { return Sequence.fromIterable(((Iterable<SNode>) availableMacros)).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return importNames.containsKey(it); } }); } public String getName(SNode macro) { return macroToName.get(context.getOriginalMacro(macro)); } public String getExportName(SNode macro) { return exportNames.get(context.getOriginalMacro(macro)); } public String getImportName(SNode macro) { return importNames.get(context.getOriginalMacro(macro)); } public String getPrefix(SNode dep) { return depPrefixes.get(context.getOriginalDep(dep)); } public String getProjectName() { return SPropertyOperations.getString(project, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); } public void report(String message, SNode node) { context.reportProblem(message, node); } public static class MacroContext { private final Set<SNode> seenProjects = new HashSet<SNode>(); private final TemplateQueryContext genContext; private final ConcurrentMap<SNode, MacroHelper> existingMacros; public MacroContext(SNode project, TemplateQueryContext genContext) { this.genContext = genContext; this.existingMacros = GenerationUtil.<SNode,MacroHelper>getSessionMap(project, genContext, "macroHelpers"); } public MacroHelper getMacros(SNode dep) { dep = SNodeOperations.as(DependenciesHelper.getOriginalNode(dep, genContext), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a13L, "jetbrains.mps.build.structure.BuildProject")); if (dep == null) { return null; } if (seenProjects.add(dep)) { try { MacroHelper helper = this.existingMacros.get(dep); if (helper == null) { helper = new MacroHelper(dep, this); helper.init(); if (this.existingMacros.putIfAbsent(dep, helper) != null) { helper = this.existingMacros.get(dep); } } return helper; } finally { seenProjects.remove(dep); } } else { reportProblem("cycle in project dependencies", dep); return null; } } public SNode getOriginalMacro(SNode macro) { return SNodeOperations.as(DependenciesHelper.getOriginalNode(macro, genContext), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x4df58c6f18f84a1fL, "jetbrains.mps.build.structure.BuildMacro")); } public SNode getOriginalDep(SNode dep) { return SNodeOperations.as(DependenciesHelper.getOriginalNode(dep, genContext), MetaAdapterFactory.getConcept(0x798100da4f0a421aL, 0xb99171f8c50ce5d2L, 0x454b730dd908c220L, "jetbrains.mps.build.structure.BuildProjectDependency")); } public void reportProblem(String message, SNode node) { genContext.showErrorMessage(node, message); } } }