Esempio n. 1
0
  /** Replaces a node with another, preserving attributes */
  public static SNode replaceWithAnother(@NotNull SNode node, SNode replacer) {
    SNode nodeParent = node.getParent();
    if (nodeParent == null) {
      SModel model = node.getModel();
      if (model != null) {
        node.delete();
        model.addRootNode(replacer);
      }
      return replacer;
    }

    SContainmentLink role = node.getContainmentLink();
    assert role != null;

    if (replacer != null) {
      // old and new child can have the same node Id
      // thus it is important to remove old child first
      SNode anchor = node.getNextSibling();
      nodeParent.removeChild(node);
      SNode replacerParent = replacer.getParent();
      if (replacerParent != null) {
        replacerParent.removeChild(replacer);
      }
      nodeParent.insertChildBefore(role, replacer, anchor);
    } else {
      nodeParent.removeChild(node);
    }

    return replacer;
  }
  private static List<INodeSubstituteAction> createPrimaryChildSubstituteActions(
      SNode parentNode,
      SNode currentChild,
      SNode childConcept,
      IChildNodeSetter childSetter,
      IOperationContext context) {

    if (childConcept == null) {
      return Collections.emptyList();
    }
    final IScope scope = context.getScope();

    String childConceptFqName = NameUtil.nodeFQName(childConcept);
    Set<String> concepts = new HashSet<String>();
    for (Language l : SModelOperations.getLanguages(parentNode.getModel(), scope)) {
      concepts.addAll(
          LanguageHierarchyCache.getInstance()
              .getDefaultSubstitutableDescendantsOf(childConceptFqName, l));
    }

    List<INodeSubstituteAction> actions = new ArrayList<INodeSubstituteAction>();
    for (String fqName : concepts) {
      SNode applicableConcept = SModelUtil.findConceptDeclaration(fqName, scope);
      assert applicableConcept != null : "No concept " + fqName;
      actions.addAll(
          createDefaultActions(applicableConcept, parentNode, currentChild, childSetter, context));
    }

    return actions;
  }
Esempio n. 3
0
  public boolean canExecute(EditorContext context) {
    EditorCell selectedCell = getCellToPasteTo((EditorCell) context.getSelectedCell());
    if (selectedCell == null) {
      return false;
    }
    SNode selectedNode = selectedCell.getSNode();
    if (selectedNode == null || jetbrains.mps.util.SNodeOperations.isDisposed(selectedNode)) {
      return false;
    }
    List<SNode> pasteNodes = CopyPasteUtil.getNodesFromClipboard(selectedNode.getModel());
    if (pasteNodes == null || pasteNodes.isEmpty()) {
      return CopyPasteUtil.isConversionAvailable(selectedNode.getModel(), selectedNode);
    }

    if (!new NodePaster(pasteNodes).canPaste(selectedCell)) {
      LOG.debug("Couldn't paste node here");
      return false;
    }
    return true;
  }
Esempio n. 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());
  }
