package jetbrains.mps.resolve;
/*Generated by MPS */
import jetbrains.mps.components.CoreComponent;
import java.util.Comparator;
import org.jetbrains.mps.openapi.model.SReference;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.util.SNodeOperations;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.LinkedList;
import org.jetbrains.mps.openapi.module.SRepository;
import jetbrains.mps.internal.collections.runtime.Sequence;
import java.util.Iterator;
public class ResolverComponent implements CoreComponent {
private static ResolverComponent INSTANCE;
private static Comparator<SReference> REFERENCE_COMPARATOR = new Comparator<SReference>() {
public int compare(SReference first, SReference second) {
SNode firstNode = first.getSourceNode();
SNode secondNode = second.getSourceNode();
if (SNodeOperations.isAncestor(firstNode, secondNode)) {
return 1;
}
if (SNodeOperations.isAncestor(secondNode, firstNode)) {
return -1;
}
return 0;
}
};
private List<IResolver> myResolvers;
private ScopeResolver myScopeResolver;
public ResolverComponent() {
myResolvers = ListSequence.fromList(new LinkedList<IResolver>());
myScopeResolver = new ScopeResolver();
}
@Override
public void init() {
if (INSTANCE != null) {
throw new IllegalStateException("double initialization");
}
INSTANCE = this;
INSTANCE.addResolver(myScopeResolver);
}
@Override
public void dispose() {
INSTANCE.removeResolver(myScopeResolver);
INSTANCE = null;
}
public void addResolver(IResolver resolver) {
ListSequence.fromList(myResolvers).addElement(resolver);
}
public void removeResolver(IResolver resolver) {
ListSequence.fromList(myResolvers).removeElement(resolver);
}
public boolean resolve(SReference reference, SRepository repository) {
SNode sourceNode = reference.getSourceNode();
if (sourceNode == null) {
return false;
}
for (IResolver nextResolver : ListSequence.fromList(myResolvers)) {
if (nextResolver.resolve(reference, sourceNode, repository)) {
return true;
}
}
return false;
}
public void resolveScopesOnly(Iterable<SReference> references, SRepository repository) {
List<SReference> unresolvedReferences = Sequence.fromIterable(references).sort(REFERENCE_COMPARATOR, true).toListSequence();
boolean performResolve = true;
while (performResolve) {
performResolve = false;
for (Iterator<SReference> iterator = ListSequence.fromList(unresolvedReferences).iterator(); iterator.hasNext();) {
if (resolveScopesOnly(iterator.next(), repository)) {
iterator.remove();
performResolve = true;
}
}
}
}
public boolean resolveScopesOnly(SReference reference, SRepository repository) {
SNode sourceNode = reference.getSourceNode();
if (sourceNode == null || sourceNode.getReference(reference.getLink()) != reference) {
return false;
}
return myScopeResolver.resolve(reference, sourceNode, repository);
}
public static ResolverComponent getInstance() {
return INSTANCE;
}
}