PageRenderTime 66ms CodeModel.GetById 52ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 1ms

/bundles/plugins-trunk/XML/sidekick/ecmascript/EcmaScriptSideKickParser.java

#
Java | 202 lines | 96 code | 27 blank | 79 comment | 21 complexity | fb23336b881ddf179c047c59976240c0 MD5 | raw file
  1/*
  2Copyright (c) 2006, Dale Anson
  3All rights reserved.
  4Redistribution and use in source and binary forms, with or without modification,
  5are permitted provided that the following conditions are met:
  6* Redistributions of source code must retain the above copyright notice,
  7this list of conditions and the following disclaimer.
  8* Redistributions in binary form must reproduce the above copyright notice,
  9this list of conditions and the following disclaimer in the documentation
 10and/or other materials provided with the distribution.
 11* Neither the name of the <ORGANIZATION> nor the names of its contributors
 12may be used to endorse or promote products derived from this software without
 13specific prior written permission.
 14THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 15ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 16WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 17DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 18ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 19(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 20LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 21ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 23SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24*/
 25package sidekick.ecmascript;
 26
 27import java.io.StringReader;
 28import java.util.*;
 29
 30import javax.swing.tree.DefaultMutableTreeNode;
 31
 32import org.gjt.sp.jedit.Buffer;
 33import org.gjt.sp.jedit.View;
 34
 35import errorlist.DefaultErrorSource;
 36import errorlist.ErrorSource;
 37
 38import sidekick.*;
 39import sidekick.enhanced.*;
 40import sidekick.util.*;
 41
 42import sidekick.ecmascript.parser.*;
 43
 44/**
 45 * @author    Dale Anson
 46 * @version   $Revision$
 47 */
 48public class EcmaScriptSideKickParser extends SideKickParser implements PartialParser {
 49
 50    private View currentView = null;
 51
 52    public static boolean showAll = true;
 53    private int lineOffset = 0;
 54
 55    public EcmaScriptSideKickParser() {
 56        super( "ecmascript" );
 57    }
 58
 59    /**
 60     * If called by another parser to parse part of a file (for example, to parse
 61     * a script tag in an html document), this can be set to the offset of the
 62     * script tag so that the node locations can be set correctly.
 63     */
 64    public void setStartLine( int offset ) {
 65        if ( offset > 0 ) {
 66            lineOffset = offset;
 67        }
 68    }
 69
 70    public void parse() {
 71        if ( currentView != null ) {
 72            parse( currentView.getBuffer(), null );
 73        }
 74    }
 75
 76    /**
 77     * Parse the contents of the given buffer.  This is the standard entry point
 78     * and will cause the entire text of the buffer to be parsed.
 79     *
 80     * @param buffer       the buffer to parse
 81     * @param errorSource  where to send errors
 82     * @return             Description of the Returned Value
 83     */
 84    public SideKickParsedData parse( Buffer buffer, DefaultErrorSource errorSource ) {
 85        setStartLine( 0 );
 86        return parse( buffer, buffer.getText( 0, buffer.getLength() ), errorSource );
 87    }
 88
 89    /**
 90     * Parse the contents of the given text.  This is the entry point to use when
 91     * only a portion of the buffer text is to be parsed.  Note that <code>setLineOffset</code>
 92     * should be called prior to calling this method, otherwise, tree node positions
 93     * may be off.
 94     *
 95     * @param buffer       the buffer to parse
 96     * @param errorSource  where to send errors
 97     * @return             Description of the Returned Value
 98     */
 99    public SideKickParsedData parse( Buffer buffer, String text, DefaultErrorSource errorSource ) {
100
101        String filename = buffer.getPath();
102        SideKickParsedData parsedData = new SideKickParsedData( buffer.getName() );
103        DefaultMutableTreeNode root = parsedData.root;
104
105        StringReader reader = new StringReader( text );
106        try {
107            // create parser
108            EcmaScript parser = new EcmaScript( reader );
109
110            // set line offset, the parser uses this to adjust line numbers in the
111            // case of a partial file, like when the javascript is embedded inside an
112            // html document
113            parser.setLineOffset( lineOffset );
114
115            // set tab size so that the parser can accurately calculate line and
116            // column positions
117            parser.setTabSize( buffer.getTabSize() );
118
119            // parse the text
120            SimpleNode ss = parser.Program();
121
122            // make a tree
123            addTreeNodes( root, ss );
124
125            // need to convert the nodes that are currently the user objects
126            // in the tree nodes to SideKick Assets
127            ElementUtil.convert( buffer, root );
128
129            if ( !buffer.isDirty() && errorSource != null ) {
130                /* only handle errors when buffer is saved. Otherwise, there will be a lot
131                of spurious errors shown when code completion is on and the user is in the
132                middle of typing something. */
133                List<ParseError> parseErrors = parser.getParseErrors();
134                for ( ParseError pe : parseErrors ) {
135                    String message = pe.message;
136                    Range range = pe.range;
137                    // addError is lame -- what if the error spans more than one line?
138                    // Need to just deal with it...
139                    if ( range.endLine != range.startLine ) {
140                        range.endColumn = range.startColumn;
141                    }
142                    errorSource.addError( ErrorSource.ERROR, filename, range.startLine, range.startColumn, range.endColumn, message );
143                }
144            }
145        }
146        catch ( Exception e ) {
147            e.printStackTrace();
148        }
149        finally {
150            reader.close();
151        }
152        return parsedData;
153    }
154
155    private void addTreeNodes( DefaultMutableTreeNode root, SimpleNode ss ) {
156        if ( ss != null && ss.hasChildren() ) {
157            Collections.sort(ss.getChildren(), nodeSorter);
158            for ( Iterator it = ss.getChildren().iterator(); it.hasNext(); ) {
159                SimpleNode cssChild = ( SimpleNode ) it.next();
160                if ( cssChild != null && cssChild.isVisible()) {
161                    DefaultMutableTreeNode dmtNode = new DefaultMutableTreeNode( cssChild );
162                    root.add( dmtNode );
163                    addTreeNodeChildren( dmtNode, cssChild );
164                }
165            }
166        }
167    }
168
169    private void addTreeNodeChildren( DefaultMutableTreeNode dmtNode, SimpleNode cssNode ) {
170        if ( cssNode.hasChildren() ) {
171            for ( Iterator it = cssNode.getChildren().iterator(); it.hasNext(); ) {
172                SimpleNode cssChild = ( SimpleNode ) it.next();
173                if ( cssChild != null && cssChild.isVisible() ) {
174                    DefaultMutableTreeNode dmtChild = new DefaultMutableTreeNode( cssChild );
175                    dmtNode.add( dmtChild );
176                    addTreeNodeChildren( dmtChild, cssChild );
177                }
178            }
179        }
180    }
181
182    /*
183    public boolean supportsCompletion() {
184        return false;
185    }
186
187    public boolean canCompleteAnywhere() {
188        return false;
189    }
190
191    public SideKickCompletion complete( EditPane editPane, int caret ) {
192        return null;
193    }
194    */
195
196    Comparator nodeSorter = new Comparator(){
197        public int compare(Object a, Object b) {
198            return a.toString().compareToIgnoreCase(b.toString());
199        }
200    };
201
202}