private void ensurePositionCategoryInstalled(final IDocument document, LinkedModeModel model) {
    if (!document.containsPositionCategory(getCategory())) {
      document.addPositionCategory(getCategory());
      fUpdater = new InclusivePositionUpdater(getCategory());
      document.addPositionUpdater(fUpdater);

      model.addLinkingListener(
          new ILinkedModeListener() {

            /*
             * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel, int)
             */
            @Override
            public void left(LinkedModeModel environment, int flags) {
              ensurePositionCategoryRemoved(document);
            }

            @Override
            public void suspend(LinkedModeModel environment) {}

            @Override
            public void resume(LinkedModeModel environment, int flags) {}
          });
    }
  }
  public void start() {
    if (getActiveLinkedMode() != null) {
      // for safety; should already be handled in RenameDartElementAction
      fgActiveLinkedMode.startFullDialog();
      return;
    }

    ISourceViewer viewer = fEditor.getViewer();
    IDocument document = viewer.getDocument();
    fOriginalSelection = viewer.getSelectedRange();
    int offset = fOriginalSelection.x;

    try {
      fLinkedPositionGroup = new LinkedPositionGroup();
      prepareElement();
      if (fDartElement == null) {
        return;
      }

      if (viewer instanceof ITextViewerExtension6) {
        IUndoManager undoManager = ((ITextViewerExtension6) viewer).getUndoManager();
        if (undoManager instanceof IUndoManagerExtension) {
          IUndoManagerExtension undoManagerExtension = (IUndoManagerExtension) undoManager;
          IUndoContext undoContext = undoManagerExtension.getUndoContext();
          IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory();
          fStartingUndoOperation = operationHistory.getUndoOperation(undoContext);
        }
      }

      fOriginalName = nameNode.getName();
      final int pos = nameNode.getOffset();
      final List<ASTNode> sameNodes = Lists.newArrayList();
      nameNode
          .getRoot()
          .accept(
              new RecursiveASTVisitor<Void>() {
                @Override
                public Void visitSimpleIdentifier(SimpleIdentifier node) {
                  Element element = node.getElement();
                  element = getCanonicalElement(element);
                  if (Objects.equal(element, fDartElement)) {
                    sameNodes.add(node);
                  }
                  return super.visitSimpleIdentifier(node);
                }
              });

      // TODO: copied from LinkedNamesAssistProposal#apply(..):
      // sort for iteration order, starting with the node @ offset
      Collections.sort(
          sameNodes,
          new Comparator<ASTNode>() {
            @Override
            public int compare(ASTNode o1, ASTNode o2) {
              return rank(o1) - rank(o2);
            }

            /**
             * Returns the absolute rank of an <code>ASTNode</code>. Nodes preceding <code>pos
             * </code> are ranked last.
             *
             * @param node the node to compute the rank for
             * @return the rank of the node with respect to the invocation offset
             */
            private int rank(ASTNode node) {
              int relativeRank = node.getOffset() + node.getLength() - pos;
              if (relativeRank < 0) {
                return Integer.MAX_VALUE + relativeRank;
              } else {
                return relativeRank;
              }
            }
          });
      for (int i = 0; i < sameNodes.size(); i++) {
        ASTNode elem = sameNodes.get(i);
        LinkedPosition linkedPosition =
            new LinkedPosition(document, elem.getOffset(), elem.getLength(), i);
        if (i == 0) {
          fNamePosition = linkedPosition;
        }
        fLinkedPositionGroup.addPosition(linkedPosition);
      }

      fLinkedModeModel = new LinkedModeModel();
      fLinkedModeModel.addGroup(fLinkedPositionGroup);
      fLinkedModeModel.forceInstall();
      fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor));
      fLinkedModeModel.addLinkingListener(new EditorSynchronizer());

      LinkedModeUI ui = new EditorLinkedModeUI(fLinkedModeModel, viewer);
      ui.setExitPosition(viewer, offset, 0, Integer.MAX_VALUE);
      ui.setExitPolicy(new ExitPolicy(document));
      ui.enter();

      viewer.setSelectedRange(
          fOriginalSelection.x,
          fOriginalSelection.y); // by default, full word is selected; restore original selection

      if (viewer instanceof IEditingSupportRegistry) {
        IEditingSupportRegistry registry = (IEditingSupportRegistry) viewer;
        registry.register(fFocusEditingSupport);
      }

      openSecondaryPopup();
      //			startAnimation();
      fgActiveLinkedMode = this;

    } catch (BadLocationException e) {
      DartToolsPlugin.log(e);
    }
  }
