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