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;
}
}