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);
}
}
}