Пример #1
0
 @Override
 public void doubleClick() {
   Project project = getProject();
   final SRepository r = ProjectHelper.getProjectRepository(project);
   SModule m =
       (r == null
           ? null
           : new ModelAccessHelper(r)
               .runReadAction(
                   new Computable<SModule>() {
                     public SModule compute() {
                       return myModule.resolve(r);
                     }
                   }));
   if (m == null) {
     return;
   }
   ProjectPane.getInstance(project).selectModule(m, false);
 }
Пример #2
0
 private SNode getNode(AbstractTreeNode treeNode) {
   if (!(treeNode instanceof MPSPsiElementTreeNode)) {
     return null;
   }
   MPSPsiNodeBase psiNode = ((MPSPsiElementTreeNode) treeNode).getValue();
   if (!(psiNode instanceof MPSPsiRealNode)) {
     return null;
   }
   final SNodeReference nodeRef = ((MPSPsiRealNode) psiNode).getSNodeReference();
   final SRepository repository = ProjectHelper.getProjectRepository(treeNode.getProject());
   // TODO remove read action from here once SModelFileTracker stops doing the same (creating read
   // action if not already in one)
   return new ModelComputeRunnable<SNode>(
           new Computable<SNode>() {
             @Override
             public SNode compute() {
               return nodeRef.resolve(repository);
             }
           })
       .runRead(repository.getModelAccess());
 }
