package jetbrains.mps.plugin; /*Generated by MPS */ import java.rmi.server.UnicastRemoteObject; import com.intellij.openapi.components.ProjectComponent; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import com.intellij.openapi.project.Project; import java.rmi.RemoteException; import jetbrains.mps.RuntimeFlags; import java.rmi.NoSuchObjectException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.awt.Frame; import com.intellij.openapi.wm.WindowManager; import jetbrains.mps.ide.project.ProjectHelper; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.smodel.ModuleRepositoryFacade; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import jetbrains.mps.openapi.navigation.NavigationSupport; import jetbrains.mps.util.FrameUtil; import jetbrains.mps.ide.findusages.model.SearchQuery; import jetbrains.mps.ide.findusages.findalgorithm.finders.specific.AspectMethodsFinder; import jetbrains.mps.project.GlobalScope; import jetbrains.mps.ide.findusages.view.UsageToolOptions; import jetbrains.mps.ide.findusages.view.UsagesViewTool; import jetbrains.mps.ide.findusages.view.FindUtils; import jetbrains.mps.ide.findusages.findalgorithm.finders.IFinder; 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 jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.ide.findusages.model.IResultProvider; import org.jetbrains.mps.openapi.module.SearchScope; import jetbrains.mps.util.NameUtil; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; public class MPSProjectIDEHandler extends UnicastRemoteObject implements IMPSIDEHandler, ProjectComponent { private static final Logger LOG = LogManager.getLogger(MPSProjectIDEHandler.class); private Project myProject; public MPSProjectIDEHandler(Project project) throws RemoteException { myProject = project; } @Override public void projectOpened() { if (RuntimeFlags.isTestMode()) { return; } new Thread() { @Override public void run() { try { IProjectHandler handler = MPSPlugin.getInstance().getProjectHandler(myProject.getBasePath()); if (handler == null) { return; } handler.addIdeHandler(MPSProjectIDEHandler.this); } catch (RemoteException e) { e.printStackTrace(); } } }.start(); } @Override public void projectClosed() { if (RuntimeFlags.isTestMode()) { return; } new Thread() { @Override public void run() { IProjectHandler handler = MPSPlugin.getInstance().getProjectHandler(myProject.getBasePath()); if (handler != null) { try { handler.removeIdeHandler(MPSProjectIDEHandler.this); } catch (RemoteException e) { MPSProjectIDEHandler.LOG.error(null, e); } } try { UnicastRemoteObject.unexportObject(MPSProjectIDEHandler.this, true); } catch (NoSuchObjectException e) { throw new RuntimeException(e); } } }.start(); } @NonNls @NotNull @Override public String getComponentName() { return "MPS Project IDE Handler"; } @Override public void initComponent() { } @Override public void disposeComponent() { } private Frame getMainFrame() { return WindowManager.getInstance().getFrame(myProject); } @Override public void showNode(final String namespace, final String id) throws RemoteException { final jetbrains.mps.project.Project mpsProject = ProjectHelper.toMPSProject(myProject); mpsProject.getModelAccess().runWriteInEDT(new Runnable() { public void run() { for (SModel descriptor : new ModuleRepositoryFacade(mpsProject).getAllModels()) { if (!(namespace.equals(descriptor.getModelName()))) { continue; } SNode node = descriptor.getNode(PersistenceFacade.getInstance().createNodeId(id)); if (node != null) { NavigationSupport.getInstance().openNode(mpsProject, node, true, node.getParent() != null); } } FrameUtil.activateFrame(getMainFrame()); } }); } @Override public void showAspectMethodUsages(final String namespace, final String name) throws RemoteException { SearchQuery searchQuery = new SearchQuery(new AspectMethodsFinder.AspectMethodsHolder(namespace, name), GlobalScope.getInstance()); UsageToolOptions opt = new UsageToolOptions().allowRunAgain(false).navigateIfSingle(false).forceNewTab(false).notFoundMessage("No usages for that method"); UsagesViewTool.showUsages(myProject, FindUtils.makeProvider(new IFinder[]{new AspectMethodsFinder()}), searchQuery, opt); } @Override public void showClassUsages(final String fqName) throws RemoteException { final jetbrains.mps.project.Project mpsProject = ProjectHelper.toMPSProject(myProject); mpsProject.getModelAccess().runReadAction(new Runnable() { @Override public void run() { SNode cls = findClassByName(fqName); if (cls == null) { MPSProjectIDEHandler.LOG.error("Can't find a class " + fqName); return; } FrameUtil.activateFrame(getMainFrame()); findUsages(cls, GlobalScope.getInstance(), FindUtils.makeProvider("jetbrains.mps.baseLanguage.findUsages.ClassUsages_Finder")); } }); } @Override public void showMethodUsages(final String classFqName, final String methodName, final int parameterCount) throws RemoteException { final jetbrains.mps.project.Project mpsProject = ProjectHelper.toMPSProject(myProject); mpsProject.getModelAccess().runReadAction(new Runnable() { @Override public void run() { if (classFqName == null || methodName == null) { MPSProjectIDEHandler.LOG.error("Can't find a method " + classFqName + "." + methodName); return; } SNode cls = findClassByName(classFqName); if (cls == null) { MPSProjectIDEHandler.LOG.error("Can't find a class " + classFqName); return; } Iterable<SNode> allMethods = SNodeOperations.ofConcept(SNodeOperations.getChildren(cls), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, "jetbrains.mps.baseLanguage.structure.BaseMethodDeclaration")); SNode method = Sequence.fromIterable(allMethods).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return methodName.equals(SPropertyOperations.getString(it, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))) && ListSequence.fromList(SLinkOperations.getChildren(it, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))).count() == parameterCount; } }); if (method == null) { MPSProjectIDEHandler.LOG.error("Can't find a method " + classFqName + "." + methodName); return; } FrameUtil.activateFrame(getMainFrame()); IResultProvider provider = FindUtils.makeProvider("jetbrains.mps.baseLanguage.findUsages.ConstructorUsages_Finder", "jetbrains.mps.baseLanguage.findUsages.BaseMethodUsages_Finder"); findUsages(method, GlobalScope.getInstance(), provider); } }); } private void findUsages(@NotNull final SNode node, final SearchScope scope, final IResultProvider provider) { UsageToolOptions opt = new UsageToolOptions().allowRunAgain(true).navigateIfSingle(false).forceNewTab(false).notFoundMessage("No usages for that node"); UsagesViewTool.showUsages(myProject, provider, new SearchQuery(node, scope), opt); } private SNode findClassByName(String classFqName) { // This is slightly updated SModelUtil.findNodeByFQName, which moved here as it's the only place we use it // FIXME however, it's ugly and needs rework String modelName = NameUtil.namespaceFromLongName(classFqName); String name = NameUtil.shortNameFromLongName(classFqName); for (SModel m : Sequence.fromIterable(GlobalScope.getInstance().getModels())) { if (!(modelName.equals(NameUtil.getModelLongName(m)))) { continue; } SModel model = m; for (SNode root : ListSequence.fromList(SModelOperations.roots(model, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) { if (name.equals(SPropertyOperations.getString(root, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")))) { return root; } } } return null; } }