@NotNull
  public static Set<SModuleReference> getModules(SRepository repository, final Library library) {
    if (!ModuleLibraryType.isModuleLibrary(library)) {
      return Collections.emptySet();
    }
    final Set<SModuleReference> modules = new HashSet<SModuleReference>();
    final Set<IFile> moduleXmls = new HashSet<IFile>();
    for (VirtualFile file : library.getFiles(ModuleXmlRootDetector.MPS_MODULE_XML)) {
      moduleXmls.add(VirtualFileUtils.toIFile(file));
    }

    repository
        .getModelAccess()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {
                for (IFile moduleDescriptor : moduleXmls) {
                  SModule moduleByFile =
                      ModuleFileTracker.getInstance().getModuleByFile(moduleDescriptor);
                  if (moduleByFile != null) {
                    modules.add(moduleByFile.getModuleReference());
                  }
                }
              }
            });
    return modules;
  }
  @Override
  public SModel resolve(SRepository repo) {
    if (myModuleReference != null) {
      final SRepository repository;
      if (repo == null) {
        // see StaticReference, which seems to be the only place we pass null as repository
        repository = MPSModuleRepository.getInstance();
      } else {
        repository = repo;
      }
      Computable<SModel> c =
          new Computable<SModel>() {
            @Override
            public SModel compute() {
              SModule module = repository.getModule(myModuleReference.getModuleId());
              if (module == null) {
                return null;
              }
              return module.getModel(myModelId);
            }
          };
      if (!repository.getModelAccess().canRead()) {
        LOG.warn(
            "Attempt to resolve a model not from read action. What are you going to do with return value? Hint: at least, read. Please ensure proper model access then.",
            new Throwable());
        return new ModelAccessHelper(repository).runReadAction(c);
      } else {
        return c.compute();
      }
    }

    // FIXME !!! use supplied SRepository, not global model repo !!!
    // If there's no module reference, and model id is global, it's supposed we shall get the model
    // from a global repository.
    // However, at the moment, there's no easy way to get model from SRepository (other than to
    // iterate over all modules and models,
    // which doesn't sound like a good approach). Either shall provide method to find model from
    // SRepository, or drop
    // 'globally unique' model id altogether. What's the benefit of them?

    // NOTE, shall tolerate null repo unless every single piece of code that expects StaticReference
    // of a newly created node
    // hanging in the air to resolve. @see StaticReference#getTargetSModel
    return SModelRepository.getInstance().getModelDescriptor(this);
  }
 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());
 }
Exemple #4
0
  /**
   * Returns whether the given node belongs to the repository (or to one of its parent
   * repositories).
   */
  public static boolean isAccessible(@NotNull SNode node, @NotNull SRepository inRepository) {
    SModel model = node.getModel();
    if (model == null) return false;

    SRepository mrep = model.getRepository();
    if (mrep == null) return false;

    mrep.getModelAccess().checkReadAccess();

    if (inRepository == mrep) {
      return true;
    }
    // FIXME this is a hack to deal with incomplete story of repository relationship.
    // We have at least two repositories, ProjectRepository and MPSModuleRepository, and with
    // repository.getParent() dropped, there are no chance
    // to figure out node coming from MPSModuleRepository is visible in ProjectRepository
    // (EditorComponent.editNode() passes here project's repository
    // but node might come from an MPSModuleRepository (e.g. temp node from console), and they don't
    // match.
    // Here, assume node is accessible even if repositories are different if its module is identical
    // in both.
    inRepository.getModelAccess().checkReadAccess();
    return model.getModule() == inRepository.getModule(model.getModule().getModuleId());
  }
Exemple #5
0
 /**
  * recounting the status map
  *
  * @see #isChanged()
  */
 private void recountStatus() {
   if (!isChanged()) return;
   myRepository
       .getModelAccess()
       .runReadAction(
           new Runnable() {
             @Override
             public void run() {
               if (!isChanged()) return;
               LOG.debug("Recount status map for modules");
               boolean updated = myModuleUpdater.refreshGraph();
               Collection<SModuleReference> invalidModules = findInvalidModules();
               updated |= (!invalidModules.equals(myCurrentInvalidModules));
               if (updated) {
                 myCurrentInvalidModules = invalidModules;
                 refillStatusMap(invalidModules);
               }
             }
           });
 }