Esempio n. 5
0
  public void execute(final EditorContext context) {
    LOG.assertInCommand();
    final EditorComponent editorComponent = (EditorComponent) context.getEditorComponent();
    EditorCell pasteTargetCell = getCellToPasteTo(editorComponent.getSelectedCell());
    final CellInfo pasteTargetCellInfo = pasteTargetCell.getCellInfo();
    final SNode nodeSelected = pasteTargetCell.getSNode();
    final SNodePointer selectedNodePointer = new SNodePointer(nodeSelected);
    final SModel model = nodeSelected.getModel();
    // sometimes model is not in repository (paste in merge dialog)
    final boolean inRepository = model.getModelDescriptor() == selectedNodePointer.getModel();

    PasteNodeData data = CopyPasteUtil.getPasteNodeDataFromClipboard(model);
    if (data == null || data.getNodes().isEmpty()) {
      data =
          CopyPasteUtil.getConvertedFromClipboard(
              model, context.getOperationContext().getProject());
      if (data == null || data.getNodes().isEmpty()) return;
    }
    final PasteNodeData pasteNodeData = data;

    SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            final Runnable addImportsRunnable =
                CopyPasteUtil.addImportsWithDialog(
                    pasteNodeData, model, context.getOperationContext());
            ModelAccess.instance()
                .runCommandInEDT(
                    new Runnable() {
                      public void run() {
                        if (addImportsRunnable != null) {
                          addImportsRunnable.run();
                        }
                        SNode selectedNode =
                            inRepository ? selectedNodePointer.getNode() : nodeSelected;
                        if (jetbrains.mps.util.SNodeOperations.isDisposed(selectedNode)) {
                          StringBuilder errorText =
                              new StringBuilder(
                                  "Selected node is disposed: " + selectedNode.toString());
                          SModelReference modelReference = selectedNodePointer.getModelReference();
                          if (modelReference != null) {
                            SModelDescriptor modelDescriptor =
                                SModelRepository.getInstance().getModelDescriptor(modelReference);
                            if (modelDescriptor != null) {
                              SModel sModel = modelDescriptor.getSModel();
                              errorText.append(", sModel.isDisposed(): " + sModel.isDisposed());
                              SNode node = sModel.getNodeById(selectedNodePointer.getNodeId());
                              if (node != null) {
                                errorText.append(
                                    ", node != null, node.isDisposed(): "
                                        + jetbrains.mps.util.SNodeOperations.isDisposed(node));
                              } else {
                                errorText.append(", node == null");
                              }
                            }
                          }
                          LOG.error(errorText.toString());
                          return;
                        }
                        EditorCell selectedCell = pasteTargetCellInfo.findCell(editorComponent);
                        assert selectedCell != null;

                        List<SNode> pasteNodes = pasteNodeData.getNodes();

                        if (canPasteBefore(selectedCell, pasteNodes)) {
                          new NodePaster(pasteNodes)
                              .pasteRelative(selectedNode, PastePlaceHint.BEFORE_ANCHOR);
                        } else {
                          new NodePaster(pasteNodes).paste(selectedCell);
                        }

                        Set<SReference> requireResolveReferences = new HashSet<SReference>();
                        for (SReference ref : pasteNodeData.getRequireResolveReferences()) {
                          // ref can be detached from model while using copy/paste handlers
                          if (ref.getSourceNode() == null || ref.getSourceNode().getModel() == null)
                            continue;
                          requireResolveReferences.add(ref);
                        }

                        ResolverComponent.getInstance()
                            .resolveScopesOnly(
                                requireResolveReferences, context.getOperationContext());

                        // set selection
                        editorComponent.flushEvents();
                        EditorCell nodeCell = editorComponent.findNodeCell(pasteNodes.get(0));
                        if (nodeCell == null) return; // after 'set reference'?

                        EditorCell_Label labelCell =
                            nodeCell.findChild(CellFinders.byClass(EditorCell_Label.class, true));
                        if (labelCell != null) {
                          editorComponent.changeSelection(labelCell);
                        }

                        if (pasteNodes.size() == 1) {
                          editorComponent.pushSelection(nodeCell);
                        } else {
                          SNode firstNodeToSelect = pasteNodes.get(0);
                          SNode lastNodeToSelect = null;
                          for (int i = pasteNodes.size() - 1;
                              i > 0 && lastNodeToSelect == null;
                              i--) {
                            if (pasteNodes.get(i).getParent() == firstNodeToSelect.getParent()) {
                              lastNodeToSelect = pasteNodes.get(i);
                            }
                          }
                          if (lastNodeToSelect != null) {
                            SelectionManager selectionManager =
                                editorComponent.getSelectionManager();
                            selectionManager.pushSelection(
                                selectionManager.createRangeSelection(
                                    firstNodeToSelect, lastNodeToSelect));
                          }
                        }
                      }
                    },
                    context.getOperationContext().getProject());
          }
        });
  }
 public void editNode(final SNode node, final IOperationContext context, final boolean focus) {
   ModelAccess.assertLegalWrite();
   NavigationSupport.getInstance()
       .openNode(context, node, focus, !(node.getModel() != null && node.getModel().isRoot(node)));
 }
  private static List<INodeSubstituteAction> createActions_internal(
      SNode parentNode,
      SNode currentChild,
      SNode childConcept,
      IChildNodeSetter childSetter,
      IOperationContext context) {
    List<INodeSubstituteAction> resultActions = new ArrayList<INodeSubstituteAction>();
    if (childConcept == null) {
      return resultActions;
    }

    // special case
    if (childConcept == SModelUtil.getBaseConcept()) {
      if ((currentChild == null
          || currentChild.getConcept().getId().equals(SNodeUtil.concept_BaseConcept))) {
        resultActions = new ArrayList<INodeSubstituteAction>();
        ISearchScope conceptsSearchScope =
            SModelSearchUtil.createConceptsFromModelLanguagesScope(
                parentNode.getModel(), true, context.getScope());
        List<SNode> allVisibleConcepts = conceptsSearchScope.getNodes();
        for (final SNode visibleConcept : allVisibleConcepts) {
          resultActions.add(
              new DefaultChildNodeSubstituteAction(
                  visibleConcept, parentNode, currentChild, childSetter, context.getScope()) {
                public String getMatchingText(String pattern) {
                  return getMatchingText(pattern, true, true);
                }

                public String getVisibleMatchingText(String pattern) {
                  return getMatchingText(pattern);
                }

                public String getDescriptionText(String pattern) {
                  String fqName = NameUtil.nodeFQName(visibleConcept);
                  return "lang: "
                      + NameUtil.compactNamespace(NameUtil.namespaceFromConceptFQName(fqName));
                }

                public Icon getIconFor(String pattern) {
                  return getIconFor(pattern, true);
                }
              });
        }
        return resultActions;
      }

      // pretend we are going to substitute more concrete concept
      childConcept = ChildSubstituteActionsUtil.getRefinedChildConcept(currentChild);
    }

    Language primaryLanguage = SModelUtil.getDeclaringLanguage(childConcept);
    if (primaryLanguage == null) {
      LOG.error(
          "Couldn't build actions : couldn't get declaring language for concept "
              + org.jetbrains.mps.openapi.model.SNodeUtil.getDebugText(childConcept));
      return resultActions;
    }

    List<SNode> allBuilders =
        ChildSubstituteActionsUtil.getActionsBuilders(
            parentNode, currentChild, childConcept, childSetter, context);
    if (!ChildSubstituteActionsUtil.containsRemoveDefaults(allBuilders)) {
      resultActions.addAll(
          createPrimaryChildSubstituteActions(
              parentNode, currentChild, childConcept, childSetter, context));
    }

    for (SNode builder : allBuilders) {
      List<INodeSubstituteAction> addActions =
          ChildSubstituteActionsUtil.invokeActionFactory(
              builder, parentNode, currentChild, childConcept, childSetter, context);
      resultActions.addAll(addActions);
    }

    for (SNode builder : allBuilders) {
      resultActions =
          ChildSubstituteActionsUtil.applyActionFilter(
              builder, resultActions, parentNode, currentChild, childConcept, context);
    }

    if (childSetter instanceof DefaultChildNodeSetter
        || childSetter instanceof AbstractCellMenuPart_ReplaceNode_CustomNodeConcept
            && currentChild != null) {
      SNode linkDeclaration;
      if (childSetter instanceof DefaultChildNodeSetter) {
        linkDeclaration = ((DefaultChildNodeSetter) childSetter).myLinkDeclaration;
      } else {
        linkDeclaration = currentChild.getRoleLink();
      }

      Iterator<INodeSubstituteAction> it = resultActions.iterator();
      while (it.hasNext()) {
        INodeSubstituteAction action = it.next();

        SNode conceptNode = action.getOutputConcept();
        if (conceptNode == null) {
          continue;
        }

        if (!ModelConstraintsManager.canBeParent(parentNode, conceptNode, linkDeclaration, context)
            || !ModelConstraintsManager.canBeAncestor(parentNode, conceptNode, context)) {
          it.remove();
        }
      }
    }

    return resultActions;
  }