package jetbrains.mps.baseLanguage.behavior;
/*Generated by MPS */
import java.util.Map;
import java.util.List;
import org.jetbrains.mps.openapi.model.SNode;
import java.util.Set;
import java.util.ArrayList;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.baseLanguage.scopes.ClassifierScopeUtils;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import java.util.HashMap;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import java.util.HashSet;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.baseLanguage.scopes.GenericTypesUtil;
public final class MethodOverrideHelper {
private Map<String, List<SNode>> myMethodsByName;
private Map<SNode, List<SNode>> myOverriddenMethods;
private Set<SNode> myDependsOnNodes;
public MethodOverrideHelper(SNode classifier) {
init(classifier);
}
public List<SNode> getMethods() {
List<SNode> result = new ArrayList<SNode>();
for (List<SNode> list : MapSequence.fromMap(this.myMethodsByName).values()) {
ListSequence.fromList(result).addSequence(ListSequence.fromList(list));
}
return result;
}
public List<SNode> getOverriddenMethods(SNode method) {
List<SNode> list = MapSequence.fromMap(this.myOverriddenMethods).get(method);
if (list != null) {
return list;
}
return new ArrayList<SNode>();
}
private void init(SNode classifier) {
Iterable<SNode> classifiers = SetSequence.fromSet(ClassifierScopeUtils.getExtendedClassifiers(classifier)).toListSequence();
Iterable<SNode> interfaces = SNodeOperations.ofConcept(classifiers, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface"));
Iterable<SNode> nonInterfaces = Sequence.fromIterable(classifiers).where(new IWhereFilter<SNode>() {
public boolean accept(SNode it) {
return !(SNodeOperations.isInstanceOf(it, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface")));
}
});
classifiers = Sequence.fromIterable(nonInterfaces).union(Sequence.fromIterable(interfaces));
List<SNode> allMethods = new ArrayList<SNode>();
for (SNode currentClassifier : classifiers) {
ListSequence.fromList(allMethods).addSequence(Sequence.fromIterable(Classifier__BehaviorDescriptor.methods_id4_LVZ3pBKCn.invoke(currentClassifier)));
}
this.myMethodsByName = MapSequence.fromMap(new HashMap<String, List<SNode>>());
this.myOverriddenMethods = MapSequence.fromMap(new HashMap<SNode, List<SNode>>());
forEachInAllMethods:
for (SNode currMethod : allMethods) {
String name = SPropertyOperations.getString(currMethod, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"));
if (name == null) {
name = "";
}
if (!(MapSequence.fromMap(this.myMethodsByName).containsKey(name))) {
List<SNode> methods = new ArrayList<SNode>();
methods.add(currMethod);
MapSequence.fromMap(myMethodsByName).put(name, methods);
MapSequence.fromMap(myOverriddenMethods).put(currMethod, new ArrayList<SNode>());
} else {
int currMethodParmCount = ListSequence.fromList(SLinkOperations.getChildren(currMethod, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))).count();
List<SNode> equalParmCountMethods = new ArrayList<SNode>();
List<SNode> methods = MapSequence.fromMap(this.myMethodsByName).get(name);
for (SNode method : methods) {
if ((SNodeOperations.getParent(currMethod) != SNodeOperations.getParent(method)) && ListSequence.fromList(SLinkOperations.getChildren(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))).count() == currMethodParmCount) {
equalParmCountMethods.add(method);
}
}
if (equalParmCountMethods.size() > 0) {
if (currMethodParmCount == 0) {
ListSequence.fromList(MapSequence.fromMap(myOverriddenMethods).get(ListSequence.fromList(equalParmCountMethods).first())).addElement(currMethod);
continue forEachInAllMethods;
}
Map<SNode, SNode> typeByTypeVar = ClassifierScopeUtils.resolveClassifierTypeVars(classifier);
String currentParms = this.createMethodParameterTypesString(currMethod, typeByTypeVar);
for (SNode otherMethod : equalParmCountMethods) {
String otherParms = this.createMethodParameterTypesString(otherMethod, typeByTypeVar);
if (otherParms.equals(currentParms)) {
MapSequence.fromMap(this.myOverriddenMethods).get(otherMethod).add(currMethod);
continue forEachInAllMethods;
}
}
}
ListSequence.fromList(MapSequence.fromMap(myMethodsByName).get(name)).addElement(currMethod);
MapSequence.fromMap(myOverriddenMethods).put(currMethod, new ArrayList<SNode>());
}
}
this.myDependsOnNodes = SetSequence.fromSet(new HashSet<SNode>());
for (SNode currentClassifier : classifiers) {
SetSequence.fromSet(this.myDependsOnNodes).addElement(currentClassifier);
}
for (SNode method : allMethods) {
SetSequence.fromSet(this.myDependsOnNodes).addElement(method);
for (SNode parm : SLinkOperations.getChildren(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))) {
SNode type = SLinkOperations.getTarget(parm, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"));
if (type == null) {
continue;
}
SetSequence.fromSet(myDependsOnNodes).addElement(type);
SetSequence.fromSet(myDependsOnNodes).addSequence(ListSequence.fromList(SNodeOperations.getNodeDescendants(type, null, false, new SAbstractConcept[]{})));
}
}
}
private String createMethodParameterTypesString(SNode method, Map<SNode, SNode> typeByTypeVar) {
StringBuilder result = new StringBuilder();
for (SNode parm : SLinkOperations.getChildren(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))) {
SNode type = SLinkOperations.getTarget(parm, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"));
type = GenericTypesUtil.getTypeWithResolvedTypeVars(type, typeByTypeVar);
if (result.length() > 0) {
result.append(',');
}
if (type != null) {
result.append(Type__BehaviorDescriptor.getErasureSignature_idhEwIzNx.invoke(type));
} else {
result.append("");
}
}
return result.toString();
}
}