Exemple #6
0
  @NotNull
  private Collection<SModuleReference> findInvalidModules0(boolean errorLevel) {
    myRepository.getModelAccess().checkReadAccess();

    Map<ReloadableModule, AbsentDependencyException> modulesWithAbsentDeps =
        myModuleUpdater.getModulesWithAbsentDeps();
    Collection<SModuleReference> result = new HashSet<SModuleReference>();
    Collection<? extends SModuleReference> allModuleRefs = getAllModules();
    for (SModuleReference mRef : allModuleRefs) {
      if (!result.contains(mRef)) {
        String msg = getModuleProblemMessage(mRef, modulesWithAbsentDeps);
        if (msg == null) {
          continue;
        }
        if (errorLevel) LOG.error(msg);
        else LOG.debug(msg);
        result.add(mRef);
      }
    }
    return result;
  }
  @Override
  public void doExecute(@NotNull final AnActionEvent event, final Map<String, Object> _params) {
    List<SModel> m = ((List<SModel>) MapSequence.fromMap(_params).get("models"));
    final Iterable<SModel> seq =
        ListSequence.fromList(m)
            .where(
                new IWhereFilter<SModel>() {
                  public boolean accept(SModel it) {
                    return !(it.isReadOnly()) && it.getSource() instanceof FileDataSource;
                  }
                });
    final SRepository repo =
        ((MPSProject) MapSequence.fromMap(_params).get("project")).getRepository();

    final FolderModelFactory filePerRootFactory =
        PersistenceRegistry.getInstance().getFolderModelFactory("file-per-root");

    repo.getModelAccess()
        .runWriteAction(
            new Runnable() {
              public void run() {
                // see MPS-18743
                repo.saveAll();
                for (SModel smodel : Sequence.fromIterable(seq)) {
                  IFile oldFile = ((FileDataSource) smodel.getSource()).getFile();
                  ModelRoot modelRoot = smodel.getModelRoot();
                  if (!(modelRoot instanceof FileBasedModelRoot)) {
                    continue;
                  }

                  SModel newModel = PersistenceUtil.loadModel(oldFile);
                  if (newModel == null) {
                    if (LOG.isEnabledFor(Level.ERROR)) {
                      LOG.error("cannot read " + smodel);
                    }
                    continue;
                  }

                  Iterable<SModel.Problem> problems =
                      Sequence.fromIterable(((Iterable<SModel.Problem>) newModel.getProblems()))
                          .where(
                              new IWhereFilter<SModel.Problem>() {
                                public boolean accept(SModel.Problem it) {
                                  return it.isError();
                                }
                              });
                  if (Sequence.fromIterable(problems).isNotEmpty()) {
                    if (LOG.isEnabledFor(Level.ERROR)) {
                      LOG.error(
                          "cannot read "
                              + smodel
                              + ": "
                              + Sequence.fromIterable(problems).first().getText());
                    }
                    continue;
                  }

                  try {
                    DataSource newSource =
                        filePerRootFactory.createNewSource(
                            (FileBasedModelRoot) modelRoot,
                            null,
                            newModel.getModelName(),
                            new HashMap<String, String>());
                    SModule module = smodel.getModule();
                    filePerRootFactory.save(newModel, newSource);
                    if (module != null) {
                      ((SModuleBase) module).unregisterModel((SModelBase) smodel);
                    }
                    oldFile.delete();
                    ((AbstractModule) module).updateModelsSet();
                  } catch (IOException ex) {
                    if (LOG.isEnabledFor(Level.ERROR)) {
                      LOG.error("cannot write " + smodel, ex);
                    }
                  } catch (ModelSaveException ex) {
                    // shouldn't happen
                    if (LOG.isEnabledFor(Level.ERROR)) {
                      LOG.error("cannot write " + smodel, ex);
                    }
                  }
                }
              }
            });
  }
Exemple #8
0
  /**
   * @return <code>true</code> to indicate generation success (what does constitute a success is,
   *     alas, undefined)
   */
  private boolean process0(
      @NotNull final ProgressMonitor monitor, @NotNull final List<? extends GeneratorTask> tasks) {
    final boolean[] result = new boolean[1];
    myTransientModelsProvider.startGeneration(myGenerationOptions.getNumberOfModelsToKeep());

    final GeneratorLoggerAdapter logger =
        new GeneratorLoggerAdapter(
            myMessageHandler,
            myGenerationOptions.isShowInfo(),
            myGenerationOptions.isShowWarnings());

    myRepository
        .getModelAccess()
        .runWriteAction(
            new Runnable() {
              @Override
              public void run() {
                for (GeneratorTask t : tasks) {
                  SModel d = t.getModel();
                  if (d instanceof EditableSModel && ((EditableSModel) d).needsReloading()) {
                    ((EditableSModel) d).reloadFromSource();
                    logger.info("Model " + d + " reloaded from disk.");
                  }
                  myTransientModelsProvider.createModule(d.getModule());
                }
              }
            });
    myTransientModelsProvider
        .initCheckpointModule(); // at the moment, starts write action, thus shall start outside of
                                 // read

    GenControllerContext ctx =
        new GenControllerContext(
            myRepository, myGenerationOptions, myTransientModelsProvider, myStreamProvider);
    GeneratorTaskListener<GeneratorTask> taskListener;
    if (myTaskListener != null) {
      taskListener = myTaskListener;
    } else {
      taskListener = new EmptyTaskListener();
    }

    final GenerationController gc = new GenerationController(tasks, ctx, taskListener, logger);
    myRepository
        .getModelAccess()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {
                result[0] =
                    UndoHelper.getInstance()
                        .runNonUndoableAction(
                            new Computable<Boolean>() {
                              @Override
                              public Boolean compute() {
                                return gc.generate(monitor);
                              }
                            });
              }
            });

    // XXX removeAllTransients done from make facet, perhaps publish shall be part of external code
    // as well?
    myTransientModelsProvider.publishAll();
    CleanupManager.getInstance().cleanup();
    return result[0];
  }
Exemple #9
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);
              }
            });
  }
Exemple #10
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());
                    }
                  }
                }
              }
            });
  }