private void addExactInstances(SNode current, SNode concept, Set<SNode> result, IScope scope) {
   if (current.getConceptFqName().equals(NameUtil.nodeFQName(concept))) {
     result.add(current);
   }
   for (SNode child : current.getChildren()) {
     addExactInstances(child, concept, result, scope);
   }
 }
 private void addUsages(SNode current, Set<SNode> nodes, Set<SReference> result) {
   for (SReference ref : current.getReferences()) {
     if (nodes.contains(ref.getTargetNode())) {
       result.add(ref);
     }
   }
   for (SNode child : current.getChildren()) {
     addUsages(child, nodes, result);
   }
 }
 public SNode createChildNode(Object parameterObject, SModel model, String pattern) {
   SNode childNode =
       SModelUtil_new.instantiateConceptDeclaration(
           NameUtil.nodeFQName(mySmartConcept), model, GlobalScope.getInstance());
   String referentRole = SModelUtil.getGenuineLinkRole(mySmartReference);
   childNode.setReferenceTarget(referentRole, myReferentNode);
   NodeFactoryManager.setupNode(
       mySmartConcept, childNode, myCurrentChild, myParentNode, model, getScope());
   return childNode;
 }
Example #4
0
    /** Unlinks s from the stack. */
    void clean(SNode s) {
      s.item = null; // forget item
      s.waiter = null; // forget thread

      /*
       * At worst we may need to traverse entire stack to unlink
       * s. If there are multiple concurrent calls to clean, we
       * might not see s if another thread has already removed
       * it. But we can stop when we see any node known to
       * follow s. We use s.next unless it too is cancelled, in
       * which case we try the node one past. We don't check any
       * further because we don't want to doubly traverse just to
       * find sentinel.
       */

      SNode past = s.next;
      if (past != null && past.isCancelled()) past = past.next;

      // Absorb cancelled nodes at head
      SNode p;
      while ((p = head) != null && p != past && p.isCancelled()) casHead(p, p.next);

      // Unsplice embedded nodes
      while (p != null && p != past) {
        SNode n = p.next;
        if (n != null && n.isCancelled()) p.casNext(n, n.next);
        else p = n;
      }
    }
 public static SNode reverseList(SNode n) {
   SNode last = n;
   SNode dummy = new SNode(0);
   while (n != null) {
     SNode newNode = new SNode(n.key);
     newNode.next = dummy.next;
     dummy.next = newNode;
     n = n.next;
   }
   return dummy.next;
 }
  public static GenerationDependencies fromIncremental(
      Map<SNode, SNode> currentToOriginalMap,
      RootDependenciesBuilder[] roots,
      String modelHash,
      String parametersHash,
      IOperationContext operationContext,
      IncrementalGenerationStrategy incrementalStrategy,
      int skippedCount,
      int fromCacheCount) {
    Map<String, List<String>> generatedFiles = getGeneratedFiles(currentToOriginalMap);

    List<GenerationRootDependencies> unchanged = null;
    List<GenerationRootDependencies> rootDependencies =
        new ArrayList<GenerationRootDependencies>(roots.length);
    Map<String, String> externalHashes = new HashMap<String, String>();
    for (RootDependenciesBuilder l : roots) {
      SNode originalRoot = l.getOriginalRoot();
      List<String> files = generatedFiles.get(originalRoot != null ? originalRoot.getId() : "");
      if (files == null) {
        files = Collections.emptyList();
      }
      GenerationRootDependencies dep;
      if (l.isUnchanged()) {
        dep = l.getSavedDependencies();
        if (unchanged == null) {
          unchanged = new ArrayList<GenerationRootDependencies>();
        }
        unchanged.add(dep);
      } else {
        dep = GenerationRootDependencies.fromData(l, files);
      }
      rootDependencies.add(dep);
      for (String modelReference : dep.getExternal()) {
        if (!externalHashes.containsKey(modelReference)) {
          SModelDescriptor sm =
              SModelRepository.getInstance()
                  .getModelDescriptor(SModelReference.fromString(modelReference));
          Map<String, String> hashes = incrementalStrategy.getModelHashes(sm, operationContext);
          String value = hashes != null ? hashes.get(ModelDigestHelper.FILE) : null;
          externalHashes.put(modelReference, value);
        }
      }
    }
    return new GenerationDependencies(
        rootDependencies,
        modelHash,
        parametersHash,
        externalHashes,
        unchanged == null ? Collections.<GenerationRootDependencies>emptyList() : unchanged,
        skippedCount,
        fromCacheCount);
  }
