All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fife.rsta.ac.js.JavaScriptParser Maven / Gradle / Ivy

Go to download

A library adding code completion and other advanced features for Java, JavaScript, Perl, and other languages to RSyntaxTextArea.

There is a newer version: 3.3.0
Show newest version
/*
 * 01/28/2012
 *
 * Copyright (C) 2012 Robert Futrell
 * robert_futrell at users.sourceforge.net
 * http://fifesoft.com/rsyntaxtextarea
 *
 * This library is distributed under a modified BSD license.  See the included
 * RSTALanguageSupport.License.txt file for details.
 */
package org.fife.rsta.ac.js;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.text.Element;

import org.fife.io.DocumentReader;
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.parser.AbstractParser;
import org.fife.ui.rsyntaxtextarea.parser.DefaultParseResult;
import org.fife.ui.rsyntaxtextarea.parser.DefaultParserNotice;
import org.fife.ui.rsyntaxtextarea.parser.ParseResult;
import org.fife.ui.rsyntaxtextarea.parser.ParserNotice;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.ErrorCollector;
import org.mozilla.javascript.ast.ParseProblem;


/**
 * Parses JavaScript code in an RSyntaxTextArea.
 * 

* * Like all RSTA Parsers, a JavaScriptParser instance is * notified when the RSTA's text content changes. After a small delay, it will * parse the content as JS code, building an AST and looking for any errors. * When parsing is complete, a property change event of type * {@link #PROPERTY_AST} is fired. Listeners can check the new value of the * property for the AstRoot built that represents the source code * in the text area. *

* * This parser cannot be shared amongst multiple instances of * RSyntaxTextArea. *

* * Please keep in mind that this class is a work-in-progress! * * @author Robert Futrell * @version 1.0 */ public class JavaScriptParser extends AbstractParser { /** * The property change event that's fired when the document is re-parsed. * Applications can listen for this property change and update themselves * accordingly. The "new" value of this property will be an instance of * org.mozilla.javascript.ast.AstRoot. */ public static final String PROPERTY_AST = "AST"; private AstRoot astRoot; private JavaScriptLanguageSupport langSupport; private PropertyChangeSupport support; private DefaultParseResult result; /** * Constructor. */ public JavaScriptParser(JavaScriptLanguageSupport langSupport, RSyntaxTextArea textArea) { this.langSupport = langSupport; support = new PropertyChangeSupport(this); result = new DefaultParseResult(this); } /** * Registers a property change listener on this parser. You'll probably * want to listen for changes to {@link #PROPERTY_AST}. * * @param prop The property to listen for changes in. * @param l The listener to add. * @see #removePropertyChangeListener(String, PropertyChangeListener) */ public void addPropertyChangeListener(String prop, PropertyChangeListener l) { support.addPropertyChangeListener(prop, l); } /** * Creates options for Rhino based off of the user's preferences. * * @param errorHandler The container for errors found while parsing. * @return The properties for the JS compiler to use. */ public static CompilerEnvirons createCompilerEnvironment(ErrorReporter errorHandler, JavaScriptLanguageSupport langSupport) { CompilerEnvirons env = new CompilerEnvirons(); env.setErrorReporter(errorHandler); env.setIdeMode(true); env.setRecordingComments(true); env.setRecordingLocalJsDocComments(true); env.setRecoverFromErrors(true); if(langSupport != null) { env.setXmlAvailable(langSupport.isXmlAvailable()); env.setStrictMode(langSupport.isStrictMode()); int version = langSupport.getLanguageVersion(); if (version > 0) { Logger.log("[JavaScriptParser]: JS language version set to: " + version); env.setLanguageVersion(version); } } return env; } /** * Returns the AST, or null if the editor's content has not * yet been parsed. * * @return The AST, or null. */ public AstRoot getAstRoot() { return astRoot; } /** * {@inheritDoc} */ public ParseResult parse(RSyntaxDocument doc, String style) { astRoot = null; result.clearNotices(); // Always spell check all lines, for now. Element root = doc.getDefaultRootElement(); int lineCount = root.getElementCount(); result.setParsedLines(0, lineCount - 1); DocumentReader r = new DocumentReader(doc); ErrorCollector errorHandler = new ErrorCollector(); CompilerEnvirons env = createCompilerEnvironment(errorHandler, langSupport); long start = System.currentTimeMillis(); try { Parser parser = new Parser(env); astRoot = parser.parse(r, null, 0); long time = System.currentTimeMillis() - start; result.setParseTime(time); } catch (IOException ioe) { // Never happens result.setError(ioe); ioe.printStackTrace(); } catch (RhinoException re) { // Shouldn't happen since we're passing an ErrorCollector in int line = re.lineNumber(); // if (line>0) { Element elem = root.getElement(line); int offs = elem.getStartOffset(); int len = elem.getEndOffset() - offs - 1; String msg = re.details(); result.addNotice(new DefaultParserNotice(this, msg, line, offs, len)); // } } catch (Exception e) { result.setError(e); // catch all } r.close(); // Get any parser errors. List errors = errorHandler.getErrors(); if (errors != null && errors.size() > 0) { for (Iterator i = errors.iterator(); i.hasNext();) { ParseProblem problem = (ParseProblem) i.next(); int offs = problem.getFileOffset(); int len = problem.getLength(); int line = root.getElementIndex(offs); String desc = problem.getMessage(); DefaultParserNotice notice = new DefaultParserNotice(this, desc, line, offs, len); if (problem.getType() == ParseProblem.Type.Warning) { notice.setLevel(ParserNotice.WARNING); } result.addNotice(notice); } } // addNotices(doc); support.firePropertyChange(PROPERTY_AST, null, astRoot); return result; } /** * Removes a property change listener from this parser. * * @param prop The property that was being listened to. * @param l The listener to remove. * @see #addPropertyChangeListener(String, PropertyChangeListener) */ public void removePropertyChangeListener(String prop, PropertyChangeListener l) { support.removePropertyChangeListener(prop, l); } public static class JSErrorReporter implements ErrorReporter { public void error(String message, String sourceName, int line, String lineSource, int lineOffset) { } public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) { return null; } public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) { } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy