XmlReconcilingStrategy.java
上传用户:fanxing
上传日期:2017-01-19
资源大小:36k
文件大小:16k
源码类别:

PlugIns编程

开发平台:

Java

  1. /*******************************************************************************
  2. * Copyright (c) 2005 Prashant Deva and Gerd Castan
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License - v 1.0
  6. * which is available at http://www.eclipse.org/legal/epl-v10.html
  7. *******************************************************************************/
  8. package projection_test.editors;
  9. import java.util.ArrayList;
  10. import org.eclipse.core.runtime.IProgressMonitor;
  11. import org.eclipse.jface.text.BadLocationException;
  12. import org.eclipse.jface.text.IDocument;
  13. import org.eclipse.jface.text.IRegion;
  14. import org.eclipse.jface.text.Position;
  15. import org.eclipse.jface.text.reconciler.DirtyRegion;
  16. import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
  17. import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
  18. import org.eclipse.swt.widgets.Display;
  19. public class XmlReconcilingStrategy implements IReconcilingStrategy,
  20.                IReconcilingStrategyExtension {
  21.        private XMLEditor editor;
  22.        private IDocument fDocument;
  23.        /** holds the calculated positions */
  24.        protected final ArrayList fPositions = new ArrayList();
  25.        /** The offset of the next character to be read */
  26.        protected int fOffset;
  27.        /** The end offset of the range to be scanned */
  28.        protected int fRangeEnd;
  29.        /**
  30.         * @return Returns the editor.
  31.         */
  32.        public XMLEditor getEditor() {
  33.                return editor;
  34.        }
  35.        public void setEditor(XMLEditor editor) {
  36.                this.editor = editor;
  37.        }
  38.        /*
  39.         * (non-Javadoc)
  40.         *
  41.         * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
  42.         */
  43.        public void setDocument(IDocument document) {
  44.                this.fDocument = document;
  45.        }
  46.        /*
  47.         * (non-Javadoc)
  48.         *
  49.         * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,
  50.         *      org.eclipse.jface.text.IRegion)
  51.         */
  52.        public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
  53.                initialReconcile();
  54.        }
  55.        /*
  56.         * (non-Javadoc)
  57.         *
  58.         * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
  59.         */
  60.        public void reconcile(IRegion partition) {
  61.                initialReconcile();
  62.        }
  63.        /*
  64.         * (non-Javadoc)
  65.         *
  66.         * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
  67.         */
  68.        public void setProgressMonitor(IProgressMonitor monitor) {
  69.                // TODO Auto-generated method stub
  70.        }
  71.        /*
  72.         * (non-Javadoc)
  73.         *
  74.         * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
  75.         */
  76.        public void initialReconcile() {
  77.                fOffset = 0;
  78.                fRangeEnd = fDocument.getLength();
  79.                calculatePositions();
  80.        }
  81.        /**
  82.         * next character position - used locally and only valid while
  83.         * {@link #calculatePositions()} is in progress.
  84.         */
  85.        protected int cNextPos = 0;
  86.        /** number of newLines found by {@link #classifyTag()} */
  87.        protected int cNewLines = 0;
  88.        protected char cLastNLChar = ' ';
  89.        protected static final int START_TAG = 1;
  90.        protected static final int LEAF_TAG = 2;
  91.        protected static final int END_TAG = 3;
  92.        protected static final int EOR_TAG = 4;
  93.        protected static final int COMMENT_TAG = 5;
  94.        protected static final int PI_TAG = 6;
  95.        /**
  96.         * uses {@link #fDocument}, {@link #fOffset} and {@link #fRangeEnd} to
  97.         * calculate {@link #fPositions}. About syntax errors: this method is not a
  98.         * validator, it is useful.
  99.         */
  100.        protected void calculatePositions() {
  101.                fPositions.clear();
  102.                cNextPos = fOffset;
  103.                try {
  104.                        recursiveTokens(0);
  105.                } catch (BadLocationException e) {
  106.                        e.printStackTrace();
  107.                }
  108.                // Collections.sort(fPositions, new RangeTokenComparator());
  109.                Display.getDefault().asyncExec(new Runnable() {
  110.                        public void run() {
  111.                                editor.updateFoldingStructure(fPositions);
  112.                        }
  113.                });
  114.        }
  115.        /**
  116.         * emits tokens to {@link #fPositions}.
  117.         *
  118.         * @return number of newLines
  119.         * @throws BadLocationException
  120.         */
  121.        protected int recursiveTokens(int depth) throws BadLocationException {
  122.                int newLines = 0;
  123.                while (cNextPos < fRangeEnd) {
  124.                        while (cNextPos < fRangeEnd) {
  125.                                char ch = fDocument.getChar(cNextPos++);
  126.                                switch (ch) {
  127.                                case '<':
  128.                                        int startOffset = cNextPos - 1;
  129.                                        int startNewLines = newLines;
  130.                                        int classification = classifyTag();
  131.                                        String tagString = fDocument.get(startOffset, Math.min(cNextPos - startOffset, fRangeEnd - startOffset)); // this is to see where we are in the debugger
  132.                                        newLines += cNewLines; // cNewLines is written by
  133.                                                                                        // classifyTag()
  134.                                        switch (classification) {
  135.                                        case START_TAG:
  136.                                                newLines += recursiveTokens(depth + 1);
  137.                                                if (newLines > startNewLines+1) {
  138.                                                        emitPosition(startOffset, cNextPos - startOffset);
  139.                                                }
  140.                                                break;
  141.                                        case LEAF_TAG:
  142.                                                if (newLines > startNewLines+1) {
  143.                                                        emitPosition(startOffset, cNextPos - startOffset);
  144.                                                }
  145.                                                break;
  146.                                        case COMMENT_TAG:
  147.                                                if (newLines > startNewLines+1) {
  148.                                                        emitPosition(startOffset, cNextPos - startOffset);
  149.                                                }
  150.                                                break;
  151.                                        case PI_TAG:
  152.                                                break;
  153.                                        case END_TAG:
  154.                                        case EOR_TAG:
  155.                                                return newLines;
  156.                                        default:
  157.                                                break;
  158.                                        }
  159.                                        break;
  160.                                case 'n':
  161.                                case 'r':
  162.                                        if ((ch == cLastNLChar) || (' ' == cLastNLChar)) {
  163.                                                newLines++;
  164.                                                cLastNLChar = ch;
  165.                                        }
  166.                                        break;
  167.                                default:
  168.                                        break;
  169.                                }
  170.                        }
  171.                }
  172.                return newLines;
  173.        }
  174.        protected void emitPosition(int startOffset, int length) {
  175.                fPositions.add(new Position(startOffset, length));
  176.        }
  177.        /**
  178.         * classsifies a tag: <br />
  179.         * &lt;?...?&gt;: {@link #PI_TAG} <br />
  180.         * &lt;!...--&gt;: {@link #COMMENT_TAG} <br />
  181.         * &lt;...&gt;: {@link #START_TAG} <br />
  182.         * &lt;.../&gt;: {@link #LEAF_TAG} <br />
  183.         * &lt;/...&gt;: {@link #END_TAG} <br />
  184.         * &lt;...: {@link #EOR_TAG} (end of range reached before closing &gt; is
  185.         * found). <br />
  186.         * when this method is called, {@link #cNextPos} must point to the character
  187.         * after &lt;, when it returns, it points to the character after &gt; or
  188.         * after the range. About syntax errors: this method is not a validator, it
  189.         * is useful. Side effect: writes number of found newLines to
  190.         * {@link #cNewLines}.
  191.         *
  192.         * @return the tag classification
  193.         */
  194.        protected int classifyTag() {
  195.                try {
  196.                        char ch = fDocument.getChar(cNextPos++);
  197.                        cNewLines = 0;
  198.                        // processing instruction?
  199.                        if ('?' == ch) {
  200.                                boolean piFlag = false;
  201.                                while (cNextPos < fRangeEnd) {
  202.                                        ch = fDocument.getChar(cNextPos++);
  203.                                        if (('>' == ch) && piFlag)
  204.                                                return PI_TAG;
  205.                                        piFlag = ('?' == ch);
  206.                                }
  207.                                return EOR_TAG;
  208.                        }
  209.                        // comment?
  210.                        if ('!' == ch) {
  211.                                cNextPos++; // must be '-' but we don't care if not
  212.                                cNextPos++; // must be '-' but we don't care if not
  213.                                int commEnd = 0;
  214.                                while (cNextPos < fRangeEnd) {
  215.                                        ch = fDocument.getChar(cNextPos++);
  216.                                        if (('>' == ch) && (commEnd >= 2))
  217.                                                return COMMENT_TAG;
  218.                                    if (('n' == ch) || (       'r' == ch)) {
  219.                                                if ((ch == cLastNLChar) || (' ' == cLastNLChar)) {
  220.                                                        cNewLines++;
  221.                                                        cLastNLChar = ch;
  222.                                                }
  223.                                    }
  224.                                        if ('-' == ch) {
  225.                                                commEnd++;
  226.                                        } else {
  227.                                                commEnd = 0;
  228.                                        }
  229.                                }
  230.                                return EOR_TAG;
  231.                        }
  232.                        // consume whitespaces
  233.                        while ((' ' == ch) || ('t' == ch) || ('n' == ch) || ('r' == ch)) {
  234.                                ch = fDocument.getChar(cNextPos++);
  235.                                if (cNextPos > fRangeEnd)
  236.                                        return EOR_TAG;
  237.                        }
  238.                        // end tag?
  239.                        if ('/' == ch) {
  240.                                while (cNextPos < fRangeEnd) {
  241.                                        ch = fDocument.getChar(cNextPos++);
  242.                                        if ('>' == ch) {
  243.                                                cNewLines += eatToEndOfLine();
  244.                                                return END_TAG;
  245.                                        }
  246.                                        if ('"' == ch) {
  247.                                                ch = fDocument.getChar(cNextPos++);
  248.                                                while ((cNextPos < fRangeEnd) && ('"' != ch)) {
  249.                                                        ch = fDocument.getChar(cNextPos++);
  250.                                                }
  251.                                        } else if (''' == ch) {
  252.                                                ch = fDocument.getChar(cNextPos++);
  253.                                                while ((cNextPos < fRangeEnd) && (''' != ch)) {
  254.                                                        ch = fDocument.getChar(cNextPos++);
  255.                                                }
  256.                                        }
  257.                                }
  258.                                return EOR_TAG;
  259.                        }
  260.                        // start tag or leaf tag?
  261.                        while (cNextPos < fRangeEnd) {
  262.                                ch = fDocument.getChar(cNextPos++);
  263.                                // end tag?
  264.                                s: switch (ch) {
  265.                                case '/':
  266.                                        while (cNextPos < fRangeEnd) {
  267.                                                ch = fDocument.getChar(cNextPos++);
  268.                                                if ('>' == ch) {
  269.                                                        cNewLines += eatToEndOfLine();
  270.                                                        return LEAF_TAG;
  271.                                                }
  272.                                        }
  273.                                        return EOR_TAG;
  274.                                case '"':
  275.                                        while (cNextPos < fRangeEnd) {
  276.                                                ch = fDocument.getChar(cNextPos++);
  277.                                                if ('"' == ch)
  278.                                                        break s;
  279.                                        }
  280.                                        return EOR_TAG;
  281.                                case ''':
  282.                                        while (cNextPos < fRangeEnd) {
  283.                                                ch = fDocument.getChar(cNextPos++);
  284.                                                if (''' == ch)
  285.                                                        break s;
  286.                                        }
  287.                                        return EOR_TAG;
  288.                                case '>':
  289.                                        cNewLines += eatToEndOfLine();
  290.                                        return START_TAG;
  291.                                default:
  292.                                        break;
  293.                                }
  294.                        }
  295.                        return EOR_TAG;
  296.                } catch (BadLocationException e) {
  297.                        // should not happen, but we treat it as end of range
  298.                        return EOR_TAG;
  299.                }
  300.        }
  301.        protected int eatToEndOfLine() throws BadLocationException {
  302.                if (cNextPos >= fRangeEnd) {
  303.                        return 0;
  304.                }
  305.                char ch = fDocument.getChar(cNextPos++);
  306.                // 1. eat all spaces and tabs
  307.                while ((cNextPos < fRangeEnd) && ((' ' == ch) || ('t' == ch))) {
  308.                        ch = fDocument.getChar(cNextPos++);
  309.                }
  310.                if (cNextPos >= fRangeEnd) {
  311.                        cNextPos--;
  312.                        return 0;
  313.                }
  314.                // now ch is a new line or a non-whitespace
  315.                if ('n' == ch) {
  316.                        if (cNextPos < fRangeEnd) {
  317.                                ch = fDocument.getChar(cNextPos++);
  318.                                if ('r' != ch) {
  319.                                        cNextPos--;
  320.                                }
  321.                        } else {
  322.                                cNextPos--;
  323.                        }
  324.                        return 1;
  325.                }
  326.                if ('r' == ch) {
  327.                        if (cNextPos < fRangeEnd) {
  328.                                ch = fDocument.getChar(cNextPos++);
  329.                                if ('n' != ch) {
  330.                                        cNextPos--;
  331.                                }
  332.                        } else {
  333.                                cNextPos--;
  334.                        }
  335.                        return 1;
  336.                }
  337.                return 0;
  338.        }
  339. }