diff --git a/src/helma/doc/DocApplication.java b/src/helma/doc/DocApplication.java index c8e8c4de..b263c4a0 100644 --- a/src/helma/doc/DocApplication.java +++ b/src/helma/doc/DocApplication.java @@ -21,7 +21,7 @@ import helma.main.Server; import helma.util.SystemProperties; import java.io.*; import java.util.*; - +import java.awt.*; /** * */ @@ -60,18 +60,34 @@ public class DocApplication extends DocDirElement { * @param args ... */ public static void main(String[] args) { - // DocApplication app; - // app = new DocApplication (args[0], args[1]); - // app.readApplication (); + System.out.println("this is helma.doc"); + DocApplication app; + app = new DocApplication (args[0], args[1]); + app.readApplication (); + // DocPrototype el = DocPrototype.newInstance (new File(args[0])); // el.readFiles (); // DocFunction func = DocFunction.newTemplate (new File(args[0])); - // DocFunction func = DocFunction.newAction (new File(args[0])); - DocFunction[] func = DocFunction.newFunctions(new File(args[0])); - // DocSkin skin = DocSkin.newInstance (new File (args[0])); - // System.out.println (func.getContent ()); - // System.out.println ("\n\n\ncomment = " + func.getComment ()); +// DocFunction func = DocFunction.newAction (new File(args[0])); + +// DocFunction[] func = DocFunction.newFunctions(new File(args[0])); +// for (int i=0; i beginLine) && (ct < endLine)) { - buf.append(line + "\n"); - } else if (ct == endLine) { - buf.append(line.substring(0, endColumn)); - } - } - } catch (Exception e) { - debug(e.getMessage()); - } - - content = buf.toString(); - } - - /** - * connects all available specialTokens starting at the given token. - */ - protected void parseCommentFromToken(Token tok) { - StringBuffer buf = new StringBuffer(); - - while (tok.specialToken != null) { - buf.append(tok.specialToken.toString()); - tok = tok.specialToken; - } - - parseComment(buf.toString().trim()); - } } diff --git a/src/helma/doc/DocFunction.java b/src/helma/doc/DocFunction.java index 577d5c2c..aa2412e3 100644 --- a/src/helma/doc/DocFunction.java +++ b/src/helma/doc/DocFunction.java @@ -16,15 +16,18 @@ package helma.doc; -import FESI.Parser.*; import helma.framework.IPathElement; +import java.awt.Point; +import java.lang.reflect.Constructor; import java.io.*; -import java.util.*; +import java.util.Vector; +import org.mozilla.javascript.TokenStream; /** * */ public class DocFunction extends DocFileElement { + protected DocFunction(String name, File location, DocElement parent, int type) { super(name, location, type); this.parent = parent; @@ -41,30 +44,20 @@ public class DocFunction extends DocFileElement { * creates a new DocFunction object of type ACTION connected to another DocElement */ public static DocFunction newAction(File location, DocElement parent) { - String name = nameFromFile(location, ".hac"); + String name = Util.nameFromFile(location, ".hac"); DocFunction func = new DocFunction(name, location, parent, ACTION); - - func.parseActionFile(); - - return func; - } - - /** - * creates a new independent DocFunction object of type TEMPLATE - */ - public static DocFunction newTemplate(File location) { - return newTemplate(location, null); - } - - /** - * creates a new DocFunction object of type TEMPLATE connected to another DocElement - */ - public static DocFunction newTemplate(File location, DocElement parent) { - String name = nameFromFile(location, ".hsp"); - DocFunction func = new DocFunction(name, location, parent, TEMPLATE); - - func.parseTemplateFile(); - + String rawComment = ""; + try { + TokenStream ts = getTokenStream (location); + Point p = getPoint (ts); + ts.getToken(); + rawComment = Util.getStringFromFile(location, p, getPoint(ts)); + } catch (IOException io) { + io.printStackTrace(); + throw new DocException (io.toString()); + } + func.parseComment(rawComment); + func.content = Util.readFile(location); return func; } @@ -75,106 +68,126 @@ public class DocFunction extends DocFileElement { return newFunctions(location, null); } + /** * reads a function file and creates DocFunction objects of type FUNCTION * connected to another DocElement. */ public static DocFunction[] newFunctions(File location, DocElement parent) { Vector vec = new Vector(); - EcmaScriptTokenManager mgr = createTokenManager(location); - Token tok = mgr.getNextToken(); + try { + // the function file: + TokenStream ts = getTokenStream (location); + DocFunction curFunction = null; + Point curFunctionStart = null; + while (!ts.eof()) { - while (tok.kind != 0) { - if (tok.kind == EcmaScriptConstants.FUNCTION) { - // store the start position of the function: - int beginLine = tok.beginLine; - int beginColumn = tok.beginColumn; + // store the position of the last token + Point endOfLastToken = getPoint (ts); + // new token + int tok = ts.getToken(); - // the name is stored in the next token: - String funcName = mgr.getNextToken().toString(); - - // create the function object - DocFunction func; - - if (funcName.endsWith("_action")) { - func = new DocFunction(funcName, location, parent, ACTION); - } else if (funcName.endsWith("_macro")) { - func = new DocFunction(funcName, location, parent, MACRO); - } else { - func = new DocFunction(funcName, location, parent, FUNCTION); + // if we're currently parsing a functionbody and come to the start + // of the next function or eof -> read function body + if (curFunction != null && (tok== ts.FUNCTION || ts.eof())) { + curFunction.content = "function " + Util.getStringFromFile(location, curFunctionStart, endOfLastToken); } - // parse the comment from the special token(s) before this token: - func.parseCommentFromToken(tok); - - // find the parameters of this function, but only if it's - // neither macro nor action: - if (func.type == FUNCTION) { - while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.RPAREN)) { - if (tok.kind == EcmaScriptConstants.IDENTIFIER) { - func.addParameter(tok.image); - } - - tok = mgr.getNextToken(); + if (tok == ts.FUNCTION) { + // store the function start for parsing the function body later + curFunctionStart = getPoint (ts); + // get and chop the comment + String rawComment = Util.getStringFromFile(location, endOfLastToken, getPoint (ts)).trim (); + if (rawComment.endsWith("function")) { + rawComment = rawComment.substring (0, rawComment.length()-8).trim(); } - } else { - tok = mgr.getNextToken(); - } + // position stream at function name token + tok = ts.getToken(); + // get the name and create the function object + String name = ts.getString(); + curFunction = newFunction (name, location, parent); + curFunction.parseComment (rawComment); + vec.add (curFunction); - // now find the end of the function: - int endLine = 0; + // subloop on the tokenstream: find the parameters of a function + // only if it's a function (and not a macro or an action) + if (curFunction.type == FUNCTION) { + while (!ts.eof() && tok != ts.RP) { + // store the position of the last token + endOfLastToken = getPoint (ts); + // new token + tok = ts.getToken(); + if (tok==ts.NAME) { + curFunction.addParameter (ts.getString()); + } + } + } + } // end if - // now find the end of the function: - int endColumn = 0; - - while ((tok.kind != 0) && (tok.kind != EcmaScriptConstants.FUNCTION)) { - endLine = tok.endLine; - endColumn = tok.endColumn; - tok = mgr.getNextToken(); - } - - // now we know the exact position of the function in the file, - // re-read it and extract the source code: - func.parseSource(location, beginLine, beginColumn, endLine, endColumn); - vec.add(func); } - if (tok.kind != EcmaScriptConstants.FUNCTION) { - tok = mgr.getNextToken(); - } + } catch (IOException io) { + io.printStackTrace(); + throw new DocException (io.toString()); } - return (DocFunction[]) vec.toArray(new DocFunction[0]); } - /** - * reads the content of a .hac file and parses the comment before the first - * javascript element - */ - private void parseActionFile() { - EcmaScriptTokenManager mgr = createTokenManager(location); - Token tok = mgr.getNextToken(); - parseCommentFromToken(tok); - content = readFile(location); + private static DocFunction newFunction (String funcName, File location, DocElement parent) { + if (funcName.endsWith("_action")) { + return new DocFunction(funcName, location, parent, ACTION); + } else if (funcName.endsWith("_macro")) { + return new DocFunction(funcName, location, parent, MACRO); + } else { + return new DocFunction(funcName, location, parent, FUNCTION); + } } + /** - * reads the content of a .hsp file and parses the comment before the first - * javascript element (only if file starts with >%-tag!). + * creates a rhino token stream for a given file */ - private void parseTemplateFile() { - content = readFile(location); + protected static TokenStream getTokenStream (File f) { + FileReader reader = null; + try { + reader = new FileReader(f); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + throw new DocException (fnfe.toString()); + } + String name = f.getName(); + int line = 0; - StringReader str = new StringReader(content.substring(content.indexOf("<%") + 2, - content.indexOf("%>"))); - ASCII_CharStream ascii = new ASCII_CharStream(str, 1, 1); - EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(ascii); - Token tok = mgr.getNextToken(); + // FIXME for some reason this doesn't compile with winxp/j2sdk141_03 + // return new TokenStream (reader, null, name, line); - parseCommentFromToken(tok); + // so we have to use reflection: + try { + Class c = Class.forName ("org.mozilla.javascript.TokenStream"); + Constructor[] constr = c.getDeclaredConstructors(); + Object[] params = new Object[4]; + params[0] = reader; + params[1] = null; + params[2] = name; + params[3] = new Integer(line); + return (TokenStream) constr[0].newInstance(params); + } catch (Exception anything) { + anything.printStackTrace(); + throw new DocException (anything.toString()); + } } + + /** + * returns a pointer to the current position in the TokenStream + */ + protected static Point getPoint (TokenStream ts) { + return new Point (ts.getOffset(), ts.getLineno()); + } + + + /** * from helma.framework.IPathElement. All macros, templates, actions etc * have the same prototype. diff --git a/src/helma/doc/DocProperties.java b/src/helma/doc/DocProperties.java index 6a050859..ba96f2de 100644 --- a/src/helma/doc/DocProperties.java +++ b/src/helma/doc/DocProperties.java @@ -31,7 +31,7 @@ public class DocProperties extends DocFileElement { throws DocException { super(location.getName(), location, PROPERTIES); this.parent = parent; - content = readFile(location); + content = Util.readFile(location); props = new SystemProperties(); try { diff --git a/src/helma/doc/DocPrototype.java b/src/helma/doc/DocPrototype.java index 28f390be..b26bd517 100644 --- a/src/helma/doc/DocPrototype.java +++ b/src/helma/doc/DocPrototype.java @@ -16,7 +16,6 @@ package helma.doc; -import FESI.Parser.*; import helma.framework.IPathElement; import java.io.*; import java.util.*; @@ -128,8 +127,6 @@ public class DocPrototype extends DocDirElement { continue; } else if (arr[i].endsWith(".hac")) { addChild(DocFunction.newAction(f, this)); - } else if (arr[i].endsWith(".hsp")) { - addChild(DocFunction.newTemplate(f, this)); } else if (arr[i].endsWith(".js")) { DocElement[] elements = DocFunction.newFunctions(f, this); diff --git a/src/helma/doc/DocSkin.java b/src/helma/doc/DocSkin.java index d4b21259..df4f8cdc 100644 --- a/src/helma/doc/DocSkin.java +++ b/src/helma/doc/DocSkin.java @@ -27,7 +27,7 @@ public class DocSkin extends DocFileElement { protected DocSkin(String name, File location, DocElement parent) { super(name, location, SKIN); this.parent = parent; - content = readFile(location); + content = Util.readFile(location); parseHandlers(); } @@ -42,7 +42,7 @@ public class DocSkin extends DocFileElement { * creates a new DocSkin object connected to another DocElement */ public static DocSkin newInstance(File location, DocElement parent) { - String skinname = nameFromFile(location, ".skin"); + String skinname = Util.nameFromFile(location, ".skin"); DocSkin skin = new DocSkin(skinname, location, parent); return skin; diff --git a/src/helma/doc/Util.java b/src/helma/doc/Util.java index 8db24a63..cc77a912 100644 --- a/src/helma/doc/Util.java +++ b/src/helma/doc/Util.java @@ -16,21 +16,23 @@ package helma.doc; +import java.awt.Point; import java.io.*; -import java.util.*; + /** * */ public final class Util { /** + * chops a string from comment-delimiters * + * @param line a line of raw text * - * @param line ... - * - * @return ... + * @return chopped string */ public static String chopDelimiters(String line) { + line = line.trim(); if (line == null) { return null; } else if (line.startsWith("/**")) { @@ -47,4 +49,129 @@ public final class Util { return line; } } + + /** + * reads a complete file + * + * @param file + * + * @return string with content of file + */ + public static String readFile(File file) { + try { + StringBuffer buf = new StringBuffer(); + BufferedReader in = new BufferedReader(new FileReader(file)); + String line = in.readLine(); + + while (line != null) { + buf.append(line + "\n"); + line = in.readLine(); + } + + in.close(); + + return buf.toString(); + } catch (IOException e) { + return (""); + } + } + + + /** + * reads a part of a file defined by two points + + * @param start of string to extract defined by column x and row y + + * @param end of string to extract + + * @return string + */ + public static String getStringFromFile (File sourceFile, Point start, Point end) { + StringBuffer buf = new StringBuffer(); + int ct = 0; + try { + BufferedReader in = new BufferedReader(new FileReader(sourceFile)); + String line = ""; + while (line != null) { + line = in.readLine(); + if (line == null) { + break; + } + if ((ct > start.y) && (ct < end.y)) { + buf.append(line + "\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()) + "\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(); + } + + + /** + * method to debug file/stream-handling with Point objects. extracts the line p + * points to and prints it with a pointer to the given column + * + * @param sourceFile + * @param p x-value is used for column, y for row + * @param debugStr string prefixed to output + */ + public static void debugLineFromFile (File sourceFile, Point p, String debugStr) { + try { + BufferedReader in = new BufferedReader(new FileReader(sourceFile)); + String line = ""; + int ct = 0; + while (line != null) { + line = in.readLine (); + if (line==null) { + System.out.println ("eof reached"); + break; + } + if (ct==p.y) { + System.out.println (debugStr + ": " + line); + for (int i=0; i<(debugStr.length()+1+p.x); i++) { + System.out.print (" "); + } + System.out.println ("^"); + break; + } + ct++; + } + } catch (Exception e) { + e.printStackTrace(); + System.out.println(e.getMessage()); + } + } + + + + /** + * extracts the function name from a file. basically chops the given suffix + * and throws an error if the file name doesn't fit. + */ + public static String nameFromFile(File f, String suffix) + throws DocException { + String filename = f.getName(); + + if (!filename.endsWith(suffix)) { + throw new DocException("file doesn't have suffix " + suffix + ": " + + f.toString()); + } + + return filename.substring(0, filename.lastIndexOf(suffix)); + } + + }