Package com.asakusafw.utils.java.parser.javadoc

Source Code of com.asakusafw.utils.java.parser.javadoc.JavadocConverter

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.utils.java.parser.javadoc;

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

import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrBasicTypeKind;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocArrayType;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocBasicType;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocBlock;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocComment;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocElementVisitor;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocField;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocFragment;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocMethod;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocMethodParameter;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocNamedType;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocQualifiedName;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocSimpleName;
import com.asakusafw.utils.java.internal.parser.javadoc.ir.IrDocText;
import com.asakusafw.utils.java.model.syntax.BasicTypeKind;
import com.asakusafw.utils.java.model.syntax.DocBlock;
import com.asakusafw.utils.java.model.syntax.DocElement;
import com.asakusafw.utils.java.model.syntax.DocMethodParameter;
import com.asakusafw.utils.java.model.syntax.Javadoc;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
import com.asakusafw.utils.java.model.syntax.Name;
import com.asakusafw.utils.java.model.syntax.NamedType;
import com.asakusafw.utils.java.model.syntax.SimpleName;
import com.asakusafw.utils.java.model.syntax.Type;

/**
* ドキュメンテーションコメントを{@code java-dom}のモデルに変換する。
*/
public class JavadocConverter {

    private final ModelFactory factory;

    private final JavadocParser parser;

    /**
     * インスタンスを生成する。
     * @param factory モデルを構築するファクトリ
     * @throws IllegalArgumentException 引数に{@code null}が含まれる場合
     */
    public JavadocConverter(ModelFactory factory) {
        super();
        this.factory = factory;
        JavadocParserBuilder builder = new JavadocParserBuilder();
        builder.addSpecialStandAloneBlockParser(new FollowsNamedTypeBlockParser(
            "exception", //$NON-NLS-1$
            "throws" //$NON-NLS-1$
        ));
        builder.addSpecialStandAloneBlockParser(new FollowsReferenceBlockParser(
            "see" //$NON-NLS-1$
        ));
        builder.addSpecialStandAloneBlockParser(new ParamBlockParser(
            "param" //$NON-NLS-1$
        ));
        builder.addSpecialStandAloneBlockParser(new SerialFieldBlockParser(
            "serialField" //$NON-NLS-1$
        ));

        builder.addSpecialInlineBlockParser(new FollowsReferenceBlockParser(
            "link", //$NON-NLS-1$
            "linkplain" //$NON-NLS-1$
        ));
        this.parser = builder.build();
    }

    /**
     * 指定の文字列で構成されたドキュメンテーションコメントを生成して返す。
     * @param content 内容文字列
     * @param offset 開始オフセット
     * @return 解析結果
     * @throws JavadocParseException ドキュメンテーションコメントの形式が不正である場合
     * @throws IllegalArgumentException 引数に{@code null}が含まれる場合
     */
    public Javadoc convert(String content, int offset) throws JavadocParseException {
        if (content == null) {
            throw new IllegalArgumentException("content must not be null"); //$NON-NLS-1$
        }
        JavadocScanner scanner = DefaultJavadocScanner.newInstance(content);
        IrDocComment ir = parser.parse(scanner);
        return convert(ir, offset);
    }

    private Javadoc convert(IrDocComment comment, int offset) {
        assert comment != null;
        Mapper mapper = new Mapper(factory, offset);

        List<DocBlock> blocks = new ArrayList<DocBlock>();
        for (IrDocBlock block : comment.getBlocks()) {
            blocks.add((DocBlock) block.accept(mapper, null));
        }
        return factory.newJavadoc(blocks);
    }