Example #7
0
  private boolean canPasteBefore(EditorCell selectedCell, List<SNode> pasteNodes) {
    if (!selectedCell.isFirstPositionInBigCell()) return false;
    SNode anchor = selectedCell.getSNode();
    if (anchor.getParent() == null) return false;

    NodeAndRole nodeAndRole =
        new NodePaster(pasteNodes).getActualAnchorNode(anchor, anchor.getRoleInParent());
    if (nodeAndRole == null) return false;

    EditorCell targetCell = selectedCell.getEditor().findNodeCell(nodeAndRole.myNode);
    return targetCell != null
        && targetCell.getFirstLeaf(CellConditions.SELECTABLE) == selectedCell
        && new NodePaster(pasteNodes).canPasteRelative(nodeAndRole.myNode);
  }
  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;
  }
 public static String getFileName(SNode outputRootNode) {
   // TODO refactor, use DefaultFileGenerator.getFileName
   String extension = TextGenManager.instance().getExtension(outputRootNode);
   return (extension == null)
       ? outputRootNode.getName()
       : outputRootNode.getName() + "." + extension;
 }
  public Set<SNode> findDescendants(SNode node, Set<SNode> descendantsKnownInModel) {
    if (!myFindUsagesSupported) return new HashSet<SNode>();
    boolean changed = false;
    if (myModelDescriptor instanceof EditableSModelDescriptor) {
      changed = ((EditableSModelDescriptor) myModelDescriptor).isChanged();
    }
    boolean atLeastRootsLoaded =
        myModelDescriptor.getLoadingState().compareTo(ModelLoadingState.ROOTS_LOADED) >= 0;
    if (atLeastRootsLoaded && !changed && !descendantsKnownInModel.isEmpty())
      return descendantsKnownInModel;
    if (myNeedSearchForStrings
        && !myModelRootManager.containsString(myModelDescriptor, node.getId()))
      return descendantsKnownInModel;

    SModel model = myModelDescriptor.getSModel();
    Set<SNode> result = new HashSet<SNode>();
    if (model != null) {
      for (SNode root : model.roots()) {
        addDescendants(root, node, result);
      }
    }
    descendantsKnownInModel.clear();
    descendantsKnownInModel.addAll(result);
    return descendantsKnownInModel;
  }
Example #11
0
 /**
  * Spins/blocks until node s is matched by a fulfill operation.
  *
  * @param s the waiting node
  * @param timed true if timed wait
  * @param nanos timeout value
  * @return matched node, or s if cancelled
  */
 SNode awaitFulfill(SNode s, boolean timed, long nanos) {
   /*
    * When a node/thread is about to block, it sets its waiter
    * field and then rechecks state at least one more time
    * before actually parking, thus covering race vs
    * fulfiller noticing that waiter is non-null so should be
    * woken.
    *
    * When invoked by nodes that appear at the point of call
    * to be at the head of the stack, calls to park are
    * preceded by spins to avoid blocking when producers and
    * consumers are arriving very close in time.  This can
    * happen enough to bother only on multiprocessors.
    *
    * The order of checks for returning out of main loop
    * reflects fact that interrupts have precedence over
    * normal returns, which have precedence over
    * timeouts. (So, on timeout, one last check for match is
    * done before giving up.) Except that calls from untimed
    * SynchronousQueue.{poll/offer} don't check interrupts
    * and don't wait at all, so are trapped in transfer
    * method rather than calling awaitFulfill.
    */
   long lastTime = timed ? System.nanoTime() : 0;
   Thread w = Thread.currentThread();
   SNode h = head;
   int spins = (shouldSpin(s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0);
   for (; ; ) {
     if (w.isInterrupted()) s.tryCancel();
     SNode m = s.match;
     if (m != null) return m;
     if (timed) {
       long now = System.nanoTime();
       nanos -= now - lastTime;
       lastTime = now;
       if (nanos <= 0) {
         s.tryCancel();
         continue;
       }
     }
     if (spins > 0) spins = shouldSpin(s) ? (spins - 1) : 0;
     else if (s.waiter == null) s.waiter = w; // establish waiter so can park next iter
     else if (!timed) LockSupport.park(this);
     else if (nanos > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanos);
   }
 }
 /** Delete an entity, and its brain if there is one. Do not ask directly this method. */
 public void delete() {
   // System.out.println("Actually deleting " + this);
   if (deleted) return;
   deleted = true;
   if (myBrain != null) {
     if (myBrain instanceof AbstractAgent)
       getStructure().getAgent().doKillAgent((AbstractAgent) myBrain);
     else myBrain.delete();
   }
   super.delete();
 }
Example #13
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;
  }
  public Set<SReference> findUsages(Set<SNode> nodes) {
    if (!myFindUsagesSupported) return Collections.emptySet();

    if (myNeedSearchForStrings) {
      Set<String> strings = new HashSet<String>();
      for (SNode node : nodes) {
        strings.add(quoteSpecialXMLCharacters(node.getId()));
      }
      if (!myModelRootManager.containsSomeString(myModelDescriptor, strings))
        return Collections.emptySet();
    }

    SModel model = myModelDescriptor.getSModel();
    if (model == null) return Collections.emptySet();

    Set<SReference> result = new HashSet<SReference>();
    for (SNode root : model.roots()) {
      addUsages(root, nodes, result);
    }
    return result;
  }
  private void addDescendants(SNode current, SNode node, Set<SNode> result) {
    if (SNodeUtil.isInstanceOfConceptDeclaration(current)) {
      for (SNode interfaceConcept : SNodeUtil.getConceptDeclaration_Implements(current)) {
        if (interfaceConcept != null && interfaceConcept == node) {
          result.add(current);
          break;
        }
      }
      if (SNodeUtil.getConceptDeclaration_Extends(current) == node) {
        result.add(current);
      }
    } else if (SNodeUtil.isInstanceOfInterfaceConceptDeclaration(current)) {
      for (SNode interfaceConcept : SNodeUtil.getInterfaceConceptDeclaration_Extends(current)) {
        if (interfaceConcept != null && interfaceConcept == node) {
          result.add(interfaceConcept);
          break;
        }
      }
    }

    for (SNode child : current.getChildren()) { // are there any "inner" concepts?
      addDescendants(child, node, result);
    }
  }
Example #16
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());
  }
Example #17
0
    /** Puts or takes an item. */
    Object transfer(Object e, boolean timed, long nanos) {
      /*
       * Basic algorithm is to loop trying one of three actions:
       *
       * 1. If apparently empty or already containing nodes of same
       *    mode, try to push node on stack and wait for a match,
       *    returning it, or null if cancelled.
       *
       * 2. If apparently containing node of complementary mode,
       *    try to push a fulfilling node on to stack, match
       *    with corresponding waiting node, pop both from
       *    stack, and return matched item. The matching or
       *    unlinking might not actually be necessary because of
       *    other threads performing action 3:
       *
       * 3. If top of stack already holds another fulfilling node,
       *    help it out by doing its match and/or pop
       *    operations, and then continue. The code for helping
       *    is essentially the same as for fulfilling, except
       *    that it doesn't return the item.
       */

      SNode s = null; // constructed/reused as needed
      int mode = (e == null) ? REQUEST : DATA;

      for (; ; ) {
        SNode h = head;
        if (h == null || h.mode == mode) { // empty or same-mode
          if (timed && nanos <= 0) { // can't wait
            if (h != null && h.isCancelled()) casHead(h, h.next); // pop cancelled node
            else return null;
          } else if (casHead(h, s = snode(s, e, h, mode))) {
            SNode m = awaitFulfill(s, timed, nanos);
            if (m == s) { // wait was cancelled
              clean(s);
              return null;
            }
            if ((h = head) != null && h.next == s) casHead(h, s.next); // help s's fulfiller
            return (mode == REQUEST) ? m.item : s.item;
          }
        } else if (!isFulfilling(h.mode)) { // try to fulfill
          if (h.isCancelled()) // already cancelled
          casHead(h, h.next); // pop and retry
          else if (casHead(h, s = snode(s, e, h, FULFILLING | mode))) {
            for (; ; ) { // loop until matched or waiters disappear
              SNode m = s.next; // m is s's match
              if (m == null) { // all waiters are gone
                casHead(s, null); // pop fulfill node
                s = null; // use new node next time
                break; // restart main loop
              }
              SNode mn = m.next;
              if (m.tryMatch(s)) {
                casHead(s, mn); // pop both s and m
                return (mode == REQUEST) ? m.item : s.item;
              } else // lost match
              s.casNext(m, mn); // help unlink
            }
          }
        } else { // help a fulfiller
          SNode m = h.next; // m is h's match
          if (m == null) // waiter is gone
          casHead(h, null); // pop fulfilling node
          else {
            SNode mn = m.next;
            if (m.tryMatch(h)) // help match
            casHead(h, mn); // pop both h and m
            else // lost match
            h.casNext(m, mn); // help unlink
          }
        }
      }
    }
