Package com.dubture.twig.ui.editor.autoEdit

Source Code of com.dubture.twig.ui.editor.autoEdit.QuotesAutoEditStrategy

/*******************************************************************************
* This file is part of the Twig eclipse plugin.
*
* (c) Robert Gruendler <r.gruendler@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
package com.dubture.twig.ui.editor.autoEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.php.internal.core.documentModel.parser.PHPRegionContext;
import org.eclipse.php.internal.core.documentModel.parser.regions.PHPRegionTypes;
import org.eclipse.php.internal.ui.Logger;
import org.eclipse.php.internal.ui.autoEdit.MatchingCharAutoEditStrategy;
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 com.dubture.twig.core.documentModel.parser.partitioner.TwigPartitionTypes;
import com.dubture.twig.core.documentModel.parser.regions.ITwigScriptRegion;
import com.dubture.twig.core.documentModel.parser.regions.TwigRegionTypes;
import com.dubture.twig.core.format.FormatterUtils;

/**
*
* A modified
* {@link org.eclipse.php.internal.ui.autoEdit.QuotesAutoEditStrategy} to make
* auto-closing quotes work with the Twig editor.
*
* @author "Robert Gruendler <r.gruendler@gmail.com>"
*
*/
@SuppressWarnings("restriction")
public class QuotesAutoEditStrategy extends MatchingCharAutoEditStrategy
{

    public void customizeDocumentCommand(IDocument document,
            DocumentCommand command)
    {

        if (/* TypingPreferences.closeQuotes && */command.text != null) {
            int length = command.text.length();
            if (length == 0 && command.length == 1) {
                try {
                    char removedChar = document.getChar(command.offset);
                    if (isQuote(removedChar)) {
                        deleteQuote((IStructuredDocument) document, command,
                                removedChar);
                    }

                } catch (BadLocationException e) {
                    Logger.logException(e);
                }
            }
            if (length == 1) {
                char c = command.text.charAt(0);
                if (isQuote(c)) {
                    autoAddPairQuote((IStructuredDocument) document, command, c);
                }
            }
        }
    }

    private void autoAddPairQuote(IStructuredDocument document,
            DocumentCommand command, char insertedChar)
    {
        int startOffset = command.offset;
        int endOffset = startOffset + command.length;

        try {
            String startState = FormatterUtils.getPartitionType(document,
                    startOffset, true);
            String endState = FormatterUtils.getPartitionType(document,
                    endOffset, true);
            if (startState == TwigPartitionTypes.TWIG_QUOTED_STRING
                    || endState == TwigPartitionTypes.TWIG_QUOTED_STRING
                    || (startState == TwigPartitionTypes.TWIG_DEFAULT
                            && endState == TwigPartitionTypes.TWIG_DEFAULT && document
                            .getChar(endOffset - 1) == '\'')) {
                if (endOffset < document.getLength()
                        && startOffset == endOffset) {
                    char nextChar = document.getChar(endOffset);
                    if (insertedChar == nextChar) {
                        char prevChar = document.getChar(startOffset - 1);
                        if (prevChar != BACK_SLASH) {
                            if (command.length == 0) {
                                adjustDocumentOffset(command);
                                command.text = ""; //$NON-NLS-1$
                            } else {
                                command.length++;
                            }
                        }
                    } else {
                        IStructuredDocumentRegion sdRegion = document
                                .getRegionAtCharacterOffset(startOffset);
                        ITextRegion tRegion = getPhpRegion(sdRegion,
                                startOffset);
                        // adding a specific char to close the qoute in case the
                        // 2 following conditions fulfilled:
                        // 1. The region ends with whitespace.
                        // 2. The command offest is located at the end of the
                        // region(include the region whitespace)
                        int regionLength = tRegion.getLength();
                        int regionTextLength = tRegion.getTextLength();
                        if (regionTextLength != regionLength
                                && startOffset > getRegionStart(sdRegion,
                                        startOffset) + regionTextLength
                                && shouldAddClosingBracket(document, endOffset,
                                        true)) {
                            command.text = command.text + insertedChar;
                            // making the change in the documet ourselfs and
                            // consuming the original command
                            document.replace(command.offset, command.length,
                                    command.text);
                            document.getUndoManager().disableUndoManagement();
                            document.replace(command.offset + 1, 0, ""); //$NON-NLS-1$
                            document.getUndoManager().enableUndoManagement();
                            adjustDocumentOffset(command);// this will cause the
                                                          // caret to be set
                                                          // between the
                                                          // quotes.
                            command.length = 0;
                            command.text = ""; //$NON-NLS-1$
                        }
                    }
                }
                return;
            }
            if (isQuoteAllowed(startState, insertedChar)) {
                if ((shouldAddClosingBracket(document, endOffset, true))) {
                    int result = isMatchingCharNeeded(document, endOffset,
                            insertedChar);
                    if (result == MATCHING_BRACKET_NEEDED) {
                        command.text = command.text + insertedChar;
                        // making the change in ther documet ourselfs and
                        // consuming the original command
                        document.replace(command.offset, command.length,
                                command.text);
                        document.getUndoManager().disableUndoManagement();
                        document.replace(command.offset + 1, 0, ""); //$NON-NLS-1$
                        document.getUndoManager().enableUndoManagement();
                        adjustDocumentOffset(command); // this will cause the
                                                       // caret to be set
                                                       // between the quotes.

                        command.length = 0;
                        command.text = ""; //$NON-NLS-1$
                    }
                }
            }

        } catch (BadLocationException e) {
            Logger.logException(e);
            document.getUndoManager().enableUndoManagement();
        }
    }

