PageRenderTime 97ms CodeModel.GetById 48ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/XML/sidekick/javascript/JavaScriptParser.java

#
Java | 225 lines | 151 code | 15 blank | 59 comment | 48 complexity | 0e0431b1cfd96b83fdff4447a9728082 MD5 | raw file
  1/*
  2 * JavaScriptParser.java
  3 * :folding=explicit:collapseFolds=1:
  4 *
  5 * Copyright (C) 2005 by Martin Raspe
  6 * (hertzhaft@biblhertz.it)
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22package sidekick.javascript;
 23
 24import org.gjt.sp.jedit.*;
 25import org.gjt.sp.util.Log;
 26
 27import sidekick.enhanced.SourceParser;
 28import sidekick.SideKickParsedData;
 29
 30import java.io.*;
 31import java.util.ArrayList;
 32import java.util.Stack;
 33import java.util.regex.Pattern;
 34
 35import errorlist.*;
 36
 37/**
 38 * JavaScriptParser: parses perl source and builds a sidekick structure tree
 39 * Parser is based on regular expressions and will therefore
 40 * not able to correctly parse very irregular perl scripts
 41 *
 42 * @author     Martin Raspe
 43 * @created    March 3, 2005
 44 * @modified   $Date: 2010-08-12 14:46:15 +0200 (Thu, 12 Aug 2010) $ by $Author: daleanson $
 45 * @version    $Revision: 18336 $
 46 */
 47public class JavaScriptParser extends SourceParser {
 48
 49/*
 50    Changes suggested by David Padgett to make the parser
 51    more compatible with namespace/package emulation in JavaScript
 52
 53    my.test.namespace.MyClass = function ...
 54    my.test.namespace.MyClass.prototype.foobar = function ...
 55    my.test.namespace.MyClass.myStaticMethod = function ...
 56*/
 57    Pattern pClassFunction	= Pattern.compile("^((\\w+\\.)*[A-Z][\\w]*)\\s*=\\s*function");
 58    Pattern pMethodFunction	= Pattern.compile("^([\\w+\\.]+\\w+)\\.([\\w]+)\\s*=\\s*function");
 59    Pattern pPrototypeFunction	= Pattern.compile("^([\\w+\\.]+\\w+)\\.prototype\\.([\\w]+)\\s*=\\s*function");
 60
 61    Pattern pAssignedFunction	= Pattern.compile("^(\\w+)\\s*=\\s*function");
 62    Pattern pVarFunction	= Pattern.compile("^var\\s+(\\w+)\\s*=\\s*function");
 63    Pattern pSimpleFunction	= Pattern.compile("^function\\s+(\\w+)");
 64
 65//  var my.test.namespace.MyClass.Object = {...
 66//  my.test.namespace.MyClass.Object = {...
 67//  method_name : function ...
 68
 69    Pattern pObject		= Pattern.compile("^((\\w+\\.)*[A-Z][\\w]*)\\s*=[^\\{]*\\{");
 70    Pattern pVarObject		= Pattern.compile("^var\\s+((\\w+\\.)*[A-Z][\\w]*)\\s*=[^\\{]*\\{");
 71    Pattern pObjectMethod	= Pattern.compile("^(\\w+)\\s*:\\s*function");
 72
 73/**	 * Constructs a new Parser object
 74	 *
 75	 */
 76	public JavaScriptParser() {
 77		super("javascript");
 78		LINE_COMMENT	= "//";
 79		COMMENT		= "Comments";
 80		MAIN		= "(Window)";
 81		USE		= "import";
 82	}
 83
 84/**	 * Parses the given text and returns a tree model.
 85	 *
 86	 * @param buffer The buffer to parse.
 87	 * @param errorSource An error source to add errors to.
 88	 */
 89
 90	 protected void parseBuffer(Buffer buffer, DefaultErrorSource errorSource) {
 91        setStartLine( 0 );
 92        parseBuffer( buffer, buffer.getText( 0, buffer.getLength() ), errorSource );
 93     }
 94
 95     public SideKickParsedData parse( Buffer buffer, String text, DefaultErrorSource errorSource ) {
 96		data = new SideKickParsedData(buffer.getName());
 97		packages = new PackageMap(new PackageComparator());
 98		commentList = new ArrayList();
 99        parseBuffer(buffer, text, errorSource);
100		completePackageAsset(_end, _lastLineNumber);
101		Log.log(Log.DEBUG, this, "parsing completed");
102		buildTrees();
103		Log.log(Log.DEBUG, this, "tree built");
104		return data;
105     }
106
107     protected void parseBuffer(Buffer buffer, String text, DefaultErrorSource errorSource) {
108		String line;
109		String name;
110		String pkgname;
111		String[] names;
112		Stack funcstack = new Stack();
113		Stack pkgstack = new Stack();
114        //if (startLine == 0) {
115            pkgstack.push(MAIN);
116        //}
117		boolean in_comment = false;
118		int buflen = buffer.getLength();
119		int _tmp;
120		for (int lineNo = startLine; lineNo < startLine + getLineCount(text); lineNo++) {
121			_start = buffer.createPosition(buffer.getLineStartOffset(lineNo));
122			_tmp = buffer.getLineEndOffset(lineNo);
123			if (_tmp > buflen) _tmp = buflen;
124			_end = buffer.createPosition(_tmp);
125			line = buffer.getLineText(lineNo).trim();
126			// line comment or empty line
127			if (line.indexOf(LINE_COMMENT) == 0 || line.length() == 0) continue;
128			// block comment: end
129			if (in_comment && line.indexOf("*/") != -1 ) {
130				in_comment = false;
131				completeAsset(_end);
132				}
133			if (in_comment) continue;
134			// Class = function()
135			name = find(line, pClassFunction, 1);
136			if (name != null) {
137				if (! pkgstack.empty()) pkgstack.pop();
138				pkgstack.push(name);
139				addPackageAsset(name, lineNo, _start);
140				addAsset(SUB_KEY, name, "(constructor)", lineNo, _start);
141				continue;
142				}
143			name = find(line, pObject, 1);
144			if (name == null)
145				name = find(line, pVarObject, 1);
146			// var Object = {
147			if (name != null) {
148				if (! pkgstack.empty()) pkgstack.pop();
149				pkgstack.push(name);
150				addPackageAsset(name, lineNo, _start);
151				addLineAsset(SUB_KEY, name, "(assignment)", lineNo, _start, _end);
152				continue;
153				}
154			// check class methods
155			names = find2(line, pPrototypeFunction);
156			if (names == null)
157				names = find2(line, pMethodFunction);
158			if (names != null) {
159				pkgname = names[0];
160				if (pkgstack.empty()) {
161					pkgstack.push(pkgname);
162					addPackageAsset(pkgname, lineNo, _start);
163					}
164				else if (! pkgname.equals((String) pkgstack.peek())) {
165					pkgstack.pop();
166					pkgstack.push(pkgname);
167					addPackageAsset(pkgname, lineNo, _start);
168					}
169				if (! funcstack.empty()) {
170					funcstack.pop();
171					completeAsset(_start);
172					}
173				funcstack.push(names[1]);
174				addAsset(SUB_KEY, names[0], names[1], lineNo, _start);
175				continue;
176				}
177			// check functions
178			name = find(line, pAssignedFunction, 1);
179			if (name == null)
180				name = find(line, pVarFunction, 1);
181			if (name == null)
182				name = find(line, pObjectMethod, 1);
183			if (name == null)
184				name = find(line, pSimpleFunction, 1);
185			if (name != null) {
186				if (! funcstack.empty()) {
187					funcstack.pop();
188					completeAsset(_start);
189					}
190				funcstack.push(name);
191				addAsset(SUB_KEY, (String) pkgstack.peek(), name, lineNo, _start);
192				continue;
193				}
194			// block comment: start
195			if (! in_comment && line.indexOf("/*") != -1 ) {
196				completeAsset(_end);
197				if (! funcstack.empty()) name = (String) funcstack.peek();
198				if (name == null)  name = (String) pkgstack.peek();
199				if (name == null)  name = "(comment)";
200				in_comment = true;
201				addCommentAsset(name, lineNo, _start);
202				}
203			}
204	 }
205
206    private int getLineCount( CharSequence text ) {
207        if ( text == null )
208            return 0;
209        BufferedReader br = new BufferedReader( new StringReader( text.toString() ) );
210        String line = null;
211        int count = 0;
212        try {
213            while ( true ) {
214                line = br.readLine();
215                if ( line == null )
216                    break;
217                ++count;
218            }
219        }
220        catch ( Exception e ) {
221            e.printStackTrace();
222        }
223        return count;
224    }
225}