package jetbrains.mps.ide.modelchecker.actions; /*Generated by MPS */ import jetbrains.mps.ide.modelchecker.platform.actions.SpecificChecker; import jetbrains.mps.project.Project; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import jetbrains.mps.util.PathManager; import java.util.List; import jetbrains.mps.ide.findusages.model.SearchResult; import jetbrains.mps.ide.modelchecker.platform.actions.ModelCheckerIssue; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.util.ProgressMonitor; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import org.jetbrains.mps.openapi.model.SReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.AttributeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.IAttributeDescriptor; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.ide.modelchecker.platform.actions.ModelChecker; import jetbrains.mps.ide.modelchecker.platform.actions.IModelCheckerFix; import jetbrains.mps.resolve.ResolverComponent; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.persistence.DataSource; import jetbrains.mps.vfs.IFile; import jetbrains.mps.extapi.persistence.FileDataSource; import jetbrains.mps.smodel.Language; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations; import jetbrains.mps.project.Solution; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; public class AspectDependenciesChecker extends SpecificChecker { private static int CORE = 1; private static int EDITOR = 2; private static int WORKBENCH = 3; private static int OTHER = 4; private final Project myProject; private final SModule coreModule; private final SModule editorModule; private final String languagesUtilPath; public AspectDependenciesChecker(@NotNull Project mpsProject) { myProject = mpsProject; this.coreModule = PersistenceFacade.getInstance().createModuleReference("6ed54515-acc8-4d1e-a16c-9fd6cfe951ea(MPS.Core)").resolve(mpsProject.getRepository()); this.editorModule = PersistenceFacade.getInstance().createModuleReference("1ed103c3-3aa6-49b7-9c21-6765ee11f224(MPS.Editor)").resolve(mpsProject.getRepository()); this.languagesUtilPath = PathManager.getHomePath() + "/languages/util/"; } @Override public List<SearchResult<ModelCheckerIssue>> checkModel(SModel model, ProgressMonitor monitor) { List<SearchResult<ModelCheckerIssue>> results = ListSequence.fromList(new ArrayList<SearchResult<ModelCheckerIssue>>()); monitor.start("wrong aspect dependencies", 1); int modelKind = getModelKind(model, null); if (modelKind == OTHER) { monitor.done(); return results; } for (SNode node : ListSequence.fromList(SModelOperations.nodes(model, null))) { if (monitor.isCanceled()) { break; } // Check for unresolved references for (final SReference ref : ListSequence.fromList(SNodeOperations.getReferences(node))) { if ((AttributeOperations.getAttribute(node, new IAttributeDescriptor.LinkAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd7f44d616L, "jetbrains.mps.lang.generator.structure.ReferenceMacro"), ref.getLink())) != null)) { continue; } SNode targetNode = jetbrains.mps.util.SNodeOperations.getTargetNodeSilently(ref); if (targetNode == null) { SpecificChecker.addIssue(results, node, "Unresolved reference: " + SLinkOperations.getResolveInfo(ref), ModelChecker.SEVERITY_ERROR, "unresolved reference", new IModelCheckerFix() { public boolean doFix() { return ResolverComponent.getInstance().resolve(ref, myProject.getRepository()); } }); continue; } SModel targetModel = SNodeOperations.getModel(targetNode); int targetKind = getModelKind(targetModel, ref); if (targetKind > modelKind) { SpecificChecker.addIssue(results, node, "Wrong reference: " + SLinkOperations.getResolveInfo(ref) + ", reference from " + kindToString(modelKind) + " to " + kindToString(targetKind), ModelChecker.SEVERITY_ERROR, "wrong aspect dependency (" + kindToString(modelKind) + ")", null); } } } monitor.done(); return results; } public int getModelKind(SModel model, @Nullable SReference reference) { DataSource source = (model != null ? model.getSource() : null); IFile modelFile = (source instanceof FileDataSource ? ((FileDataSource) source).getFile() : null); if (modelFile != null) { String filePath = modelFile.getPath().replace('\\', '/'); if (filePath.startsWith(languagesUtilPath)) { return OTHER; } } SModule module = model.getModule(); if (module instanceof Language) { if (SModuleOperations.isAspect(model, "actions")) { return EDITOR; } else if (SModuleOperations.isAspect(model, "behavior")) { return CORE; } else if (SModuleOperations.isAspect(model, "constraints")) { return CORE; } else if (SModuleOperations.isAspect(model, "dataFlow")) { return CORE; } else if (SModuleOperations.isAspect(model, "editor")) { return EDITOR; } else if (SModuleOperations.isAspect(model, "findUsages")) { return CORE; } else if (SModuleOperations.isAspect(model, "intentions")) { return EDITOR; } else if (SModuleOperations.isAspect(model, "plugin")) { return WORKBENCH; } else if (SModuleOperations.isAspect(model, "refactorings")) { return CORE; } else if (SModuleOperations.isAspect(model, "scripts")) { return CORE; } else if (SModuleOperations.isAspect(model, "structure")) { return CORE; } else if (SModuleOperations.isAspect(model, "migration")) { return CORE; } else if (SModuleOperations.isAspect(model, "test")) { return EDITOR; } else if (SModuleOperations.isAspect(model, "textGen")) { return CORE; } else if (SModuleOperations.isAspect(model, "typesystem")) { return CORE; } else { return CORE; } } else if (module instanceof Solution) { String moduleFqName = module.getModuleName(); if (moduleFqName.equals("JDK")) { return CORE; } if (moduleFqName.equals("MPS.Core")) { return CORE; } if (moduleFqName.equals("MPS.Editor")) { return EDITOR; } if (moduleFqName.equals("MPS.Workbench")) { return WORKBENCH; } if (moduleFqName.equals("MPS.Classpath")) { SNode refTargetRoot = reference.getTargetNode().getContainingRoot(); if (SNodeOperations.isInstanceOf(refTargetRoot, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) { String cName = SPropertyOperations.getString(SNodeOperations.cast(refTargetRoot, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); String modelName = model.getModelName(); if (findInModule(coreModule, modelName, cName)) { return CORE; } if (findInModule(editorModule, modelName, cName)) { return EDITOR; } return WORKBENCH; } return OTHER; } Solution sol = (Solution) module; switch (sol.getKind()) { case NONE: return OTHER; case PLUGIN_CORE: return CORE; case PLUGIN_EDITOR: return EDITOR; case PLUGIN_OTHER: return WORKBENCH; default: } } return OTHER; } public static boolean findInModule(SModule module, String modelName, String rootName) { for (SModel d : module.getModels()) { if (d.getModelName().equals(modelName)) { for (SNode _n : d.getRootNodes()) { SNode n = (SNode) _n; if (SNodeOperations.isInstanceOf(n, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")) && SPropertyOperations.getString(SNodeOperations.cast(n, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")).equals(rootName)) { return true; } } } } return false; } public static String kindToString(int kind) { switch (kind) { case 1: return "core"; case 2: return "editor"; case 3: return "workbench"; default: } return "unknown"; } }