package jetbrains.mps.baseLanguage.generator.java.closures.util; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import java.util.List; import jetbrains.mps.generator.template.TemplateQueryContext; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import org.jetbrains.mps.openapi.language.SAbstractConcept; import java.util.Set; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import java.util.ArrayList; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import java.util.HashMap; public class ClosuresUtil { private static Object CLOSURE_CONTEXT_DATA = new Object(); public ClosuresUtil() { } public static boolean isClosureContextOwner(SNode node) { if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration"))) { return true; } return SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, "jetbrains.mps.baseLanguage.structure.ConceptFunction")) && !(SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure"))); } public static SNode findEnclosingClosureContextOwner(SNode node) { return ListSequence.fromList(SNodeOperations.getNodeAncestors(node, null, false)).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return ClosuresUtil.isClosureContextOwner(it); } }); } public static List<SNode> getVariablesUsedInClosure(SNode contextOwner, TemplateQueryContext genContext) { ensureClosureContextOwnerProcessed(contextOwner, genContext); return getClosureContextData(contextOwner, genContext).getVariables(); } public static String getVariableNameInClosureContext(SNode contextOwner, SNode var, TemplateQueryContext genContext) { ensureClosureContextOwnerProcessed(contextOwner, genContext); return getClosureContextData(contextOwner, genContext).getVariableName(var); } public static boolean isVariableUsedInClosure(SNode contextOwner, SNode var, TemplateQueryContext genContext) { ensureClosureContextOwnerProcessed(contextOwner, genContext); ClosuresUtil.ClosureContextData contextData = getClosureContextData(contextOwner, genContext); return (contextData != null ? contextData.hasVariable(var) : false); } public static boolean hasVariablesUsedInClosure(SNode contextOwner, TemplateQueryContext genContext) { ensureClosureContextOwnerProcessed(contextOwner, genContext); return !(getClosureContextData(contextOwner, genContext).isEmpty()); } private static void ensureClosureContextOwnerProcessed(SNode node, TemplateQueryContext genContext) { if (!(isClosureContextOwner(node))) { genContext.showErrorMessage(node, "node can't be owner of a closure context "); return; } if (getClosureContextData(node, genContext) == null) { MapSequence.fromMap(ClosuresUtil.getClosureContext(genContext)).put(node, new ClosuresUtil.ClosureContextData()); if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration"))) { processMethodDeclaration(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration")), genContext); } else { processConceptFunction(SNodeOperations.cast(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, "jetbrains.mps.baseLanguage.structure.ConceptFunction")), genContext); } } } private static Map<SNode, ClosuresUtil.ClosureContextData> getClosureContext(TemplateQueryContext genContext) { // init ClosureContextData synchronized (CLOSURE_CONTEXT_DATA) { Map<SNode, ClosuresUtil.ClosureContextData> closureContexts = ((Map<SNode, ClosuresUtil.ClosureContextData>) genContext.getTransientObject(CLOSURE_CONTEXT_DATA)); if (closureContexts == null) { closureContexts = new ConcurrentHashMap<SNode, ClosuresUtil.ClosureContextData>(); genContext.putTransientObject(CLOSURE_CONTEXT_DATA, closureContexts); } return closureContexts; } } private static boolean processMethodDeclaration(SNode method, TemplateQueryContext genContext) { if (SLinkOperations.getTarget(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body")) == null) { return false; } if (ListSequence.fromList(SNodeOperations.getNodeDescendants(SLinkOperations.getTarget(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure"), false, new SAbstractConcept[]{})).isEmpty()) { return false; } Set<SNode> varDecl = SetSequence.fromSetWithValues(new HashSet<SNode>(), SLinkOperations.getChildren(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))); return processNode(method, SLinkOperations.getTarget(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body")), varDecl, genContext); } private static boolean processConceptFunction(SNode concFunc, TemplateQueryContext genContext) { if (SLinkOperations.getTarget(concFunc, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, 0x108bbd29b4aL, "body")) == null) { return false; } if (ListSequence.fromList(SNodeOperations.getNodeDescendants(SLinkOperations.getTarget(concFunc, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, 0x108bbd29b4aL, "body")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure"), false, new SAbstractConcept[]{})).isEmpty()) { return false; } return processNode(concFunc, SLinkOperations.getTarget(concFunc, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, 0x108bbd29b4aL, "body")), SetSequence.fromSet(new HashSet<SNode>()), genContext); } private static boolean processNode(SNode contextOwner, SNode node, Set<SNode> localVariables, TemplateQueryContext genContext) { boolean outerVarsFound = false; for (SNode child : ListSequence.fromList(SNodeOperations.getChildren(node))) { if (SNodeOperations.isInstanceOf(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration"))) { SetSequence.fromSet(localVariables).addElement(SNodeOperations.cast(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration"))); } else if (SNodeOperations.isInstanceOf(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure"))) { if (processClosure(contextOwner, SNodeOperations.cast(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure")), localVariables, genContext)) { outerVarsFound = true; } } if (processNode(contextOwner, child, localVariables, genContext)) { outerVarsFound = true; } } return outerVarsFound; } private static boolean processClosure(SNode contextOwner, SNode closure, Set<SNode> localVars, TemplateQueryContext genContext) { if (SLinkOperations.getTarget(closure, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, 0x108bbd29b4aL, "body")) == null) { return false; } return processClosureNode(contextOwner, SLinkOperations.getTarget(closure, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x108bbca0f48L, 0x108bbd29b4aL, "body")), localVars, genContext); } private static boolean processClosureNode(SNode contextOwner, SNode node, Set<SNode> localVars, TemplateQueryContext genContext) { boolean outerVarsFound = false; for (SNode child : ListSequence.fromList(SNodeOperations.getChildren(node))) { // skip inner closure if (SNodeOperations.isInstanceOf(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10c63f4f3f3L, "jetbrains.mps.baseLanguage.structure.Closure"))) { continue; } if ((SNodeOperations.isInstanceOf(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")) && SNodeOperations.isInstanceOf(SLinkOperations.getTarget(SNodeOperations.cast(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc67c7efL, "jetbrains.mps.baseLanguage.structure.LocalVariableDeclaration"))) || (SNodeOperations.isInstanceOf(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")) && SNodeOperations.isInstanceOf(SLinkOperations.getTarget(SNodeOperations.cast(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e94L, "jetbrains.mps.baseLanguage.structure.ParameterDeclaration")))) { SNode variable = SLinkOperations.getTarget(SNodeOperations.cast(child, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference")), MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); if (SetSequence.fromSet(localVars).contains(variable)) { getClosureContextData(contextOwner, genContext).putVariable(variable); outerVarsFound = true; } } else { if (processClosureNode(contextOwner, child, localVars, genContext)) { outerVarsFound = true; } } } return outerVarsFound; } private static ClosuresUtil.ClosureContextData getClosureContextData(SNode contextOwner, TemplateQueryContext genContext) { Map<SNode, ClosuresUtil.ClosureContextData> closureContexts = ((Map<SNode, ClosuresUtil.ClosureContextData>) genContext.getTransientObject(CLOSURE_CONTEXT_DATA)); if (closureContexts == null) { return null; } return MapSequence.fromMap(closureContexts).get(contextOwner); } public static class ClosureContextData { private Map<SNode, String> myVar2Name; private Map<String, SNode> myName2Var; private List<SNode> myVars; public ClosureContextData() { } public List<SNode> getVariables() { if (this.myVars == null) { return new ArrayList<SNode>(); } return this.myVars; } public String getVariableName(SNode var) { return MapSequence.fromMap(this.myVar2Name).get(var); } public boolean isEmpty() { return this.myVars == null || ListSequence.fromList(this.myVars).isEmpty(); } public boolean hasVariable(SNode var) { if (this.myVar2Name == null) { return false; } return MapSequence.fromMap(this.myVar2Name).containsKey(var); } /*package*/ void putVariable(SNode var) { this.ensureInitialized(); if (this.hasVariable(var)) { return; } int count = 1; String name = SPropertyOperations.getString(var, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); while (MapSequence.fromMap(this.myName2Var).containsKey(name)) { name = SPropertyOperations.getString(var, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")) + (count++); } MapSequence.fromMap(this.myName2Var).put(name, var); MapSequence.fromMap(this.myVar2Name).put(var, name); ListSequence.fromList(this.myVars).addElement(var); } private void ensureInitialized() { if (this.myVars == null) { this.myVar2Name = MapSequence.fromMap(new HashMap<SNode, String>()); this.myName2Var = MapSequence.fromMap(new HashMap<String, SNode>()); this.myVars = new ArrayList<SNode>(); } } } }