rewrote the method for parsing function files so that it handles

the various ways of declaring functions in rhino
This commit is contained in:
stefanp 2004-04-13 08:33:40 +00:00
parent eee11438d7
commit 54f60eecef

View file

@ -19,10 +19,7 @@ package helma.doc;
import java.awt.Point; import java.awt.Point;
import java.io.*; import java.io.*;
import java.util.Vector; import java.util.Vector;
import org.mozilla.javascript.TokenStream; import org.mozilla.javascript.*;
import org.mozilla.javascript.Token;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.CompilerEnvirons;
/** /**
* *
@ -76,55 +73,159 @@ public class DocFunction extends DocFileElement {
* connected to another DocElement. * connected to another DocElement.
*/ */
public static DocFunction[] newFunctions(File location, DocElement parent) { public static DocFunction[] newFunctions(File location, DocElement parent) {
Vector vec = new Vector(); Vector vec = new Vector();
try { try {
// the function file:
int token = Token.EMPTY;
int lastToken = Token.EMPTY;
Point endOfLastToken = null;
Point endOfLastUsedToken = null;
Point startOfFunctionBody = null;
Point endOfFunctionBody = null;
String lastNameString = null;
String functionName = null;
String context = null;
TokenStream ts = getTokenStream (location); TokenStream ts = getTokenStream (location);
DocFunction curFunction = null;
Point curFunctionStart = null;
while (!ts.eof()) { while (!ts.eof()) {
// store the position of the last token // store the position of the last token
Point endOfLastToken = getPoint (ts); endOfLastToken = getPoint (ts);
// new token
int tok = ts.getToken(); // store last token
lastToken = token;
// if we're currently parsing a functionbody and come to the start
// of the next function or eof -> read function body // now get a new token
if (curFunction != null && (tok== Token.FUNCTION || ts.eof())) { // regular expression syntax is troublesome for the TokenStream
curFunction.content = "function " + Util.getStringFromFile(location, curFunctionStart, endOfLastToken); // we can safely ignore syntax errors in regular expressions here
try {
token = ts.getToken();
} catch(Exception anything) {
continue;
} }
if (tok == Token.FUNCTION) { if (token == Token.LC) {
// store the function start for parsing the function body later
curFunctionStart = getPoint (ts); // when we come across a left brace outside of a function,
// get and chop the comment // we store the current string of the stream, it might be
String rawComment = Util.getStringFromFile(location, endOfLastToken, getPoint (ts)).trim (); // a function object declaration
// e.g. HttpClient = { func1:function()...}
context = ts.getString();
} else if (token == Token.RC && context != null) {
// when we come across a right brace outside of a function,
// we reset the current context cache
context = null;
} else if (token == Token.NAME) {
// store all names, the last one before a function
// declaration may be used as its name
if (lastToken != Token.DOT) {
lastNameString = ts.getString();
// this may be the start of a name chain declaring a function
// e.g. Number.prototype.functionName = function() { }
startOfFunctionBody = getPoint(ts);
startOfFunctionBody.x -= (ts.getString().length() + 1);
// set pointer to end of last function to the token before the name
endOfLastUsedToken = endOfLastToken;
} else {
// token in front of the name was a dot, so we connect the
// names that way
lastNameString += "." + ts.getString();
}
} else if (token == Token.FUNCTION) {
// store the end of the function word
Point p = getPoint(ts);
// look at the next token:
int peekToken = ts.peekToken();
// depending of the style of the declaration we already have all we need
// or need to fetch the name from the next token:
if (peekToken == Token.NAME) {
// if the token after FUNCTION is NAME, it's the usual function
// declaration like this: function abc() {}
// set the pointer for the start of the actual function body
// to the letter f of the function word
startOfFunctionBody = p;
startOfFunctionBody.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
// function is the stream's current string
token = ts.getToken();
functionName = ts.getString();
} else {
// it's a different kind of function declaration.
// the function name is the last found NAME-token
// if context is set, prepend it to the function name
functionName = (context != null) ? context + "." + lastNameString : lastNameString;
}
// get the comment from the file (unfortunately, the stream simply skips comments) ...
String rawComment = Util.getStringFromFile(location, endOfLastUsedToken, startOfFunctionBody).trim ();
// .. and clean it
rawComment = Util.chopComment (rawComment); rawComment = Util.chopComment (rawComment);
// position stream at function name token
tok = ts.getToken(); // create the function object
// get the name and create the function object DocFunction theFunction = newFunction (functionName, location, parent);
String name = ts.getString(); theFunction.parseComment (rawComment);
curFunction = newFunction (name, location, parent); vec.add (theFunction);
curFunction.parseComment (rawComment);
vec.add (curFunction);
// subloop on the tokenstream: find the parameters of a function // subloop on the tokenstream: find the parameters of a function
// only if it's a function (and not a macro or an action) while (!ts.eof() && token != Token.RP) {
if (curFunction.type == FUNCTION) { token = ts.getToken();
while (!ts.eof() && tok != Token.RP) { if (token==Token.NAME && theFunction.type == FUNCTION) {
// store the position of the last token // add names of parameter only for functions, not for macros or actions
endOfLastToken = getPoint (ts); theFunction.addParameter (ts.getString());
// new token
tok = ts.getToken();
if (tok==Token.NAME) {
curFunction.addParameter (ts.getString());
}
} }
} }
} // end if
} // subloop on the tokenstream: find the closing right bracket of the function
token = ts.getToken();
int level = (token == Token.LC) ? 1 : 0;
while (!ts.eof() && level > 0) {
// regular expression syntax is troublesome for the TokenStream
// we don't need them here, so we just ignore such an error
try {
token = ts.getToken();
} catch(Exception anything) {
continue;
}
if (token == Token.LC) {
level++;
} else if (token == Token.RC) {
level--;
}
}
endOfFunctionBody = getPoint(ts);
theFunction.content = Util.getStringFromFile(location, startOfFunctionBody, endOfFunctionBody);
} // end if
} // end while
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();