    private static class Mapper
            extends IrDocElementVisitor<DocElement, Void> {

        final ModelFactory factory;

        private final TypeMapper types;

        Mapper(ModelFactory factory, int offset) {
            assert factory != null;
            this.factory = factory;
            this.types = new TypeMapper();
        }

        @Override
        public DocElement visitBlock(IrDocBlock elem, Void context) {
            String tag = elem.getTag();
            List<DocElement> elements = new ArrayList<DocElement>();
            for (IrDocFragment f : elem.getFragments()) {
                elements.add(f.accept(this, null));
            }
            return factory.newDocBlock(
                tag == null ? "" : tag,
                elements);
        }

        @Override
        public DocElement visitText(IrDocText elem, Void context) {
            return factory.newDocText(elem.getContent());
        }

        @Override
        public DocElement visitSimpleName(IrDocSimpleName elem, Void context) {
            return factory.newSimpleName(elem.getIdentifier());
        }

        @Override
        public DocElement visitQualifiedName(IrDocQualifiedName elem, Void context) {
            Name qualifier = (Name) elem.getQualifier().accept(this, null);
            SimpleName simple = (SimpleName) elem.getName().accept(this, null);
            return factory.newQualifiedName(qualifier, simple);
        }

        @Override
        public DocElement visitField(IrDocField elem, Void context) {
            Type type = declaring(elem.getDeclaringType());
            SimpleName name = (SimpleName) elem.getName().accept(this, null);
            return factory.newDocField(type, name);
        }

        @Override
        public DocElement visitMethod(IrDocMethod elem, Void context) {
            Type type = declaring(elem.getDeclaringType());
            SimpleName name = (SimpleName) elem.getName().accept(this, null);
            List<DocMethodParameter> params = new ArrayList<DocMethodParameter>();
            for (IrDocMethodParameter p : elem.getParameters()) {
                params.add(convert(p));
            }
            return factory.newDocMethod(type, name, params);
        }

        private DocMethodParameter convert(IrDocMethodParameter elem) {
            Type type = elem.getType().accept(types, this);
            SimpleName name;
            if (elem.getName() != null) {
                name = (SimpleName) elem.getName().accept(this, null);
            } else {
                name = null;
            }
            return factory.newDocMethodParameter(
                type,
                name,
                elem.isVariableArity());
        }

        @Override
        public DocElement visitNamedType(IrDocNamedType elem, Void context) {
            Name name = (Name) elem.getName().accept(this, null);
            return factory.newNamedType(name);
        }

        private NamedType declaring(IrDocNamedType declaringType) {
            if (declaringType == null) {
                return null;
            }
            return (NamedType) visitNamedType(declaringType, null);
        }
    }

    private static class TypeMapper extends IrDocElementVisitor<Type, Mapper> {

        TypeMapper() {
            return;
        }

        @Override
        public Type visitArrayType(IrDocArrayType elem, Mapper context) {
            Type component = elem.getComponentType().accept(this, context);
            return context.factory.newArrayType(component);
        }

        @Override
        public Type visitBasicType(IrDocBasicType elem, Mapper context) {
            BasicTypeKind kind = convert(elem.getTypeKind());
            return context.factory.newBasicType(kind);
        }

        @Override
        public Type visitNamedType(IrDocNamedType elem, Mapper context) {
            Name name = (Name) elem.getName().accept(context, null);
            return context.factory.newNamedType(name);
        }

        private static BasicTypeKind convert(IrBasicTypeKind kind) {
            switch (kind) {
            case BOOLEAN:
                return BasicTypeKind.BOOLEAN;
            case BYTE:
                return BasicTypeKind.BYTE;
            case CHAR:
                return BasicTypeKind.CHAR;
            case DOUBLE:
                return BasicTypeKind.DOUBLE;
            case FLOAT:
                return BasicTypeKind.FLOAT;
            case INT:
                return BasicTypeKind.INT;
            case LONG:
                return BasicTypeKind.LONG;
            case SHORT:
                return BasicTypeKind.SHORT;
            case VOID:
                return BasicTypeKind.VOID;
            default:
                throw new AssertionError(kind);
            }
        }
    }
}
TOP

Related Classes of com.asakusafw.utils.java.parser.javadoc.JavadocConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.