Пример #3
0
  @Override
  public Collection<AbstractTreeNode> modify(
      final AbstractTreeNode treeNode,
      final Collection<AbstractTreeNode> children,
      final ViewSettings settings) {
    final Ref<Collection<AbstractTreeNode>> result =
        new Ref<Collection<AbstractTreeNode>>(children);

    // we're actually in EDT here, but we work with SModels, and various routines assert that we can
    // read, thus read action
    ProjectHelper.getProjectRepository(treeNode.getProject())
        .getModelAccess()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {
                List<AbstractTreeNode> updatedChildren = null;
                final MPSPsiProvider mpsPsiProvider =
                    MPSPsiProvider.getInstance(treeNode.getProject());

                // if current dir is data source from some model
                FolderDataSource currentDirectoryDataSource = null;

                if (treeNode instanceof PsiDirectoryNode) {
                  // let's see if we have a model built from this dir, e.g. in per-root persistence
                  SModel sModel =
                      SModelFileTracker.getInstance()
                          .findModel(
                              VirtualFileUtils.toIFile(
                                  ((PsiDirectoryNode) treeNode).getVirtualFile()));
                  if (sModel != null) {
                    // adding root nodes (removing their corresponding files' nodes from the tree is
                    // further below)
                    List<MPSPsiElementTreeNode> rootsTreeNodes =
                        new ArrayList<MPSPsiElementTreeNode>();
                    for (SNode root : sModel.getRootNodes()) {
                      rootsTreeNodes.add(
                          new MPSPsiElementTreeNode(
                              treeNode.getProject(),
                              (MPSPsiRootNode) mpsPsiProvider.getPsi(root).getContainingFile(),
                              settings));
                    }
                    if (!rootsTreeNodes.isEmpty() && updatedChildren == null) {
                      updatedChildren = new ArrayList<AbstractTreeNode>(children);
                      updatedChildren.addAll(rootsTreeNodes);
                    }

                    DataSource dataSource = sModel.getSource();
                    if (dataSource instanceof FolderDataSource) {
                      // could be assert as currently SModelFileTracker only tracks FileDataSource
                      // and FolderDataSource
                      currentDirectoryDataSource = (FolderDataSource) dataSource;
                    }
                  }
                } else if (treeNode instanceof MPSPsiModelTreeNode) {
                  MPSPsiModel psiModel = ((MPSPsiModelTreeNode) treeNode).extractPsiFromValue();
                  updatedChildren = new ArrayList<AbstractTreeNode>();
                  for (PsiElement psiElement : psiModel.getChildren()) {
                    updatedChildren.add(
                        new MPSPsiElementTreeNode(
                            treeNode.getProject(), (MPSPsiRootNode) psiElement, settings));
                  }
                }

                for (final AbstractTreeNode child : children) {
                  if (child instanceof PsiFileNode) {
                    VirtualFile vFile = ((PsiFileNode) child).getVirtualFile();
                    if (vFile == null) {
                      continue;
                    }

                    // check if it's a single file model
                    final SModel sModel =
                        SModelFileTracker.getInstance().findModel(VirtualFileUtils.toIFile(vFile));
                    if (sModel != null) {
                      if (updatedChildren == null)
                        updatedChildren = new ArrayList<AbstractTreeNode>(children);
                      int idx = updatedChildren.indexOf(child);
                      updatedChildren.remove(idx);
                      updatedChildren.add(
                          idx,
                          new MPSPsiModelTreeNode(
                              treeNode.getProject(), mpsPsiProvider.getPsi(sModel), settings));
                      continue;
                    }

                    if (currentDirectoryDataSource != null
                        && currentDirectoryDataSource.isIncluded(VirtualFileUtils.toIFile(vFile))) {
                      // it's a file that constitutes a FolderDataSource-backed model, remove it
                      // from the tree (root nodes are shown instead)
                      if (updatedChildren == null)
                        updatedChildren = new ArrayList<AbstractTreeNode>(children);
                      int idx = updatedChildren.indexOf(child);
                      updatedChildren.remove(idx);
                    }

                  } else if (child instanceof PsiDirectoryNode) {
                    // below code only attaches our action to the directory and makes it show added
                    // children - our root nodes

                    final SModel perRootModel =
                        SModelFileTracker.getInstance()
                            .findModel(
                                VirtualFileUtils.toIFile(
                                    ((PsiDirectoryNode) child).getVirtualFile()));
                    if (perRootModel != null) {
                      if (updatedChildren == null)
                        updatedChildren = new ArrayList<AbstractTreeNode>(children);

                      int idx = updatedChildren.indexOf(child);
                      updatedChildren.remove(idx);
                      updatedChildren.add(
                          idx,
                          new PsiDirectoryNode(
                              treeNode.getProject(),
                              ((PsiDirectoryNode) child).getValue(),
                              settings) {
                            @Override
                            public boolean canNavigate() {
                              return true;
                            }

                            @Override
                            public String getNavigateActionText(boolean focusEditor) {
                              return MPSBundle.message("open.model.properties.action");
                            }

                            @Override
                            public void navigate(boolean requestFocus) {
                              MPSPropertiesConfigurable configurable =
                                  new ModelPropertiesConfigurable(
                                      perRootModel, ProjectHelper.toMPSProject(myProject), true);
                              final SingleConfigurableEditor dialog =
                                  new SingleConfigurableEditor(myProject, configurable);
                              configurable.setParentForCallBack(dialog);
                              SwingUtilities.invokeLater(
                                  new Runnable() {
                                    @Override
                                    public void run() {
                                      dialog.show();
                                    }
                                  });
                            }
                          });
                    }
                  }
                }

                if (updatedChildren != null) {
                  result.set(updatedChildren);
                }
              }
            });

    return result.get();
  }
Пример #4
0
  @Override
  public void processQuery(
      @NotNull SearchParameters queryParameters, @NotNull final Processor<PsiReference> consumer) {

    if (!(queryParameters.getEffectiveSearchScope() instanceof GlobalSearchScope)) {
      return;
    }
    final GlobalSearchScope scope = (GlobalSearchScope) queryParameters.getEffectiveSearchScope();

    final PsiElement target = queryParameters.getElementToSearch();
    // Only class names can be prefixes in foreign ids of other nodes
    if (!(target instanceof PsiClass)) return;
    final SRepository repository = ProjectHelper.getProjectRepository(scope.getProject());
    if (repository == null) {
      return;
    }

    repository
        .getModelAccess()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {

                final NodePtr nodePtr = JavaForeignIdBuilder.computeNodePtr(target);
                if (nodePtr == null) return;

                final SNodeReference mpsTarget =
                    new SNodePointer(nodePtr.getSModelReference(), nodePtr.getNodeId());
                // do we have this node?
                if (mpsTarget.resolve(MPSModuleRepository.getInstance()) == null) return;

                String prefix = nodePtr.getNodeId().toString();
                final String prefixToSearch =
                    (prefix.startsWith(Foreign.ID_PREFIX) ? prefix.substring(1) : prefix);
                final String prefixToSearchWithDot = prefixToSearch + ".";
                final Project project = target.getProject();

                // first look into changed models
                SearchScope mpsSearchScope = new IdeaSearchScope(scope, true);
                CollectConsumer<VirtualFile> processedFilesConsumer =
                    new CollectConsumer<VirtualFile>();

                for (SModel model : mpsSearchScope.getModels()) {
                  boolean changed =
                      model instanceof EditableSModel && ((EditableSModel) model).isChanged();
                  if (!changed) continue;

                  findInModel(
                      model,
                      prefixToSearch,
                      processedFilesConsumer,
                      new Consumer<SReference>() {
                        @Override
                        public void consume(SReference ref) {

                          String role = ref.getRole();
                          SNode source = ref.getSourceNode();

                          PsiElement psiNode =
                              MPSPsiProvider.getInstance(project).getPsi(source.getReference());
                          assert psiNode instanceof MPSPsiNode;

                          consumer.process(new IdPrefixReference(mpsTarget, role, psiNode));
                        }
                      });
                }

                // now index
                final Collection<VirtualFile> filesOfChangedModels =
                    processedFilesConsumer.getResult();

                GlobalSearchScope truncatedScope =
                    new DelegatingGlobalSearchScope(scope) {
                      @Override
                      public boolean contains(VirtualFile file) {
                        if (filesOfChangedModels.contains(file)) return false;
                        return super.contains(file);
                      }
                    };

                ValueProcessor<Collection<Pair<SNodeDescriptor, String>>> sReferenceProcessor =
                    new ValueProcessor<Collection<Pair<SNodeDescriptor, String>>>() {
                      @Override
                      public boolean process(
                          VirtualFile file, Collection<Pair<SNodeDescriptor, String>> refs) {
                        for (Pair<SNodeDescriptor, String> ref : refs) {
                          SNodeReference nodeRef = ref.o1.getNodeReference();
                          String role = ref.o2;

                          // index got out-of-date on this
                          // unfortunately our indices are not always up-to-date, as we don't index
                          // yet-unsaved changes
                          if (nodeRef.resolve(repository) == null) continue;

                          PsiElement psiNode = MPSPsiProvider.getInstance(project).getPsi(nodeRef);

                          // original node came from MPS index, it must be converted to our PSI
                          // element
                          assert psiNode instanceof MPSPsiNode;

                          consumer.process(new IdPrefixReference(mpsTarget, role, psiNode));
                        }
                        return true;
                      }
                    };

                FileBasedIndex.getInstance()
                    .processValues(
                        ForeignIdReferenceIndex.ID,
                        prefixToSearchWithDot,
                        null,
                        sReferenceProcessor,
                        truncatedScope);
              }
            });
  }
