com.htmlhifive.tools.rhino.comment.js.JSDocCommentNodeParser.java Source code

Java tutorial

Introduction

Here is the source code for com.htmlhifive.tools.rhino.comment.js.JSDocCommentNodeParser.java

Source

/*
 * Copyright (C) 2012 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.comment.js;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import com.htmlhifive.tools.rhino.Constants;
import com.htmlhifive.tools.rhino.comment.RelationNodeType;
import com.htmlhifive.tools.rhino.comment.TagType;
import com.htmlhifive.tools.rhino.comment.Token;
import com.htmlhifive.tools.rhino.comment.TokenType;
import com.htmlhifive.tools.rhino.comment.TokenUtil;

public class JSDocCommentNodeParser {

    private RelationNodeType docType;

    private List<Token> tokenList;

    public JSDocCommentNodeParser(RelationNodeType docType) {

        this.docType = docType;
        tokenList = new ArrayList<Token>();
    }

    public JSDocRoot parse(String comment) {

        StringTokenizer lineSeparator = new StringTokenizer(comment, "\n\r");
        int currentLineNum = 0;
        int currentIndexNum = 0;
        tokenList = new ArrayList<Token>();
        while (lineSeparator.hasMoreTokens()) {
            // ?
            String lineStr = lineSeparator.nextToken();
            // ?
            StringTokenizer tokenSeparator = new StringTokenizer(lineStr);

            while (tokenSeparator.hasMoreTokens()) {
                // token?
                String tokenStr = tokenSeparator.nextToken();
                Token token = new Token(TokenUtil.resolveType(tokenStr), tokenStr);
                // token??
                token.setLineNum(currentLineNum);
                // token????
                token.setIndexNum(currentIndexNum);
                tokenList.add(token);
                currentIndexNum = currentIndexNum + tokenStr.length() + 1;
            }
            currentIndexNum = 0;
            currentLineNum++;
        }

        return resolveJsDoc();
    }

    private JSDocRoot resolveJsDoc() {

        // ?????(@~~)
        JSTag currentTag = JSTag.ROOT;
        // ??Token?
        TokenType previousTokenType = TokenType.START;
        JSDocRoot root = new JSDocRoot(docType);
        // ?.?????.
        JSTagNode tempNode = root;
        int currentLineNum = 0;
        // ??StringBuilder
        StringBuilder currentDesc = new StringBuilder();
        // JsDoc?.
        String desc = null;
        for (Token token : tokenList) {
            if (currentDesc.length() != 0 && !TokenUtil.isSymbolType(token.getType())) {
                if (token.getLineNum() != currentLineNum) {
                    // ??????
                    currentDesc.append(Constants.LINE_SEPARATOR);
                    currentLineNum = token.getLineNum();
                } else {
                    // ?????Token?.
                    currentDesc.append(" ");
                }
            }
            switch (token.getType()) {
            case STRING_LITERAL:
                resolveStringLiteral(token, currentTag, previousTokenType, tempNode, currentDesc);
                break;
            case ANNOTATION:
                if (tempNode instanceof JSDocRoot) {
                    // ??????desc?JSDoc????desc??
                    desc = currentDesc.toString();
                } else if (tempNode instanceof JSSinglePartTagNode) {
                    // ?????.
                    ((JSSinglePartTagNode) tempNode).setValue(StringUtils.chomp(currentDesc.toString()));
                }
                if (tempNode != root) {
                    root.addTagNode(tempNode);
                }
                currentDesc = new StringBuilder();
                // ?????.
                JSTag temp = TokenUtil.resolveTagType(token);
                if (temp != null) {
                    currentTag = temp;
                }
                // ?????.
                tempNode = resolveTagNode(currentTag);
                break;
            case TYPE:
                if (currentTag == null) {
                    // ????????
                    currentDesc.append(token.getValue());
                }
                if (tempNode instanceof JSTypePartNode) {
                    // Type??????node?
                    ((JSTypePartNode) tempNode).setType(StringUtils.strip(token.getValue(), "{}"));
                }
                break;
            case END:
                if (tempNode instanceof JSSinglePartTagNode) {
                    // ?????.
                    ((JSSinglePartTagNode) tempNode).setValue(currentDesc.toString());
                }
                root.addTagNode(tempNode);
                break;
            case START:
            case SYMBOL:
            default:
                break;
            }
            previousTokenType = token.getType();
        }
        // ?.
        root.setDescription(desc);
        return root;
    }

    /**
     * token???.??????????.
     *
     * @param token ??.
     * @param currentTag ?????
     * @param previousTokenType ?????.
     * @param tempNode .
     * @param desc .
     */
    private void resolveStringLiteral(Token token, JSTag currentTag, TokenType previousTokenType,
            JSTagNode tempNode, StringBuilder desc) {

        switch (currentTag) {
        case PARAM:
        case PROPERTY:
            // ???????Param????tempNode?TypeNamePartNode
            switch (previousTokenType) {
            case TYPE:
                // ???????????????.
                if (tempNode instanceof JSTypeNamePartNode) {
                    ((JSTypeNamePartNode) tempNode).setName(token.getValue());
                }
                return;
            default:
                break;
            }
        default:
            // ????.
            desc.append(token.getValue());
            break;
        }

    }

    private JSTagNode resolveTagNode(JSTag currentTag) {

        if (ArrayUtils.contains(TagType.NO_PART_TAG.getJsTag(), currentTag)) {
            return new JSNoPartTagNode(currentTag);
        } else if (ArrayUtils.contains(TagType.SINGLE_PART_TAG.getJsTag(), currentTag)) {
            return new JSSinglePartTagNode(currentTag);
        } else if (ArrayUtils.contains(TagType.OTHER_PARAM_TAG.getJsTag(), currentTag)) {
            switch (currentTag) {
            case PARAM:
            case PROPERTY:
                return new JSTypeNamePartNode(currentTag);

            case THROWS:
            case RETURNS:
                return new JSTypePartNode(currentTag);
            default:
                break;
            }
            // ??SinglePartTag?
            return new JSSinglePartTagNode(currentTag);
        }
        return null;
    }
}