package jetbrains.mps.baseLanguage.textGen; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.language.SContainmentLink; import java.util.Map; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import org.apache.log4j.Level; import java.util.Collections; import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; import java.util.HashMap; import jetbrains.mps.baseLanguage.behavior.Classifier__BehaviorDescriptor; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.lang.core.behavior.INamedConcept__BehaviorDescriptor; public class ContextClassifiersInRoot { private static final Logger LOG = LogManager.getLogger(ContextClassifiersInRoot.class); private SimpleCache<Tuples._2<SNode, SContainmentLink>, Map<String, String>> contextClassifiersCache; private SimpleCache<SNode, Map<String, String>> nestedClassifiersCache; public ContextClassifiersInRoot(SNode rootNode) { contextClassifiersCache = new SimpleCache<Tuples._2<SNode, SContainmentLink>, Map<String, String>>() { @Override protected Map<String, String> innerGet(Tuples._2<SNode, SContainmentLink> key) { return getContextClassifiers(key._0(), key._1()); } }; nestedClassifiersCache = new SimpleCache<SNode, Map<String, String>>() { @Override protected Map<String, String> innerGet(SNode key) { return getNestedClassifiers(key); } }; } public Map<String, String> getContextClassifiers(SNode contextNode) { // only AnonymousClass has Classifier as reference // todo: make it clearer if (SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x2f89e470eed6258eL, "jetbrains.mps.baseLanguage.structure.IAnonymousClass"))) { contextNode = SNodeOperations.getParent(contextNode); } if (SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("contextNode is classifier in getContextClassifiers: " + contextNode); } return Collections.emptyMap(); } // find first classifier in path SContainmentLink sourceChildRole = null; while ((contextNode != null) && !(SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) { sourceChildRole = contextNode.getContainmentLink(); contextNode = SNodeOperations.getParent(contextNode); } if ((contextNode == null)) { // todo: impossible? return Collections.emptyMap(); } return contextClassifiersCache.get(MultiTuple.<SNode,SContainmentLink>from(SNodeOperations.cast(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), sourceChildRole)); } private Map<String, String> getContextClassifiers(SNode contextNode, SContainmentLink sourceChildRole) { Map<String, String> bindings = new HashMap<String, String>(); SNode current = contextNode; while ((current != null)) { if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) { boolean processNestedClassifiers = false; if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x1107e0cb103L, "jetbrains.mps.baseLanguage.structure.AnonymousClass")) || SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"))) { processNestedClassifiers = true; } else if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface"))) { processNestedClassifiers = !(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, 0x101eddadad7L, "extendedInterface").equals(sourceChildRole)); } else if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"))) { processNestedClassifiers = !((MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0x10f6353296dL, "superclass").equals(sourceChildRole) || MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0xff2ac0b419L, "implementedInterface").equals(sourceChildRole))); } else { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("Illegal classifier node in bl textgen: " + current); } } // todo: is it true? had a bug with it. Look like nested classifier has more priority then class with same name addClassifierToBindingMap(bindings, SNodeOperations.cast(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))); if (processNestedClassifiers) { for (Map.Entry<String, String> simpleToFqName : nestedClassifiersCache.get(SNodeOperations.cast(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))).entrySet()) { if (!(bindings.containsKey(simpleToFqName.getKey()))) { bindings.put(simpleToFqName.getKey(), simpleToFqName.getValue()); } } } } // todo: specialized links? // should not be a problem: superclass/extendedInterface/implementedInterface not specialized sourceChildRole = current.getContainmentLink(); current = SNodeOperations.getParent(current); } return bindings; } private static Map<String, String> getNestedClassifiers(SNode classifier) { // returns map from simpleName to fqName Map<String, String> nestedClassifiers = new HashMap<String, String>(); // todo: classifiers with same names in different supertypes? for (SNode superClassifier : Classifier__BehaviorDescriptor.getAllExtendedClassifiers_id2xreLMO8jma.invoke(SNodeOperations.cast(classifier, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) { for (SNode nestedClassifier : Classifier__BehaviorDescriptor.nestedClassifiers_id4_LVZ3pBjGQ.invoke(superClassifier)) { addClassifierToBindingMap(nestedClassifiers, nestedClassifier); } } return nestedClassifiers; } private static void addClassifierToBindingMap(Map<String, String> bindings, SNode classifier) { String simpleName = SPropertyOperations.getString(classifier, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); String fqName = INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(classifier); if (!(bindings.containsKey(simpleName))) { bindings.put(simpleName, fqName); } } }