Package com.dubture.symfony.core.util

Source Code of com.dubture.symfony.core.util.AnnotationUtils

/*******************************************************************************
* This file is part of the Symfony eclipse plugin.
*
* (c) Robert Gruendler <r.gruendler@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
package com.dubture.symfony.core.util;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.php.internal.core.ast.nodes.Comment;
import org.eclipse.php.internal.core.codeassist.strategies.PHPDocTagStrategy;
import org.eclipse.php.internal.core.compiler.ast.nodes.ClassDeclaration;
import org.eclipse.php.internal.core.compiler.ast.nodes.IPHPDocAwareDeclaration;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPDocBlock;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPMethodDeclaration;
import org.eclipse.php.internal.ui.Logger;

import com.dubture.doctrine.annotation.model.Annotation;
import com.dubture.doctrine.annotation.parser.AnnotationCommentParser;
import com.dubture.symfony.core.preferences.SymfonyCoreConstants;
import com.dubture.symfony.index.model.Route;

@SuppressWarnings("restriction")
public class AnnotationUtils {

    protected static final String[] PHPDOC_TAGS_EXTRA = {"api", "inheritdoc"};
    protected static final List<Annotation> EMPTY_ANNOTATIONS = new LinkedList<Annotation>();

    /**
     * See {@link #extractAnnotations(AnnotationCommentParser, Comment, ISourceModule)} for
     * a more detailed description.
     *
     * @param comment The comment node to parse the comment from
     * @param sourceModule The source module where the comment is located
     *
     * @return A list of valid annotations
     */
    public static List<Annotation> extractAnnotations(Comment comment, ISourceModule sourceModule) {
        return extractAnnotations(createParser(), comment, sourceModule);
    }

    /**
     * Parse a comment from a comment PHP AST node. This is the preferred method to
     * use if you need exact source position in the annotations returned.
     *
     * @param parser The parser used to parse a comment
     * @param comment The comment node to parse the comment from
     * @param sourceModule The source module where the comment is located
     *
     * @return A list of valid annotations
     */
    public static List<Annotation> extractAnnotations(AnnotationCommentParser parser,
                                                      Comment comment,
                                                      ISourceModule sourceModule) {
        if (comment == null || comment.getCommentType() != Comment.TYPE_PHPDOC) {
            return EMPTY_ANNOTATIONS;
        }

        try {
            int commentStartOffset = comment.getStart();
            int commentEndOffset = comment.getEnd();
            String commentSource = getCommentSource(sourceModule, commentStartOffset, commentEndOffset);

            return parser.parse(commentSource, commentStartOffset);
        } catch (Exception exception) {
            Logger.logException("Unable to extract annotations from comment", exception);
            return EMPTY_ANNOTATIONS;
        }
    }

    /**
     * Parse a comment from a PHP doc aware declaration. This is not the most accurate
     * way to extract annotations from a comment since the comment source returned by
     * the declaration is not really the same as the one found in the PHP file. Mainly,
     * some line endings and some formatting is lost when using this method.
     *
     * <p>
     * To get a more accurate extraction, provide the source module associated with
     * this declaration. Use {@link #extractAnnotations(IPHPDocAwareDeclaration, ISourceModule)}
     * to do this.
     * </p>
     *
     * @param declaration The declaration to parse the comment from
     *
     * @return A list of valid annotations
     */
    public static List<Annotation> extractAnnotations(IPHPDocAwareDeclaration declaration) {
        return extractAnnotations(declaration, null);
    }

    /**
     * See {@link #extractAnnotations(AnnotationCommentParser, IPHPDocAwareDeclaration,
     * ISourceModule)} for a more detailed description.
     *
     * @param declaration The declaration to parse the comment from
     * @param sourceModule The source module to extract the comment from
     *
     * @return A list of valid annotations
     */
    public static List<Annotation> extractAnnotations(IPHPDocAwareDeclaration declaration,
                                                      ISourceModule sourceModule) {
        return extractAnnotations(declaration, null);
    }

    /**
     * Parse a comment from a PHP doc aware declaration. This is not the most accurate
     * way to extract annotations from a comment since the comment source returned by
     * the declaration is not really the same as the one found in the PHP file. Mainly,
     * some line endings and some formatting is lost when using this method.
     *
     * <p>
     * To get a more accurate extraction, provide the source module associated with
     * this declaration. Use {@link #extractAnnotations(AnnotationCommentParser,
     * IPHPDocAwareDeclaration, ISourceModule)} to do this.
     * </p>
     *
     * @param parser The parser used to parse a comment
     * @param declaration The declaration to parse the comment from
     *
     * @return A list of valid annotations according to the parser
     */
    public static List<Annotation> extractAnnotations(AnnotationCommentParser parser,
                                                      IPHPDocAwareDeclaration declaration) {
        return extractAnnotations(parser, declaration, null);
    }

    /**
     * Parse a comment from a PHP doc aware declaration. By using the source module,
     * you ensure that source positions of the annotations will be set correctly
     * relative to the PHP file.
     *
     * @param parser The parser used to parse a comment
     * @param declaration The declaration to parse the comment from
     * @param sourceModule The source module to extract the comment from
     *
     * @return A list of valid annotations according to the parser
     */
    public static List<Annotation> extractAnnotations(AnnotationCommentParser parser,
                                                      IPHPDocAwareDeclaration declaration,
                                                      ISourceModule sourceModule) {
        try {
            PHPDocBlock comment = declaration.getPHPDoc();
            if (comment == null || comment.getCommentType() != Comment.TYPE_PHPDOC) {
                return EMPTY_ANNOTATIONS;
            }

            int commentStartOffset = comment.sourceStart();
            String commentSource;
            if (sourceModule != null) {
                commentSource = getCommentSource(sourceModule, commentStartOffset, comment.sourceEnd());
            } else {
                commentSource = comment.getShortDescription() + comment.getLongDescription();
            }

            return parser.parse(commentSource, commentStartOffset);
        } catch (Exception exception) {
            Logger.logException("Unable to extract annotations from declaration " + getDeclarationName(declaration), exception);
            return EMPTY_ANNOTATIONS;
        }
    }

    /**
     * This will create a {@link Route} object from a route annotation.
     *
     * @param routeAnnotation The annotation to extract the route from
     * @param bundle The bundle where the annotation is located
     * @param controller The controller where the annotation is located
     * @param action The action associated with the route annotation
     *
     * @return The {@link Route} object represented by the annotation
     */
    public static Route extractRoute(Annotation routeAnnotation, String bundle, String controller, String action) {
        assert(routeAnnotation.getClassName().startsWith(SymfonyCoreConstants.ROUTE_ANNOTATION));

        String pattern = (String) routeAnnotation.getArgumentValue(0).getValue();
        String name = (String) routeAnnotation.getArgumentValue("name").getValue();

        return new Route(bundle, controller, action, name, pattern);
    }

    /**
     * This will create a view path from a template annotation. This method uses
     * {@link PathUtils#createViewPath(String)} internally to convert the annotation
     * to a view path.
     *
     * @param templateAnnotation The annotation to extract the template view path from
     * @param bundle The bundle where the annotation is located
     * @param controller The controller where the annotation is located
     * @param action The action associated with the template annotation
     *
     * @return The view path represented by the annotation
     */
    public static String extractTemplate(Annotation templateAnnotation,
                                         String bundle,
                                         String controller,
                                         String action) {
        assert(templateAnnotation.getClassName().startsWith(SymfonyCoreConstants.TEMPLATE_ANNOTATION));

        String defaultViewPath = bundle + ":" + controller + ":" + action;
        String viewPath = defaultViewPath;
        if (templateAnnotation.hasArgument(0)) {
            viewPath = (String) templateAnnotation.getArgumentValue(0).getValue();
        }

        return PathUtils.createViewPath(viewPath);
    }

    /**
     * This will create a default {@link AnnotationCommentParser}. This default
     * parser will exclude base PHP doc tags and also some extra PHP doc tags (
     * {@literal @inheritdoc} and {@literal @api}).
     *
     * @return A default {@link AnnotationCommentParser}
     */
    public static AnnotationCommentParser createParser() {
        return createParser(null);
    }

    /**
     * This will create a default {@link AnnotationCommentParser}. This default
     * parser will exclude base PHP doc tags and also some extra PHP doc tags (
     * {@literal @inheritdoc} and {@literal @api}).
     *
     * <p>
     * With this method, you can also specify which classes would like to include
     * in the list of annotations. This is useful when only want a certain types
     * of annotation like {@literal @Template} ones. The class names are the fully
     * qualified names. So, to include only {@literal "@Orm\Entity"} annotations,
     * you will need to pass the array new String[] {"@Orm\Entity"} to the method.
     * </p>
     *
     * @param includedClassNames The class names to includes, can be null
     *
     * @return A default {@link AnnotationCommentParser} set to include only the classes specified
     */
    public static AnnotationCommentParser createParser(String[] includedClassNames) {
        AnnotationCommentParser parser = new AnnotationCommentParser();
        parser.addExcludedClassNames(PHPDocTagStrategy.PHPDOC_TAGS);
        parser.addExcludedClassNames(PHPDOC_TAGS_EXTRA);
        if (includedClassNames != null) {
            parser.addIncludedClassNames(includedClassNames);
        }

        return parser;
    }

    /**
     * This is used for logging purpose. It takes an IPHPDocAwareDeclaration declaration
     * and tries to extract the name from it. For now, this method handle method and
     * class declaration.
     *
     * @param declaration The PHP doc aware declaration
     *
     * @return The name associated with this declaration if it can be found, string "unknown" otherwise
     */
    private static String getDeclarationName(IPHPDocAwareDeclaration declaration) {

        if (declaration instanceof PHPMethodDeclaration) {
            return "method: " + ((PHPMethodDeclaration) declaration).getName();
        }

        if (declaration instanceof ClassDeclaration) {
            return "class: " + ((ClassDeclaration) declaration).getName();
        }

        return "unknown";
    }

    /**
     * Get the comment source from a source module. This will simply get the source
     * and extract the substring representing the comment.
     *
     * @param sourceModule The source module to extract the comment from
     * @param start The start offset of the comment
     * @param end The end offset of the comment
     *
     * @return The comment source extracted from the source module
     *
     * @throws ModelException If an exception occurs while accessing the underlying resource
     */
    private static String getCommentSource(ISourceModule sourceModule, int start, int end) throws ModelException {
        String source = sourceModule.getSource();

        return source.substring(start, end);
    }
}
TOP

Related Classes of com.dubture.symfony.core.util.AnnotationUtils

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.