    /*
     * get php region by given IStructuredDocumentRegion and offset
     */
    private ITextRegion getPhpRegion(IStructuredDocumentRegion sdRegion,
            int offset) throws BadLocationException
    {
        ITextRegion tRegion = sdRegion.getRegionAtCharacterOffset(offset);

        if (tRegion.getType().equals(PHPRegionContext.PHP_CLOSE)) {
            offset--;
            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();
        }

        if (tRegion instanceof ITwigScriptRegion) {
            ITwigScriptRegion scriptRegion = (ITwigScriptRegion) tRegion;
            tRegion = scriptRegion.getTwigToken(offset - regionStart);
            return tRegion;
        }
        return null;
    }

    /*
     * get php region by given IStructuredDocumentRegion and offset
     */
    private int getRegionStart(IStructuredDocumentRegion sdRegion, int offset)
            throws BadLocationException
    {
        ITextRegion tRegion = sdRegion.getRegionAtCharacterOffset(offset);

        if (tRegion.getType().equals(PHPRegionContext.PHP_CLOSE)) {
            offset--;
            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();
        }
        if (tRegion instanceof ITwigScriptRegion) {
            ITwigScriptRegion scriptRegion = (ITwigScriptRegion) tRegion;
            tRegion = scriptRegion.getTwigToken(offset - regionStart);
            regionStart += tRegion.getStart();
        }
        return regionStart;
    }

    /**
     * returns true if the lexical state demands qoute balance
     */
    private boolean isQuoteAllowed(String state, char quote)
    {
        return (state == TwigPartitionTypes.TWIG_DEFAULT)
                || (state == PHPRegionTypes.PHP_OPENTAG)
                || (state == PHPRegionTypes.PHP_CLOSETAG);
    }

    public int isMatchingCharNeeded(IStructuredDocument document, int offset,
            char quoteChar)
    {
        try {
            String postCharState = FormatterUtils.getPartitionType(document,
                    offset, true);
            if (!(postCharState == TwigPartitionTypes.TWIG_DEFAULT
                    || postCharState == PHPRegionTypes.PHP_OPENTAG || postCharState == PHPRegionTypes.PHP_CLOSETAG)) {
                if (isSpecialOpenCurlyInQuotes(document, offset)) {
                    postCharState = FormatterUtils.getPartitionType(document,
                            offset + 1);
                }
            }

            if (postCharState != TwigPartitionTypes.TWIG_DEFAULT
                    && postCharState != PHPRegionTypes.PHP_OPENTAG
                    && postCharState != PHPRegionTypes.PHP_CLOSETAG) {
                return SEARCH_NOT_VALID;
            }
            if (FormatterUtils.getPartitionType(document,
                    document.getLength() - 1) == TwigPartitionTypes.TWIG_QUOTED_STRING) {
                IStructuredDocumentRegion sdRegion = document
                        .getLastStructuredDocumentRegion();
                ITextRegion tRegion = sdRegion.getLastRegion();
                char lastChar = document.getChar(sdRegion.getStartOffset()
                        + tRegion.getTextEnd() - 1);
                if (lastChar != quoteChar) {
                    return MATCHING_BRACKET_NOT_NEEDED;
                }
            }

        } catch (BadLocationException e) {
            Logger.logException(e);
        }
        return MATCHING_BRACKET_NEEDED;
    }

    private void deleteQuote(IStructuredDocument document,
            DocumentCommand command, char removedChar)
    {
        int offset = command.offset;

        IStructuredDocumentRegion sdRegion = document
                .getRegionAtCharacterOffset(offset);
        if (sdRegion == null
                || sdRegion.getType() != TwigRegionTypes.TWIG_CONTENT) {
            return;
        }
        try {
            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();
            }

            if (tRegion instanceof ITwigScriptRegion) {
                ITwigScriptRegion scriptRegion = (ITwigScriptRegion) tRegion;
                tRegion = scriptRegion.getTwigToken(offset - regionStart);

                if (tRegion == null
                        || tRegion.getType() != TwigRegionTypes.TWIG_CONSTANT_ENCAPSED_STRING) {
                    return;
                }

                if (offset != tRegion.getStart() + regionStart
                        || (tRegion.getTextLength() != 2 && !isBetweenBackquotes(
                                sdRegion, offset))) {
                    // looking only for the cases where the user is trying to
                    // remove the first quote out of two coupled ones.
                    return;
                }

                char nextChar = document.getChar(offset + 1);
                if (nextChar != removedChar) {
                    return;
                }
                command.length = 2;
            }
        } catch (BadLocationException e) {
        }
    }

    // fixed bug 172149 - The offset changed according to the PHP script region
    // offset
    private boolean isBetweenBackquotes(IStructuredDocumentRegion sdRegion,
            int offset) throws BadLocationException
    {
        if (sdRegion.getParentDocument().getLength() <= offset) {
            return false;
        }
        ITextRegion quoteRegion = getPhpRegion(sdRegion, offset);
        if (quoteRegion == null || quoteRegion.getLength() > 1) {
            return false;
        }

        // fixed bug 197412
        if (sdRegion.getFullText().charAt(offset - sdRegion.getStartOffset()) != BACK_QOUTE) {
            return false;
        }

        quoteRegion = getPhpRegion(sdRegion, offset + 1);
        if (quoteRegion == null || quoteRegion.getLength() > 1) {
            return false;
        }

        // fixed bug 197412
        if (sdRegion.getFullText().charAt(
                offset + 1 - sdRegion.getStartOffset()) != BACK_QOUTE) {
            return false;
        }
        return true;
    }
}
TOP

Related Classes of com.dubture.twig.ui.editor.autoEdit.QuotesAutoEditStrategy

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.