Пример #5
0
  @Override
  public void processQuery(
      @NotNull SearchParameters queryParameters, final @NotNull Processor<PsiReference> consumer) {
    if (!(queryParameters.getEffectiveSearchScope() instanceof GlobalSearchScope)) {
      return;
    }

    final GlobalSearchScope scope = (GlobalSearchScope) queryParameters.getEffectiveSearchScope();

    final PsiElement psiTarget = queryParameters.getElementToSearch();
    if (psiTarget instanceof MPSPsiNodeBase) return;

    final Project project = psiTarget.getProject();
    final MPSPsiProvider psiProvider = MPSPsiProvider.getInstance(project);
    SRepository repository = ProjectHelper.getProjectRepository(project);

    repository
        .getModelAccess()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {
                if (DumbService.getInstance(project).isDumb()) {
                  return;
                }

                if (psiTarget instanceof LightElement) {
                  // we don't handle light psi elements we don't know about
                  // we may not be able to compute their node id and their Java meaning can be
                  // represented in baseLanguage
                  // in a special way
                  return;
                }

                // if MPSReferenceSearch is moved to mps-core, it will be
                // MPS2PsiMapperUtil.getNodeId
                final SNode targetNode = getNodeForElement(psiTarget);
                if (targetNode == null) {
                  // it can't be referenced from MPS
                  return;
                }

                Set<SNode> targetNodes = new HashSet<SNode>(1);
                targetNodes.add(targetNode);

                Set<SReference> references;
                try {
                  references =
                      FindUsagesFacade.getInstance()
                          .findUsages(new IdeaSearchScope(scope), targetNodes, null);
                } catch (IndexNotReadyException e) {
                  // DumbService doesn't seem to work
                  return;
                }

                for (SReference sReference : references) {
                  SNode source = sReference.getSourceNode();
                  MPSPsiNode psiNode = (MPSPsiNode) psiProvider.getPsi(source);
                  // the source could have come from the psi stub itself
                  if (psiNode == null) return;
                  String refRole = sReference.getRole();
                  MPSPsiRef[] refs = psiNode.getReferences(refRole);
                  if (refs.length == 0) continue;

                  for (MPSPsiRef r : refs) {
                    if (targetNode.getNodeId().equals(r.getNodeId())) {
                      // it's our reference: giving it out to find usages
                      consumer.process(r.getReference());
                    }
                  }
                }
              }
            });
  }
Пример #6
0
  // Maybe will go to MPS2PsiMapper
  @Nullable
  public static SNode getNodeForElement(PsiElement element) {
    // baseLanguage specific check
    if (!(element instanceof PsiClass
        || element instanceof PsiMethod
        || element instanceof PsiField)) {
      return null;
    }

    PsiFile psiFile = element.getContainingFile();
    if (!(psiFile instanceof PsiJavaFile)) {
      return null;
    }

    if (PsiManager.getInstance(element.getProject()).isInProject(element)) {
      // It must be sources, try psi stubs
      // There might be psi stubs for this element, but there also might not (e.g. if it's inside a
      // module
      // with no MPS facet)

      NodePtr nodePtr = JavaForeignIdBuilder.computeNodePtr(element);
      if (nodePtr == null) {
        return null;
      }
      SNode node =
          nodePtr
              .toSNodeReference()
              .resolve(ProjectHelper.getProjectRepository(element.getProject()));

      return node;

    } else {
      // It must be from a library or SDK or something like that
      // Trying to find a suitable node in a class stub model
      SNodeId nodeId = null;
      if (element instanceof PsiClass) {
        nodeId = ASMNodeId.createId(((PsiClass) element).getQualifiedName());

      } else if (element instanceof PsiField) {
        PsiClass clas = ((PsiField) element).getContainingClass();
        String clasFqName = clas.getQualifiedName();
        nodeId = ASMNodeId.createFieldId(clasFqName, ((PsiField) element).getName());

      } else if (element instanceof PsiMethod) {
        // TODO argument types must be handled like they are in ASMNodeId (via asm classes)
      }

      if (nodeId == null) {
        // can't do anything about it
        return null;
      }

      String packageName = ((PsiJavaFile) psiFile).getPackageName();
      for (SModel model :
          new ModuleRepositoryFacade(ProjectHelper.getProjectRepository(element.getProject()))
              .getAllModels()) {
        if (!(model instanceof JavaClassStubModelDescriptor)) continue;
        if (!packageName.equals(model.getName().getLongName())) {
          continue;
        }
        SNode node = model.getNode(nodeId);
        if (node == null) continue;
        return node;
      }
    }

    return null;
  }