* Work on DocFunction to make it work with Rhino 1.6.

* Make DocFunction not a RuntimeException, and throw it only where needed.
* Add TokenStreamInjector class to rhino to make TokenStream publicly available
* Add StringUtils.splitLines()
This commit is contained in:
hns 2006-11-15 15:48:46 +00:00
parent 578ecb148b
commit bc8653a873
10 changed files with 103 additions and 123 deletions

Binary file not shown.

View file

@ -35,11 +35,8 @@ public class DocApplication extends DocElement {
/** /**
* Creates a new DocApplication object. * Creates a new DocApplication object.
* *
* @param app
*
* @throws DocException ...
*/ */
public DocApplication(Application app) throws DocException { public DocApplication(Application app) {
super(app.getName(), APPLICATION); super(app.getName(), APPLICATION);
this.app = app; this.app = app;
readProps(); readProps();

View file

@ -52,7 +52,7 @@ public abstract class DocElement implements IPathElement {
List tags = new Vector(); List tags = new Vector();
List parameters = new Vector(); List parameters = new Vector();
protected DocElement(String name, int type) throws DocException { protected DocElement(String name, int type) {
this.name = name; this.name = name;
this.type = type; this.type = type;
} }

View file

@ -19,25 +19,25 @@ package helma.doc;
/** /**
* *
*/ */
public class DocException extends RuntimeException { public class DocException extends Exception {
String str;
/** /**
* Creates a new DocException object. * Creates a new DocException object.
* *
* @param str ... * @param msg ...
*/ */
public DocException(String str) { public DocException(String msg) {
super(str); super(msg);
this.str = str;
} }
/** /**
* Creates a new DocException object.
* *
* * @param msg the exception message
* @return ... * @param t the cause
*/ */
public String getMessage() { public DocException(String msg, Throwable t) {
return str; super(msg, t);
} }
} }

View file

@ -16,11 +16,16 @@
package helma.doc; package helma.doc;
import java.awt.Point;
import java.io.*;
import java.util.Vector;
import org.mozilla.javascript.*;
import helma.framework.repository.Resource; import helma.framework.repository.Resource;
import helma.util.StringUtils;
import java.awt.Point;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Vector;
import org.mozilla.javascript.*;
/** /**
* *
@ -44,18 +49,14 @@ public class DocFunction extends DocResourceElement {
*/ */
public static DocFunction newAction(Resource res, DocElement parent) throws IOException { public static DocFunction newAction(Resource res, DocElement parent) throws IOException {
String name = res.getBaseName(); String name = res.getBaseName();
String[] lines = StringUtils.splitLines(res.getContent());
DocFunction func = new DocFunction(name, res, parent, ACTION); DocFunction func = new DocFunction(name, res, parent, ACTION);
String rawComment = ""; String rawComment = "";
try { TokenStreamInjector ts = getTokenStream (res);
DockenStream ts = getDockenStream (res);
Point p = getPoint (ts); Point p = getPoint (ts);
ts.getToken(); ts.getToken();
rawComment = Util.getStringFromFile(res, p, getPoint(ts)); rawComment = Util.extractString(lines, p, getPoint(ts));
rawComment = Util.chopComment (rawComment); rawComment = Util.chopComment (rawComment);
} catch (IOException io) {
io.printStackTrace();
throw new DocException (io.toString());
}
func.parseComment(rawComment); func.parseComment(rawComment);
func.content = res.getContent(); func.content = res.getContent();
return func; return func;
@ -64,7 +65,7 @@ public class DocFunction extends DocResourceElement {
/** /**
* reads a function file and creates independent DocFunction objects of type FUNCTION * reads a function file and creates independent DocFunction objects of type FUNCTION
*/ */
public static DocFunction[] newFunctions(Resource res) { public static DocFunction[] newFunctions(Resource res) throws IOException {
return newFunctions(res, null); return newFunctions(res, null);
} }
@ -73,35 +74,34 @@ public class DocFunction extends DocResourceElement {
* reads a function file and creates DocFunction objects of type FUNCTION * reads a function file and creates DocFunction objects of type FUNCTION
* connected to another DocElement. * connected to another DocElement.
*/ */
public static DocFunction[] newFunctions(Resource res, DocElement parent) { public static DocFunction[] newFunctions(Resource res, DocElement parent)
throws IOException {
Vector vec = new Vector(); Vector vec = new Vector();
try { String content = res.getContent();
String[] lines = StringUtils.splitLines(content);
String comment = "";
int token = Token.EMPTY; int token = Token.EMPTY;
int lastToken = Token.EMPTY; int lastToken = Token.EMPTY;
Point endOfLastToken = null; Point marker;
Point endOfLastUsedToken = null;
Point startOfFunctionBody = null;
Point endOfFunctionBody = null;
String lastNameString = null; String lastNameString = null;
String functionName = null; String functionName = null;
String context = null; String context = null;
DockenStream ts = getDockenStream (res); TokenStreamInjector ts = getTokenStream (content);
while (!ts.eof()) { while (!ts.eof()) {
// store the position of the last token // store the position of the last token
endOfLastToken = getPoint (ts); marker = getPoint (ts);
// store last token // store last token
lastToken = token; lastToken = token;
// now get a new token // now get a new token
// regular expression syntax is troublesome for the DockenStream // regular expression syntax is troublesome for the TokenStream
// we can safely ignore syntax errors in regular expressions here // we can safely ignore syntax errors in regular expressions here
try { try {
token = ts.getToken(); token = ts.getToken();
@ -109,7 +109,13 @@ public class DocFunction extends DocResourceElement {
continue; continue;
} }
if (token == Token.LC) { if (token == Token.EOL) {
String c = Util.extractString(lines, marker, getPoint(ts));
if (c.startsWith("/**"))
comment = c;
} else if (token == Token.LC) {
// when we come across a left brace outside of a function, // when we come across a left brace outside of a function,
// we store the current string of the stream, it might be // we store the current string of the stream, it might be
@ -134,11 +140,8 @@ public class DocFunction extends DocResourceElement {
// this may be the start of a name chain declaring a function // this may be the start of a name chain declaring a function
// e.g. Number.prototype.functionName = function() { } // e.g. Number.prototype.functionName = function() { }
startOfFunctionBody = getPoint(ts); marker = getPoint(ts);
startOfFunctionBody.x -= (ts.getString().length() + 1); marker.x -= (ts.getString().length() + 1);
// set pointer to end of last function to the token before the name
endOfLastUsedToken = endOfLastToken;
} else { } else {
@ -165,17 +168,13 @@ public class DocFunction extends DocResourceElement {
// set the pointer for the start of the actual function body // set the pointer for the start of the actual function body
// to the letter f of the function word // to the letter f of the function word
startOfFunctionBody = p; marker = p;
startOfFunctionBody.x -= 9; marker.x -= 9;
// lastToken should be the last thing that didn't belong to this function
endOfLastUsedToken = endOfLastToken;
// set stream to next token, so that name of the // set stream to next token, so that name of the
// function is the stream's current string // function is the stream's current string
token = ts.getToken(); token = ts.getToken();
functionName = ts.getString(); functionName = ts.getString();
} else { } else {
// it's a different kind of function declaration. // it's a different kind of function declaration.
@ -185,14 +184,9 @@ public class DocFunction extends DocResourceElement {
} }
// get the comment from the file (unfortunately, the stream simply skips comments) ...
String rawComment = Util.getStringFromFile(res, endOfLastUsedToken, startOfFunctionBody).trim ();
// .. and clean it
rawComment = Util.chopComment (rawComment);
// create the function object // create the function object
DocFunction theFunction = newFunction (functionName, res, parent); DocFunction theFunction = newFunction (functionName, res, parent);
theFunction.parseComment (rawComment); theFunction.parseComment (comment);
vec.add (theFunction); vec.add (theFunction);
// subloop on the tokenstream: find the parameters of a function // subloop on the tokenstream: find the parameters of a function
@ -208,7 +202,7 @@ public class DocFunction extends DocResourceElement {
token = ts.getToken(); token = ts.getToken();
int level = (token == Token.LC) ? 1 : 0; int level = (token == Token.LC) ? 1 : 0;
while (!ts.eof() && level > 0) { while (!ts.eof() && level > 0) {
// regular expression syntax is troublesome for the DockenStream // regular expression syntax is troublesome for the TokenStream
// we don't need them here, so we just ignore such an error // we don't need them here, so we just ignore such an error
try { try {
token = ts.getToken(); token = ts.getToken();
@ -221,17 +215,14 @@ public class DocFunction extends DocResourceElement {
level--; level--;
} }
} }
endOfFunctionBody = getPoint(ts);
theFunction.content = Util.getStringFromFile(res, startOfFunctionBody, endOfFunctionBody); theFunction.content = Util.extractString(lines, marker, getPoint(ts));
comment = "";
} // end if } // end if
} // end while } // end while
} catch (Exception ex) {
ex.printStackTrace();
throw new DocException (ex.toString());
}
return (DocFunction[]) vec.toArray(new DocFunction[0]); return (DocFunction[]) vec.toArray(new DocFunction[0]);
} }
@ -246,37 +237,45 @@ public class DocFunction extends DocResourceElement {
} }
} }
/** /**
* creates a rhino token stream for a given file * Creates a rhino token stream for a given file.
* @param src the JS source, either as Resource or String object
* @return a TokenStream wrapper
* @throws IOException if an I/O exception was raised
*/ */
protected static DockenStream getDockenStream (Resource res) throws IOException { protected static TokenStreamInjector getTokenStream (Object src) throws IOException {
// TODO the TokenStreamInjector is really just a hack, and we shouldn't
// interact with the rhino TokenStream class directly. The proper way to
// go would be to use the public Parser class to parse the input, and walk
// through the parse tree and extract the comments manually.
// As a result of our approach, the TokenStream member in our Parser instance
// will be null, resulting in a NullPointerException when an error is
// encountered. For the time being, this is something we can live with.
Reader reader = null; Reader reader = null;
try { String content = null;
reader = new InputStreamReader(res.getInputStream()); if (src instanceof Resource) {
} catch (FileNotFoundException fnfe) { reader = new InputStreamReader(((Resource) src).getInputStream());
fnfe.printStackTrace(); } else if (src instanceof String) {
throw new DocException (fnfe.toString()); content = (String) src;
} else {
throw new IllegalArgumentException("src must be either a Resource or a String");
} }
// String name = res.getName();
Integer line = new Integer(0);
CompilerEnvirons compilerEnv = new CompilerEnvirons(); CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(Context.getCurrentContext()); compilerEnv.initFromContext(Context.getCurrentContext());
ErrorReporter errorReporter = Context.getCurrentContext().getErrorReporter(); ErrorReporter errorReporter = Context.getCurrentContext().getErrorReporter();
Parser parser = new Parser(compilerEnv, errorReporter); Parser parser = new Parser(compilerEnv, errorReporter);
return new DockenStream (parser, reader, null, line); return new TokenStreamInjector (parser, reader, content, 0);
} }
/** /**
* returns a pointer to the current position in the DockenStream * Returns a pointer to the current position in the TokenStream
* @param ts the TokenStream
* @return the current position
*/ */
protected static Point getPoint (DockenStream ts) { protected static Point getPoint (TokenStreamInjector ts) {
return new Point (ts.getOffset(), ts.getLineno()); return new Point (ts.getOffset(), ts.getLineno());
} }
/** /**
* from helma.framework.IPathElement. All macros, templates, actions etc * from helma.framework.IPathElement. All macros, templates, actions etc
* have the same prototype. * have the same prototype.

View file

@ -32,7 +32,7 @@ public class DocProperties extends DocResourceElement {
protected DocProperties(Resource res, ResourceProperties props, protected DocProperties(Resource res, ResourceProperties props,
int index, DocElement parent) int index, DocElement parent)
throws DocException, IOException { throws IOException {
super(res.getShortName(), res, PROPERTIES); super(res.getShortName(), res, PROPERTIES);
this.parent = parent; this.parent = parent;

View file

@ -61,7 +61,7 @@ public abstract class DocRepositoryElement extends DocElement {
} }
private void checkCommentFiles() throws DocException, IOException { private void checkCommentFiles() throws IOException {
if (repos == null) { if (repos == null) {
return; return;
} }
@ -70,9 +70,7 @@ public abstract class DocRepositoryElement extends DocElement {
if (res.exists()) { if (res.exists()) {
String rawComment = res.getContent(); String rawComment = res.getContent();
parseComment(rawComment); parseComment(rawComment);
return; return;
} }
} }

View file

@ -16,8 +16,6 @@
package helma.doc; package helma.doc;
import helma.framework.repository.Resource;
import java.awt.Point; import java.awt.Point;
import java.io.*; import java.io.*;
@ -70,43 +68,22 @@ public final class Util {
} }
/** /**
* reads a part of a file defined by two points * Extract a part of a file defined by two points from a String array
* @param lines an array of lines
* @param start of string to extract defined by column x and row y * @param start of string to extract defined by column x and row y
* @param end of string to extract * @param end of string to extract
* @return string * @return string
*/ */
public static String getStringFromFile (Resource res, Point start, Point end) { public static String extractString (String[] lines, Point start, Point end) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
int ct = 0; int to = Math.min(end.y + 1, lines.length);
try { for (int i = start.y; i < to; i++) {
BufferedReader in = new BufferedReader(new InputStreamReader(res.getInputStream())); int from = (i == start.y) ? start.x : 0;
String line = ""; if (i == end.y && end.x < lines[i].length())
while (line != null) { buf.append(lines[i].substring(from, end.x));
line = in.readLine(); else
if (line == null) { buf.append(lines[i].substring(from));
break; buf.append("\n");
}
if ((ct > start.y) && (ct < end.y)) {
buf.append(line).append("\n");
} else if (ct == start.y) {
if (start.y==end.y) {
buf.append (line.substring (start.x, end.x));
break;
} else {
buf.append(line.substring(start.x, line.length())).append("\n");
}
} else if (ct == end.y) {
buf.append(line.substring(0, end.x));
break;
}
ct++;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} }
return buf.toString().trim(); return buf.toString().trim();
} }

View file

@ -485,7 +485,7 @@ public class RhinoEngine implements ScriptingEngine {
doc = new DocApplication(app); doc = new DocApplication(app);
doc.readApplication(); doc.readApplication();
} catch (IOException x) { } catch (IOException x) {
throw new RuntimeException(x.toString()); throw new RuntimeException(x.toString(), x);
} }
} }
return doc; return doc;

View file

@ -48,4 +48,13 @@ public class StringUtils {
return s; return s;
} }
/**
* Split a string into an array of lines.
* @param str the string to split
* @return an array of lines
*/
public static String[] splitLines(String str) {
return str.split("\\r|\\n|\\r\\n");
}
} }