Example #18
0
 /**
  * Creates or resets fields of a node. Called only from transfer where the node to push on stack
  * is lazily created and reused when possible to help reduce intervals between reads and CASes
  * of head and to avoid surges of garbage when CASes to push nodes fail due to contention.
  */
 static SNode snode(SNode s, Object e, SNode next, int mode) {
   if (s == null) s = new SNode(e);
   s.mode = mode;
   s.next = next;
   return s;
 }
  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;
  }
 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> createSmartReferenceActions(
      final SNode smartConcept,
      final SNode smartReference,
      final SNode parentNode,
      final SNode currentChild,
      final IChildNodeSetter childSetter,
      final IOperationContext context) {

    if (parentNode == null) {
      return null;
    }

    // try to create referent-search-scope
    SNode linkDeclaration = null;
    int index = 0;
    if (currentChild != null) {
      linkDeclaration = currentChild.getRoleLink();
      index = parentNode.getChildren(currentChild.getRoleInParent()).indexOf(currentChild);
    }
    //    TODO generate wrapping setter to have access to original link
    //    if(childSetter instanceof WrappingSetter) {
    //      childSetter = ((WrappingSetter)childSetter).unwrap();
    //    }
    if (linkDeclaration == null && childSetter instanceof DefaultChildNodeSetter) {
      linkDeclaration = ((DefaultChildNodeSetter) childSetter).getLinkDeclaration();
    }

    //    TODO restore (when wrapping setter is created)
    //    if (linkDeclaration == null) {
    //      return null;
    //    }

    ReferenceDescriptor refDescriptor =
        ModelConstraintsUtil.getSmartReferenceDescriptor(
            parentNode,
            linkDeclaration == null ? null : SModelUtil.getLinkDeclarationRole(linkDeclaration),
            index,
            smartConcept);
    if (refDescriptor == null) return null;

    Scope searchScope = refDescriptor.getScope();
    if (searchScope == null) return null;

    // create smart actions
    final String targetConcept =
        NameUtil.nodeFQName(SModelUtil.getLinkDeclarationTarget(smartReference));
    List<INodeSubstituteAction> actions = new ArrayList<INodeSubstituteAction>();
    IReferencePresentation presentation = refDescriptor.getReferencePresentation();
    Iterable<SNode> referentNodes = searchScope.getAvailableElements(null);
    for (SNode referentNode : referentNodes) {
      if (referentNode == null
          || !referentNode
              .getConcept()
              .isSubConceptOf(SConceptRepository.getInstance().getConcept(targetConcept))) continue;
      actions.add(
          new SmartRefChildNodeSubstituteAction(
              referentNode,
              parentNode,
              currentChild,
              childSetter,
              context.getScope(),
              smartConcept,
              smartReference,
              presentation));
    }

    return actions;
  }
Example #22
0
 // todo move to snode class
 public static boolean isInstanceOf(@Nullable SNode node, @NotNull SAbstractConcept concept) {
   if (node == null) return false;
   SConcept c = node.getConcept();
   return c.isSubConceptOf(concept);
 }
 private void addInstances(SNode current, SNode concept, Set<SNode> result, IScope scope) {
   if (current.isInstanceOfConcept(NameUtil.nodeFQName(concept))) result.add(current);
   for (SNode child : current.getChildren()) {
     addInstances(child, concept, result, scope);
   }
 }
Example #24
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());
          }
        });
  }
Example #25
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;
  }