Example #3
0
  @Override
  public void apply(final ITextViewer viewer, char trigger, int stateMask, final int offset) {
    try {
      fLocations = null;
      Point selection = viewer.getSelectedRange();
      final int secectionOffset = selection.x;
      final int selectionLength = selection.y;

      ASTProvider.getASTProvider()
          .runOnAST(
              fTranslationUnit,
              ASTProvider.WAIT_ACTIVE_ONLY,
              new NullProgressMonitor(),
              new ASTRunnable() {
                @Override
                public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot)
                    throws CoreException {
                  if (astRoot == null) return Status.CANCEL_STATUS;

                  IASTNodeSelector selector = astRoot.getNodeSelector(null);
                  IASTName name = selector.findEnclosingName(secectionOffset, selectionLength);
                  if (name != null) {
                    fLocations = LinkedNamesFinder.findByName(astRoot, name);
                  }
                  return Status.OK_STATUS;
                }
              });

      if (fLocations == null || fLocations.length == 0) {
        return;
      }

      // Sort the locations starting with the one @ offset.
      Arrays.sort(
          fLocations,
          new Comparator<IRegion>() {
            @Override
            public int compare(IRegion n1, IRegion n2) {
              return rank(n1) - rank(n2);
            }

            /**
             * Returns the absolute rank of a location. Location preceding {@code offset} are ranked
             * last.
             *
             * @param location the location to compute the rank for
             * @return the rank of the location with respect to the invocation offset
             */
            private int rank(IRegion location) {
              int relativeRank = location.getOffset() + location.getLength() - offset;
              if (relativeRank < 0) {
                return Integer.MAX_VALUE + relativeRank;
              } else {
                return relativeRank;
              }
            }
          });

      IDocument document = viewer.getDocument();
      LinkedPositionGroup group = new LinkedPositionGroup();
      for (int i = 0; i < fLocations.length; i++) {
        IRegion item = fLocations[i];
        group.addPosition(new LinkedPosition(document, item.getOffset(), item.getLength(), i));
      }

      LinkedModeModel model = new LinkedModeModel();
      model.addGroup(group);
      model.forceInstall();
      CEditor editor = getCEditor();
      if (editor != null) {
        model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
      }

      LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
      ui.setExitPolicy(new DeleteBlockingExitPolicy(document));
      ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
      ui.enter();

      if (fValueSuggestion != null) {
        document.replace(fLocations[0].getOffset(), fLocations[0].getLength(), fValueSuggestion);
        IRegion selectedRegion = ui.getSelectedRegion();
        selection = new Point(selectedRegion.getOffset(), fValueSuggestion.length());
      }

      viewer.setSelectedRange(
          selection.x, selection.y); // By default full word is selected, restore original selection
    } catch (BadLocationException e) {
      CUIPlugin.log(e);
    }
  }
  public void start() {
    if (getActiveLinkedMode() != null) {
      // for safety; should already be handled in RenameDartElementAction
      fgActiveLinkedMode.startFullDialog();
      return;
    }

    ISourceViewer viewer = fEditor.getViewer();
    IDocument document = viewer.getDocument();
    fOriginalSelection = viewer.getSelectedRange();
    int offset = fOriginalSelection.x;

    try {
      DartUnit root =
          ASTProvider.getASTProvider().getAST(getCompilationUnit(), ASTProvider.WAIT_YES, null);

      fLinkedPositionGroup = new LinkedPositionGroup();
      DartNode selectedNode = NodeFinder.perform(root, fOriginalSelection.x, fOriginalSelection.y);
      if (!(selectedNode instanceof DartIdentifier)) {
        return; // TODO: show dialog
      }
      DartIdentifier nameNode = (DartIdentifier) selectedNode;

      if (viewer instanceof ITextViewerExtension6) {
        IUndoManager undoManager = ((ITextViewerExtension6) viewer).getUndoManager();
        if (undoManager instanceof IUndoManagerExtension) {
          IUndoManagerExtension undoManagerExtension = (IUndoManagerExtension) undoManager;
          IUndoContext undoContext = undoManagerExtension.getUndoContext();
          IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory();
          fStartingUndoOperation = operationHistory.getUndoOperation(undoContext);
        }
      }

      fOriginalName = nameNode.getName();
      final int pos = nameNode.getSourceInfo().getOffset();
      DartNode[] sameNodes = LinkedNodeFinder.findByNode(root, nameNode);

      // TODO: copied from LinkedNamesAssistProposal#apply(..):
      // sort for iteration order, starting with the node @ offset
      Arrays.sort(
          sameNodes,
          new Comparator<DartNode>() {
            @Override
            public int compare(DartNode o1, DartNode o2) {
              return rank(o1) - rank(o2);
            }

            /**
             * Returns the absolute rank of an <code>DartNode</code>. Nodes preceding <code>pos
             * </code> are ranked last.
             *
             * @param node the node to compute the rank for
             * @return the rank of the node with respect to the invocation offset
             */
            private int rank(DartNode node) {
              int relativeRank =
                  node.getSourceInfo().getOffset() + node.getSourceInfo().getLength() - pos;
              if (relativeRank < 0) {
                return Integer.MAX_VALUE + relativeRank;
              } else {
                return relativeRank;
              }
            }
          });
      for (int i = 0; i < sameNodes.length; i++) {
        DartNode elem = sameNodes[i];
        LinkedPosition linkedPosition =
            new LinkedPosition(
                document, elem.getSourceInfo().getOffset(), elem.getSourceInfo().getLength(), i);
        if (i == 0) {
          fNamePosition = linkedPosition;
        }
        fLinkedPositionGroup.addPosition(linkedPosition);
      }

      fLinkedModeModel = new LinkedModeModel();
      fLinkedModeModel.addGroup(fLinkedPositionGroup);
      fLinkedModeModel.forceInstall();
      fLinkedModeModel.addLinkingListener(new EditorHighlightingSynchronizer(fEditor));
      fLinkedModeModel.addLinkingListener(new EditorSynchronizer());

      LinkedModeUI ui = new EditorLinkedModeUI(fLinkedModeModel, viewer);
      ui.setExitPosition(viewer, offset, 0, Integer.MAX_VALUE);
      ui.setExitPolicy(new ExitPolicy(document));
      ui.enter();

      viewer.setSelectedRange(
          fOriginalSelection.x,
          fOriginalSelection.y); // by default, full word is selected; restore original selection

      if (viewer instanceof IEditingSupportRegistry) {
        IEditingSupportRegistry registry = (IEditingSupportRegistry) viewer;
        registry.register(fFocusEditingSupport);
      }

      openSecondaryPopup();
      //			startAnimation();
      fgActiveLinkedMode = this;

    } catch (BadLocationException e) {
      DartToolsPlugin.log(e);
    }
  }
  /** @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent) */
  public void verifyKey(VerifyEvent event) {
    // early pruning to slow down normal typing as little as possible
    if (!event.doit || !isAutoInsertEnabled() || !isAutoInsertCharacter(event.character)) {
      return;
    }

    IDocument document = textViewer.getDocument();
    final Point selection = textViewer.getSelectedRange();
    final int offset = selection.x;
    final int length = selection.y;

    try {

      String scope = getScopeAtOffset(document, offset);
      if (fgCommentSelector.matches(scope)) {
        return;
      }

      if (length > 0) {
        wrapSelection(event, document, offset, length);
        return;
      }

      // Don't auto-close if next char is a letter or digit
      if (document.getLength() > offset) {
        char nextChar = document.getChar(offset);
        if (Character.isJavaIdentifierPart(nextChar)) {
          return;
        }
      }

      // Don't auto-close if we have an open pair!
      if (isUnclosedPair(
          event, document, offset)) // We have an open string or pair, just insert the single
      // character, don't do anything special
      {
        return;
      }

      final char closingCharacter = getPeerCharacter(event.character);
      // If this is the start char and there's no unmatched close char, insert the close char
      if (unpairedClose(event.character, closingCharacter, document, offset)) {
        return;
      }

      final StringBuffer buffer = new StringBuffer();
      buffer.append(event.character);
      buffer.append(closingCharacter);
      if (offset == document.getLength()) {
        String delim = null;
        if (document instanceof IDocumentExtension4) {
          delim = ((IDocumentExtension4) document).getDefaultLineDelimiter();
        }
        if (delim == null) {
          delim = System.getProperty("line.separator", "\r\n"); // $NON-NLS-1$ //$NON-NLS-2$
        }
        buffer.append(delim);
      }

      document.replace(offset, length, buffer.toString());

      BracketLevel level = new BracketLevel();
      fBracketLevelStack.push(level);

      LinkedPositionGroup group = new LinkedPositionGroup();
      group.addPosition(new LinkedPosition(document, offset + 1, 0, LinkedPositionGroup.NO_STOP));

      LinkedModeModel model = new LinkedModeModel();
      model.addLinkingListener(this);
      model.addGroup(group);
      model.forceInstall();

      // set up position tracking for our magic peers
      if (fBracketLevelStack.size() == 1) {
        document.addPositionCategory(CATEGORY);
        document.addPositionUpdater(fUpdater);
      }
      level.fFirstPosition = new Position(offset, 1);
      level.fSecondPosition = new Position(offset + 1, 1);
      document.addPosition(CATEGORY, level.fFirstPosition);
      document.addPosition(CATEGORY, level.fSecondPosition);

      level.fUI = new EditorLinkedModeUI(model, textViewer);
      level.fUI.setSimpleMode(true);
      level.fUI.setExitPolicy(
          new ExitPolicy(
              textViewer,
              closingCharacter,
              getEscapeCharacter(closingCharacter),
              fBracketLevelStack));
      level.fUI.setExitPosition(textViewer, offset + 2, 0, Integer.MAX_VALUE);
      level.fUI.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
      level.fUI.enter();

      IRegion newSelection = level.fUI.getSelectedRegion();
      textViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());

      event.doit = false;
    } catch (BadLocationException e) {
      CommonEditorPlugin.logError(e);
    } catch (BadPositionCategoryException e) {
      CommonEditorPlugin.logError(e);
    }
  }
  /*
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
   */
  @Override
  public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {

    IDocument document = viewer.getDocument();
    try {
      fContext.setReadOnly(false);
      int start;
      TemplateBuffer templateBuffer;
      try {
        beginCompoundChange(viewer);

        int oldReplaceOffset = getReplaceOffset();
        try {
          // this may already modify the document (e.g. add imports)
          templateBuffer = fContext.evaluate(fTemplate);
        } catch (TemplateException e1) {
          fSelectedRegion = fRegion;
          return;
        }

        start = getReplaceOffset();
        int shift = start - oldReplaceOffset;
        int end = Math.max(getReplaceEndOffset(), offset + shift);

        // insert template string
        if (end > document.getLength()) end = offset;
        String templateString = templateBuffer.getString();
        document.replace(start, end - start, templateString);
      } finally {
        endCompoundChange(viewer);
      }

      // translate positions
      LinkedModeModel model = new LinkedModeModel();
      TemplateVariable[] variables = templateBuffer.getVariables();

      MultiVariableGuess guess =
          fContext instanceof CompilationUnitContext
              ? ((CompilationUnitContext) fContext).getMultiVariableGuess()
              : null;

      boolean hasPositions = false;
      for (int i = 0; i != variables.length; i++) {
        TemplateVariable variable = variables[i];

        if (variable.isUnambiguous()) continue;

        LinkedPositionGroup group = new LinkedPositionGroup();

        int[] offsets = variable.getOffsets();
        int length = variable.getLength();

        LinkedPosition first;
        if (guess != null && variable instanceof MultiVariable) {
          first =
              new VariablePosition(
                  document, offsets[0] + start, length, guess, (MultiVariable) variable);
          guess.addSlave((VariablePosition) first);
        } else {
          String[] values = variable.getValues();
          ICompletionProposal[] proposals = new ICompletionProposal[values.length];
          for (int j = 0; j < values.length; j++) {
            ensurePositionCategoryInstalled(document, model);
            Position pos = new Position(offsets[0] + start, length);
            document.addPosition(getCategory(), pos);
            proposals[j] = new PositionBasedCompletionProposal(values[j], pos, length);
          }

          if (proposals.length > 1)
            first = new ProposalPosition(document, offsets[0] + start, length, proposals);
          else first = new LinkedPosition(document, offsets[0] + start, length);
        }

        for (int j = 0; j != offsets.length; j++)
          if (j == 0) group.addPosition(first);
          else group.addPosition(new LinkedPosition(document, offsets[j] + start, length));

        model.addGroup(group);
        hasPositions = true;
      }

      if (hasPositions) {
        model.forceInstall();
        JavaEditor editor = getJavaEditor();
        if (editor != null) {
          model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
        }

        LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
        ui.setExitPosition(viewer, getCaretOffset(templateBuffer) + start, 0, Integer.MAX_VALUE);
        ui.enter();

        fSelectedRegion = ui.getSelectedRegion();
      } else {
        fSelectedRegion = new Region(getCaretOffset(templateBuffer) + start, 0);
      }

    } catch (BadLocationException e) {
      JavaPlugin.log(e);
      openErrorDialog(viewer.getTextWidget().getShell(), e);
      fSelectedRegion = fRegion;
    } catch (BadPositionCategoryException e) {
      JavaPlugin.log(e);
      openErrorDialog(viewer.getTextWidget().getShell(), e);
      fSelectedRegion = fRegion;
    }
  }