package jetbrains.mps.ide.java.util; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.smodel.SModelStereotype; import jetbrains.mps.smodel.LanguageID; import java.util.Set; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.ISelector; import java.util.List; import org.jetbrains.mps.openapi.model.SReference; import java.util.Map; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.smodel.ModuleRepositoryFacade; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.smodel.SModelInternal; import jetbrains.mps.kernel.model.MissingDependenciesFixer; import jetbrains.mps.project.OptimizeImportsHelper; import jetbrains.mps.project.MPSProject; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.model.EditableSModel; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.scope.Scope; import jetbrains.mps.smodel.constraints.ModelConstraints; import jetbrains.mps.scope.ErrorScope; import jetbrains.mps.typesystem.inference.TypeContextManager; import jetbrains.mps.util.Computable; import jetbrains.mps.internal.collections.runtime.IListSequence; import org.apache.log4j.Level; import org.jetbrains.mps.openapi.model.SNodeAccessUtil; public class StubResolver { private static final Logger LOG = LogManager.getLogger(StubResolver.class); private static final String JAVA_STUB = SModelStereotype.getStubStereotypeForId(LanguageID.JAVA); private Set<SModelReference> myUsedModels; private final SRepository myContextRepository; public StubResolver(SRepository contextRepo) { // resolve to any nonstub model myUsedModels = null; myContextRepository = contextRepo; } public StubResolver(SRepository contextRepo, Iterable<SModel> models) { // resolve only to models from sequence myUsedModels = SetSequence.fromSetWithValues(new HashSet<SModelReference>(), Sequence.fromIterable(models).select(new ISelector<SModel, SModelReference>() { public SModelReference select(SModel it) { return it.getReference(); } })); myContextRepository = contextRepo; } private List<SReference> getReferencesToResolve(SModel sourceModel, Map<SModelReference, SModelReference> models) { // fills models map with stub -> model correspondance List<SReference> result = ListSequence.fromList(new ArrayList<SReference>()); ModuleRepositoryFacade repoFacade = new ModuleRepositoryFacade(myContextRepository); for (SNode node : ListSequence.fromList(SModelOperations.nodes(sourceModel, null))) { for (SReference ref : ListSequence.fromList(SNodeOperations.getReferences(node))) { SModelReference targetModelRef = ref.getTargetSModelReference(); if (targetModelRef == null || !(JAVA_STUB.equals(targetModelRef.getName().getStereotype()))) { continue; } // trying to find correspondent nonstub model SModelReference modelRef = check_ar1im2_a0d0a0d0h(repoFacade.getModelByName(targetModelRef.getName().getLongName())); if (modelRef == null) { continue; } if (myUsedModels == null || SetSequence.fromSet(myUsedModels).contains(modelRef)) { MapSequence.fromMap(models).put(targetModelRef, modelRef); ListSequence.fromList(result).addElement(ref); } } } return result; } public void resolveInModel(final SModel model) { Map<SModelReference, SModelReference> models = MapSequence.fromMap(new HashMap<SModelReference, SModelReference>()); List<SReference> toResolve = getReferencesToResolve(model, models); if (ListSequence.fromList(toResolve).isEmpty()) { return; } Iterable<SModelReference> modelsToAdd = Sequence.fromIterable(MapSequence.fromMap(models).values()).where(new IWhereFilter<SModelReference>() { public boolean accept(SModelReference it) { return !(jetbrains.mps.smodel.SModelOperations.getImportedModelUIDs(model).contains(it)); } }); Sequence.fromIterable(modelsToAdd).visitAll(new IVisitor<SModelReference>() { public void visit(SModelReference it) { ((SModelInternal) model).addModelImport(it, false); } }); if (Sequence.fromIterable(modelsToAdd).isNotEmpty()) { new MissingDependenciesFixer(model).fixModuleDependencies(); } int cnt = StubResolver.resolveReferences(toResolve, models); new OptimizeImportsHelper(myContextRepository).optimizeModelImports(model); if (LOG.isInfoEnabled()) { LOG.info(cnt + " stub references were re-resolved in model " + SModelOperations.getModelName(model) + ". (" + ListSequence.fromList(toResolve).count() + ")"); } } public void resolveInModels(List<SModel> models) { for (SModel model : ListSequence.fromList(models)) { resolveInModel(model); } } public void resolveInProject(MPSProject project) { for (SModule module : Sequence.fromIterable(project.getModulesWithGenerators())) { if (module.isReadOnly()) { continue; } for (SModel model : Sequence.fromIterable(module.getModels())) { if (SModelStereotype.isUserModel(model) && model instanceof EditableSModel) { resolveInModel(model); } } } } public static int resolveReferences(List<SReference> toResolve, Map<SModelReference, SModelReference> models) { int cnt = 0; boolean found; do { found = false; for (SReference ref : ListSequence.fromList(toResolve).toGenericArray(SReference.class)) { SNode node = ref.getSourceNode(); final SModelReference modelRef = MapSequence.fromMap(models).get(ref.getTargetSModelReference()); final String resolveInfo = SLinkOperations.getResolveInfo(ref); if (modelRef == null || resolveInfo == null) { continue; } final Scope refScope = ModelConstraints.getScope(ref); if (refScope instanceof ErrorScope) { continue; } List<SNode> resolved = TypeContextManager.getInstance().runResolveAction(new Computable<IListSequence<SNode>>() { public IListSequence<SNode> compute() { return Sequence.fromIterable(refScope.getAvailableElements(null)).where(new IWhereFilter<SNode>() { public boolean accept(SNode n) { return modelRef.equals(SNodeOperations.getModel(n).getReference()) && resolveInfo.equals(jetbrains.mps.util.SNodeOperations.getResolveInfo(n)); } }).toListSequence(); } }); if (ListSequence.fromList(resolved).count() > 1) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("more than 1 possible resolution for " + SLinkOperations.getResolveInfo(ref) + " in model " + modelRef.getName()); } } if (ListSequence.fromList(resolved).isNotEmpty()) { SNodeAccessUtil.setReferenceTarget(node, ref.getLink(), ListSequence.fromList(resolved).first()); ListSequence.fromList(toResolve).removeElement(ref); ++cnt; found = true; } } } while (found); return cnt; } private static SModelReference check_ar1im2_a0d0a0d0h(SModel checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getReference(); } return null; } }