コード例 #1
0
  private void smartPaste(IDocument document, DocumentCommand command) {
    int newOffset = command.offset;
    int newLength = command.length;
    String newText = command.text;

    try {
      JavaHeuristicScanner scanner = new JavaHeuristicScanner(document);
      JavaIndenter indenter = new JavaIndenter(document, scanner, fProject);
      int offset = newOffset;

      // reference position to get the indent from
      int refOffset = indenter.findReferencePosition(offset);
      if (refOffset == JavaHeuristicScanner.NOT_FOUND) return;
      int peerOffset = getPeerPosition(document, command);
      peerOffset = indenter.findReferencePosition(peerOffset);
      if (peerOffset != JavaHeuristicScanner.NOT_FOUND) refOffset = Math.min(refOffset, peerOffset);

      // eat any WS before the insertion to the beginning of the line
      int firstLine =
          1; // don't format the first line per default, as it has other content before it
      IRegion line = document.getLineInformationOfOffset(offset);
      String notSelected = document.get(line.getOffset(), offset - line.getOffset());
      if (notSelected.trim().length() == 0) {
        newLength += notSelected.length();
        newOffset = line.getOffset();
        firstLine = 0;
      }

      // prefix: the part we need for formatting but won't paste
      IRegion refLine = document.getLineInformationOfOffset(refOffset);
      String prefix = document.get(refLine.getOffset(), newOffset - refLine.getOffset());

      // handle the indentation computation inside a temporary document
      Document temp = new Document(prefix + newText);
      DocumentRewriteSession session =
          temp.startRewriteSession(DocumentRewriteSessionType.STRICTLY_SEQUENTIAL);
      scanner = new JavaHeuristicScanner(temp);
      indenter = new JavaIndenter(temp, scanner, fProject);
      installJavaStuff(temp);

      // indent the first and second line
      // compute the relative indentation difference from the second line
      // (as the first might be partially selected) and use the value to
      // indent all other lines.
      boolean isIndentDetected = false;
      StringBuffer addition = new StringBuffer();
      int insertLength = 0;
      int firstLineInsertLength = 0;
      int firstLineIndent = 0;
      int first = document.computeNumberOfLines(prefix) + firstLine; // don't format first line
      int lines = temp.getNumberOfLines();
      int tabLength = getVisualTabLengthPreference();
      boolean changed = false;
      for (int l = first;
          l < lines;
          l++) { // we don't change the number of lines while adding indents

        IRegion r = temp.getLineInformation(l);
        int lineOffset = r.getOffset();
        int lineLength = r.getLength();

        if (lineLength == 0) // don't modify empty lines
        continue;

        if (!isIndentDetected) {

          // indent the first pasted line
          String current = getCurrentIndent(temp, l);
          StringBuffer correct = indenter.computeIndentation(lineOffset);
          if (correct == null) return; // bail out

          insertLength = subtractIndent(correct, current, addition, tabLength);
          if (l == first) {
            firstLineInsertLength = insertLength;
            firstLineIndent = current.length();
          }
          if (l != first && temp.get(lineOffset, lineLength).trim().length() != 0) {
            isIndentDetected = true;
            if (firstLineIndent >= current.length()) insertLength = firstLineInsertLength;
            if (insertLength == 0) {
              // no adjustment needed, bail out
              if (firstLine == 0) {
                // but we still need to adjust the first line
                command.offset = newOffset;
                command.length = newLength;
                if (changed) break; // still need to get the leading indent of the first line
              }
              return;
            }
          } else {
            changed = insertLength != 0;
          }
        }

        // relatively indent all pasted lines
        if (insertLength > 0) addIndent(temp, l, addition, tabLength);
        else if (insertLength < 0) cutIndent(temp, l, -insertLength, tabLength);
      }

      removeJavaStuff(temp);
      temp.stopRewriteSession(session);
      newText = temp.get(prefix.length(), temp.getLength() - prefix.length());

      command.offset = newOffset;
      command.length = newLength;
      command.text = newText;

    } catch (BadLocationException e) {
      JavaPlugin.log(e);
    }
  }