/* * Copyright (C) 2012-2016 NS Solutions Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.htmlhifive.tools.rhino; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.SortedSet; import java.util.StringTokenizer; import org.apache.commons.lang.StringUtils; import org.mozilla.javascript.CompilerEnvirons; import org.mozilla.javascript.Context; import org.mozilla.javascript.Parser; import org.mozilla.javascript.Token.CommentType; import org.mozilla.javascript.ast.AstRoot; import org.mozilla.javascript.ast.Comment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.htmlhifive.tools.rhino.comment.JSDocVSDocConverter; import com.htmlhifive.tools.rhino.comment.RelationNodeType; import com.htmlhifive.tools.rhino.comment.js.JSDocCommentNodeParser; import com.htmlhifive.tools.rhino.comment.js.JSDocRoot; import com.htmlhifive.tools.rhino.comment.vs.VSCommentBuilder; import com.htmlhifive.tools.rhino.comment.vs.VSDocRoot; /** * */ public class Main { private Logger logger = LoggerFactory.getLogger(Main.class); /** * * @param args */ public static void main(String[] args) { boolean printTree = false; String[] inPaths = new String[] {// // // "js/h5.tmp.js",// // "js/h5.tmp2.js",// // "js/h5.js",// // "js/h5.dev.js",// // "js/h5.async.js",// // "js/jquery-codeAssist.js", // "js/jquery-1.7.js",// // "js/jquery-1.6.2-vsdoc.js",// // "js/jquery.mobile-1.0.js",// // "js/test.js" "js/h5-1.1.6.dev.js" }; Main sample = new Main(); for (String path : inPaths) { try { String dstPath = getOutPath(path); sample.execute(path, dstPath, printTree); sample.execute(path, getOutPath(dstPath), printTree, DocType.VSDOC); // sample.execute(dstPath, getOutPath(dstPath), false); } catch (Exception e) { e.printStackTrace(); } } } public void execute(String path, String dstPath, boolean printTree) throws IOException { this.execute(path, dstPath, printTree, DocType.JSDOC); } /** * * @param srcPath * @param dstPath * @param printTree * @throws IOException */ public void execute(String srcPath, String dstPath, boolean printTree, DocType docType) throws IOException { Reader sourceReader = new FileReader(new File(srcPath)); String sourceName = srcPath; File out = new File(dstPath); AstRoot astRoot = parse(sourceReader, sourceName, docType); // System.out.println(astRoot.toSource()); logger.info("[" + sourceName + "]-------------------------"); // System.out.println("[" + sourceName + "]-------------------------"); // String source = SourceMaker.toSource(astRoot); // System.out.println(source); Util.dumpToFile(astRoot, out); // System.out.println(astRoot.toSource()); if (printTree) { logger.info("-------------------------"); logger.debug(Util.printTree(astRoot)); } } /** * * * * @param src * @param srcName * @return * @throws IOException */ public AstRoot parse(String src, String srcName) throws IOException { return parse(src, null, srcName, DocType.JSDOC); } /** * * * * @param src * @param srcName * @return * @throws IOException */ public AstRoot parse(String src, String srcName, DocType docType) throws IOException { return parse(src, null, srcName, docType); } /* * * * @param srcReader * * @param srcName * * @return * * @throws IOException */ public AstRoot parse(Reader srcReader, String srcName, DocType docType) throws IOException { return parse(null, srcReader, srcName, docType); } // /** // * @param content // * @param srcReader // * @param srcName // * @param docType // * @return // * @throws IOException // */ // public AstRoot parse(String src, Reader srcReader, String srcName, // DocType doctype) throws IOException { // return parse(src, srcReader, srcName, doctype, System.out); // } /** * @param content * @param srcReader * @param srcName * @param docType * @param out * @return * @throws IOException */ public AstRoot parse(String src, Reader srcReader, String srcName, DocType doctype) throws IOException { Context context = Context.enter(); try { context.setOptimizationLevel(-1); CompilerEnvirons compilerEnv = new CompilerEnvirons(); compilerEnv.setRecordingComments(true); compilerEnv.setRecordingLocalJsDocComments(true); compilerEnv.initFromContext(context); Parser p = new Parser(compilerEnv); // Rhino通常のパース. int lineno = 1; AstRoot astRoot = null; if (null != src) { astRoot = p.parse(src, srcName, lineno); } else { astRoot = p.parse(srcReader, srcName, lineno); } logger.debug(astRoot.toSource()); // 木構造の生成. AddNodeInfoVisitor nodeVisitor = new AddNodeInfoVisitor(); astRoot.visit(nodeVisitor); // 行番号の追加. AddLineno.setup(astRoot); // コメントノードの追加. SortedSet<Comment> comments = astRoot.getComments(); AddCommentNode node = null; switch (doctype) { case JSDOC: cleanComment(comments); node = new AddJSDocCommentNode(comments); break; case VSDOC: convertVsDoc(comments); node = new AddVSDocCommentNode(comments); break; default: throw new IllegalArgumentException(); } node.setup(astRoot); if (null != comments) { for (Comment comment : comments) { nodeVisitor.visit(comment); } } // ログ出力コードの削除. // きっとどんな変換を行うか、設定可能とした方が良いんだろうな. SuppressLoggerVisitor logVisitor; // if (out instanceof PrintStream) { // logVisitor = new SuppressLoggerVisitor((PrintStream) out); // } else { logVisitor = new SuppressLoggerVisitor(); // } astRoot.visit(logVisitor); return astRoot; } finally { Context.exit(); } } /** * * @param path * @return */ public static String getOutPath(String path) { int index = path.lastIndexOf('/'); if (0 > index) { return path; } else { String outPath = path.substring(0, index) + "/out" + path.substring(index); return outPath; } } /** * コメントを一行ずつ両端の空白を除去する. * * @param comments コメントノードのセット */ private void cleanComment(SortedSet<Comment> comments) { for (Comment comment : comments) { if (comment.getCommentType() == CommentType.JSDOC) { if (comment.getCommentType() == CommentType.JSDOC) { StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(comment.getValue(), Constants.LINE_SEPARATOR); while (st.hasMoreTokens()) { String token = st.nextToken(); sb.append(StringUtils.strip(token)); sb.append("\n"); } // comment.setJsDoc(sb.toString()); comment.setJsDocNode(new Comment(0, 0, CommentType.JSDOC, sb.toString())); } } } } private void convertVsDoc(SortedSet<Comment> comments) { for (Comment comment : comments) { if (comment.getCommentType() == CommentType.JSDOC) { JSDocCommentNodeParser nodeParser = new JSDocCommentNodeParser(RelationNodeType.FUNCTION); JSDocRoot jsdoc = nodeParser.parse(comment.getValue()); JSDocVSDocConverter converter = new JSDocVSDocConverter(); VSDocRoot vsDocRoot = converter.convert(jsdoc); VSCommentBuilder builder = new VSCommentBuilder(vsDocRoot); comment.putProp(Constants.VSDOC_FLAG, Boolean.valueOf(true)); // comment.setJsDoc(builder.build()); comment.setJsDocNode(new Comment(0, 0, CommentType.JSDOC, builder.build())); } } } public enum DocType { JSDOC, VSDOC } }