Package org.eclipse.php.internal.ui.autoEdit

Source Code of org.eclipse.php.internal.ui.autoEdit.PairCurlyBracketAutoEditStrategy

/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.autoEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IRegion;
import org.eclipse.php.internal.core.documentModel.parser.regions.IPhpScriptRegion;
import org.eclipse.php.internal.core.documentModel.parser.regions.PHPRegionTypes;
import org.eclipse.php.internal.core.format.CurlyCloseIndentationStrategy;
import org.eclipse.php.internal.core.format.FormatterUtils;
import org.eclipse.php.internal.core.format.IndentationBaseDetector;
import org.eclipse.php.internal.ui.Logger;
import org.eclipse.php.internal.ui.text.PHPDocumentRegionEdgeMatcher;
import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;

/**
*
* @author guy.g
*
*/

public class PairCurlyBracketAutoEditStrategy implements
    IAfterNewLineAutoEditStrategy {
  private static final char CURLY_OPEN = '{';
  private static final char CURLY_CLOSE = '}';

  private static PHPDocumentRegionEdgeMatcher matcher = new PHPDocumentRegionEdgeMatcher();

  /**
   * get the php token according to the given sdRegion and offset.
   *
   * @param sdRegion
   * @param offset
   * @return
   */
  private ITextRegion getPhpToken(IStructuredDocumentRegion sdRegion,
      int offset) {
    try {
      // get the ITextRegionContainer region or PhpScriptRegion region
      ITextRegion tRegion = sdRegion.getRegionAtCharacterOffset(offset);
      int regionStart = sdRegion.getStartOffset(tRegion);

      // in case of container we have the extract the PhpScriptRegion
      if (tRegion instanceof ITextRegionContainer) {
        ITextRegionContainer container = (ITextRegionContainer) tRegion;
        tRegion = container.getRegionAtCharacterOffset(offset);
        regionStart += tRegion.getStart();
      }

      // find the specified php token in the PhpScriptRegion
      if (tRegion instanceof IPhpScriptRegion) {
        IPhpScriptRegion scriptRegion = (IPhpScriptRegion) tRegion;
        tRegion = scriptRegion.getPhpToken(offset - regionStart);

        return tRegion;
      }
    } catch (BadLocationException e) {
    }
    return null;
  }

  public int autoEditAfterNewLine(IStructuredDocument document,
      DocumentCommand command, StringBuffer buffer) {
    try {

      boolean isClosingParen = isClosingParen(document, command);
      int offset = command.offset;

      int rvPosition = offset + buffer.length();
      if (!isClosingParen) {
        rvPosition += copyRestOfLine(document, command, buffer);
      }

      boolean addCurlyClose = false;
      int curlyCloseCounter = 0;
      int currOffset = offset;
      IStructuredDocumentRegion sdRegion = document
          .getRegionAtCharacterOffset(currOffset);

      int regionStart = sdRegion.getStart();
      String text = sdRegion.getFullText();

      ITextRegion tRegion = null;
      int indexInText = text.length() - 1;
      while (indexInText >= 0) {
        char currChar = text.charAt(indexInText);
        if (currChar == CURLY_CLOSE) {
          tRegion = getPhpToken(sdRegion, regionStart + indexInText);
          if (tRegion == null
              || tRegion.getType() == PHPRegionTypes.PHP_CURLY_CLOSE) {
            curlyCloseCounter++;
          }
        } else if (currChar == CURLY_OPEN) {
          tRegion = getPhpToken(sdRegion, regionStart + indexInText);
          boolean found = false;
          if (tRegion != null) {
            if (tRegion.getType().equals(
                PHPRegionTypes.PHP_CURLY_OPEN)) {
              found = true;
            } else if (tRegion.getType().equals(
                PHPRegionTypes.PHP_TOKEN)
                && tRegion.getLength() == 2) {
              ITextRegion reg = sdRegion
                  .getRegionAtCharacterOffset(regionStart
                      + indexInText);
              int start = reg.getStart() + tRegion.getStart();
              if (text.substring(start, start + 2).equals("${")) { //$NON-NLS-1$
                found = true;
              }
            }
          }
          if (!found) {
            indexInText--;
            continue;
          }
          curlyCloseCounter--;
          if (curlyCloseCounter < 0) {
            if (matcher.match(document, regionStart + indexInText
                + 1) == null) {
              addCurlyClose = true;
              break;
            }
            curlyCloseCounter++;
          }
        }
        indexInText--;
      }

      if (addCurlyClose) {
        addCurlyCloseBracket(document, command, buffer);
      }
      if (isClosingParen) {
        rvPosition += copyRestOfLine(document, command, buffer);
      }

      return rvPosition;
    } catch (BadLocationException e) {
      Logger.logException(e);
    }
    return -1;
  }

  private boolean isClosingParen(IStructuredDocument document,
      DocumentCommand command) throws BadLocationException {
    // TODO Auto-generated method stub
    int documentLength = document.getLength();
    if (command.offset + command.length == documentLength) { // if we're at
                                  // the end
                                  // of the
                                  // document
                                  // then
                                  // nothing
                                  // to copy
      return false;
    }
    int offset = command.offset;
    IRegion lineInfo = document.getLineInformationOfOffset(offset);
    int endOffset = lineInfo.getOffset() + lineInfo.getLength();
    int whiteSpacesAdded = 0;
    int lengthToCopyDown = endOffset - offset;

    IStructuredDocumentRegion[] structuredDocumentRegions = document
        .getStructuredDocumentRegions(offset, lengthToCopyDown);
    if (structuredDocumentRegions != null
        && structuredDocumentRegions.length > 0) {
      IStructuredDocumentRegion structuredDocumentRegion = structuredDocumentRegions[0];
      ITextRegion firstRegion = structuredDocumentRegion.getFirstRegion();
      ITextRegion lastRegion = structuredDocumentRegion.getLastRegion();

      int xmlRelativeOffset = 0;

      // deal with PHP block within HTML tags
      if (!(firstRegion instanceof ContextRegion)) { // meaning
                              // "not-PHP-Resgion"
        ITextRegion regionAtCharacterOffset = structuredDocumentRegion
            .getRegionAtCharacterOffset(offset);
        if (regionAtCharacterOffset instanceof ContextRegionContainer) {
          ContextRegionContainer phpContext = (ContextRegionContainer) regionAtCharacterOffset;
          lastRegion = phpContext.getLastRegion();
          firstRegion = phpContext.getFirstRegion();
          xmlRelativeOffset = firstRegion.getLength();
        }

      }
      int absolutOffset = lastRegion.getStart()
          + structuredDocumentRegion.getStartOffset()
          + xmlRelativeOffset;
      if (absolutOffset <= endOffset && offset <= absolutOffset) {
        lengthToCopyDown = absolutOffset - offset;
        ;
      }
    }
    String lineEnd = document.get(offset, lengthToCopyDown).trim();
    if (lineEnd.startsWith(")") || lineEnd.startsWith("]")) { //$NON-NLS-1$ //$NON-NLS-2$
      return true;
    }
    return false;
  }

  /**
   * Copies the rest of the line (after the { ) into the buffer in order put
   * the text inside the curly brackets
   *
   * @return The number of characters the caret should be advanced at
   */
  private int copyRestOfLine(IStructuredDocument document,
      DocumentCommand command, StringBuffer buffer)
      throws BadLocationException {

    int documentLength = document.getLength();
    if (command.offset + command.length == documentLength) { // if we're at
                                  // the end
                                  // of the
                                  // document
                                  // then
                                  // nothing
                                  // to copy
      return 0;
    }
    int offset = command.offset;
    IRegion lineInfo = document.getLineInformationOfOffset(offset);
    int endOffset = lineInfo.getOffset() + lineInfo.getLength();
    int whiteSpacesAdded = 0;
    int lengthToCopyDown = endOffset - offset;

    IStructuredDocumentRegion[] structuredDocumentRegions = document
        .getStructuredDocumentRegions(offset, lengthToCopyDown);
    if (structuredDocumentRegions != null
        && structuredDocumentRegions.length > 0) {
      IStructuredDocumentRegion structuredDocumentRegion = structuredDocumentRegions[0];
      ITextRegion firstRegion = structuredDocumentRegion.getFirstRegion();
      ITextRegion lastRegion = structuredDocumentRegion.getLastRegion();

      int xmlRelativeOffset = 0;

      // deal with PHP block within HTML tags
      if (!(firstRegion instanceof ContextRegion)) { // meaning
                              // "not-PHP-Resgion"
        ITextRegion regionAtCharacterOffset = structuredDocumentRegion
            .getRegionAtCharacterOffset(offset);
        if (regionAtCharacterOffset instanceof ContextRegionContainer) {
          ContextRegionContainer phpContext = (ContextRegionContainer) regionAtCharacterOffset;
          lastRegion = phpContext.getLastRegion();
          firstRegion = phpContext.getFirstRegion();
          xmlRelativeOffset = firstRegion.getLength();
        }

      }
      int absolutOffset = lastRegion.getStart()
          + structuredDocumentRegion.getStartOffset()
          + xmlRelativeOffset;
      if (absolutOffset <= endOffset && offset <= absolutOffset) {
        lengthToCopyDown = absolutOffset - offset;
        ;
      }
    }
    String lineEnd = document.get(offset, lengthToCopyDown);

    // if there are spaces between the '{' and the text in the line
    // (or the end of line)then need to override them
    for (int i = 0; i < lineEnd.length(); i++) {
      char c = lineEnd.charAt(i);
      lengthToCopyDown--; // for every iteration, need copy one less char
      if (c == '\n' || c == '\r' || !Character.isWhitespace(c)) {
        command.length += i;
        lengthToCopyDown++; // incrementing one back...
        break;
      }
    }

    String trimmedLineEnd = lineEnd.trim();
    if (trimmedLineEnd.length() > 0 && trimmedLineEnd.charAt(0) == '}') {
      // if there is a } then there is a problem with
      // curlyCloseInsertionStrategy calc
      // and we need to add manually another indentation.
      int indentationSize = FormatterUtils.getFormatterCommonPrferences()
          .getIndentationSize(document);
      char indentationChar = FormatterUtils
          .getFormatterCommonPrferences()
          .getIndentationChar(document);
      for (int i = 0; i < indentationSize; i++) {
        buffer.append(indentationChar);
        whiteSpacesAdded++;
      }
      buffer.append(document.getLineDelimiter());
      IndentationBaseDetector indentationDetector = new IndentationBaseDetector(
          document);
      int baseline = indentationDetector.getIndentationBaseLine(
          document.getLineOfOffset(offset), offset, true);
      lineInfo = document.getLineInformation(baseline);
      String blanks = FormatterUtils.getLineBlanks(document, lineInfo);
      buffer.append(blanks);
    }

    // copying the rest of the line after the "{" ,
    // using length calculated according to regionEnd or EndOfLine
    offset += command.length;
    char nextChar = document.getChar(offset);
    for (int i = 0; lengthToCopyDown > 0; lengthToCopyDown--) {
      buffer.append(nextChar);
      command.length++;
      offset++;
      if (offset == documentLength) {
        break;
      }
      nextChar = document.getChar(offset);
    }

    return whiteSpacesAdded;
  }

  private final CurlyCloseIndentationStrategy curlyCloseIndentationStrategy = new CurlyCloseIndentationStrategy();

  private void addCurlyCloseBracket(IStructuredDocument document,
      DocumentCommand command, StringBuffer buffer) {

    buffer.append(document.getLineDelimiter());
    int lineIndex = document.getLineOfOffset(command.offset);
    try {
      IRegion lineInfo = document.getLineInformation(lineIndex);
      curlyCloseIndentationStrategy.placeMatchingBlanks(document, buffer,
          lineIndex, lineInfo.getOffset() + lineInfo.getLength());
    } catch (BadLocationException e) {
      Logger.logException(e);
    }

    buffer.append('}');
  }
}
TOP

Related Classes of org.eclipse.php.internal.ui.autoEdit.PairCurlyBracketAutoEditStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.