Package japa.parser

Source Code of japa.parser.JavaParser

/*
* Copyright (C) 2008 Júlio Vilmar Gesser.
*
* This file is part of Java 1.5 parser and Abstract Syntax Tree.
*
* Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Java 1.5 parser and Abstract Syntax Tree.  If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Created on 05/10/2006
*/
package japa.parser;

import static japa.parser.PositionUtils.areInOrder;
import static japa.parser.PositionUtils.sortByBeginPosition;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.ImportDeclaration;
import japa.parser.ast.Node;
import japa.parser.ast.body.AnnotableNode;
import japa.parser.ast.body.BodyDeclaration;
import japa.parser.ast.comments.Comment;
import japa.parser.ast.comments.CommentsCollection;
import japa.parser.ast.comments.CommentsParser;
import japa.parser.ast.comments.LineComment;
import japa.parser.ast.expr.AnnotationExpr;
import japa.parser.ast.expr.Expression;
import japa.parser.ast.stmt.BlockStmt;
import japa.parser.ast.stmt.Statement;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

// FIXME this file does not seem to be generated by javacc. Is the doc wrong, or the javacc config?
/**
* <p>
* This class was generated automatically by javacc, do not edit.
* </p>
* <p>
* Parse Java 1.5 source code and creates Abstract Syntax Tree classes.
* </p>
*
* @author Júlio Vilmar Gesser
*/
public final class JavaParser {
  private JavaParser() {
    // hide the constructor
  }

    private static boolean _doNotAssignCommentsPreceedingEmptyLines = true;

    private static boolean _doNotConsiderAnnotationsAsNodeStartForCodeAttribution = false;

    public static boolean getDoNotConsiderAnnotationsAsNodeStartForCodeAttribution()
    {
        return _doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
    }

    public static void setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution) {
        _doNotConsiderAnnotationsAsNodeStartForCodeAttribution = doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
    }

    public static boolean getDoNotAssignCommentsPreceedingEmptyLines()
    {
        return _doNotAssignCommentsPreceedingEmptyLines;
    }

    public static void setDoNotAssignCommentsPreceedingEmptyLines(boolean doNotAssignCommentsPreceedingEmptyLines)
    {
        _doNotAssignCommentsPreceedingEmptyLines = doNotAssignCommentsPreceedingEmptyLines;
    }

    public static CompilationUnit parse(final InputStream in,
                                        final String encoding) throws ParseException {
        return parse(in,encoding,true);
    }

  /**
   * Parses the Java code contained in the {@link InputStream} and returns a
   * {@link CompilationUnit} that represents it.
   *
   * @param in
   *            {@link InputStream} containing Java source code
   * @param encoding
   *            encoding of the source code
   * @return CompilationUnit representing the Java source code
   * @throws ParseException
   *             if the source code has parser errors
   */
  public static CompilationUnit parse(final InputStream in,
      final String encoding, boolean considerComments) throws ParseException {
        try {
            String code = SourcesHelper.streamToString(in, encoding);
            InputStream in1 = SourcesHelper.stringToStream(code);
            CompilationUnit cu = new ASTParser(in1, encoding).CompilationUnit();
            if (considerComments){
                insertComments(cu,code);
            }
            return cu;
        } catch (IOException ioe){
            throw new ParseException(ioe.getMessage());
        }
  }

  /**
   * Parses the Java code contained in the {@link InputStream} and returns a
   * {@link CompilationUnit} that represents it.
   *
   * @param in
   *            {@link InputStream} containing Java source code
   * @return CompilationUnit representing the Java source code
   * @throws ParseException
   *             if the source code has parser errors
   */
  public static CompilationUnit parse(final InputStream in)
      throws ParseException {
    return parse(in, null,true);
  }

    public static CompilationUnit parse(final File file, final String encoding)
            throws ParseException, IOException {
        return parse(file,encoding,true);
    }

  /**
   * Parses the Java code contained in a {@link File} and returns a
   * {@link CompilationUnit} that represents it.
   *
   * @param file
   *            {@link File} containing Java source code
   * @param encoding
   *            encoding of the source code
   * @return CompilationUnit representing the Java source code
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static CompilationUnit parse(final File file, final String encoding, boolean considerComments)
      throws ParseException, IOException {
    final FileInputStream in = new FileInputStream(file);
    try {
      return parse(in, encoding, considerComments);
    } finally {
      in.close();
    }
  }

  /**
   * Parses the Java code contained in a {@link File} and returns a
   * {@link CompilationUnit} that represents it.
   *
   * @param file
   *            {@link File} containing Java source code
   * @return CompilationUnit representing the Java source code
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static CompilationUnit parse(final File file) throws ParseException,
      IOException {
    return parse(file, null,true);
  }

  public static CompilationUnit parse(final Reader reader, boolean considerComments)
      throws ParseException {
        try {
            String code = SourcesHelper.readerToString(reader);
            Reader reader1 = SourcesHelper.stringToReader(code);
            CompilationUnit cu = new ASTParser(reader1).CompilationUnit();
            if (considerComments){
                insertComments(cu,code);
            }
            return cu;
        } catch (IOException ioe){
            throw new ParseException(ioe.getMessage());
        }
  }

  /**
   * Parses the Java block contained in a {@link String} and returns a
   * {@link BlockStmt} that represents it.
   *
   * @param blockStatement
   *            {@link String} containing Java block code
   * @return BlockStmt representing the Java block
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static BlockStmt parseBlock(final String blockStatement)
      throws ParseException {
    StringReader sr = new StringReader(blockStatement);
    BlockStmt result = new ASTParser(sr).Block();
    sr.close();
    return result;
  }

  /**
   * Parses the Java statement contained in a {@link String} and returns a
   * {@link Statement} that represents it.
   *
   * @param statement
   *            {@link String} containing Java statement code
   * @return Statement representing the Java statement
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static Statement parseStatement(final String statement)
      throws ParseException {
    StringReader sr = new StringReader(statement);
    Statement stmt = new ASTParser(sr).Statement();
    sr.close();
    return stmt;
  }

  /**
   * Parses the Java import contained in a {@link String} and returns a
   * {@link ImportDeclaration} that represents it.
   *
   * @param importDeclaration
   *            {@link String} containing Java import code
   * @return ImportDeclaration representing the Java import declaration
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static ImportDeclaration parseImport(final String importDeclaration)
      throws ParseException {
    StringReader sr = new StringReader(importDeclaration);
    ImportDeclaration id = new ASTParser(sr).ImportDeclaration();
    sr.close();
    return id;
  }

  /**
   * Parses the Java expression contained in a {@link String} and returns a
   * {@link Expression} that represents it.
   *
   * @param expression
   *            {@link String} containing Java expression
   * @return Expression representing the Java expression
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static Expression parseExpression(final String expression)
      throws ParseException {
    StringReader sr = new StringReader(expression);
    Expression e = new ASTParser(sr).Expression();
    sr.close();
    return e;
  }

  /**
   * Parses the Java annotation contained in a {@link String} and returns a
   * {@link AnnotationExpr} that represents it.
   *
   * @param annotation
   *            {@link String} containing Java annotation
   * @return AnnotationExpr representing the Java annotation
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static AnnotationExpr parseAnnotation(final String annotation)
      throws ParseException {
    StringReader sr = new StringReader(annotation);
    AnnotationExpr ae = new ASTParser(sr).Annotation();
    sr.close();
    return ae;
  }

  /**
   * Parses the Java body declaration(e.g fields or methods) contained in a
   * {@link String} and returns a {@link BodyDeclaration} that represents it.
   *
   * @param body
   *            {@link String} containing Java body declaration
   * @return BodyDeclaration representing the Java annotation
   * @throws ParseException
   *             if the source code has parser errors
   * @throws IOException
   */
  public static BodyDeclaration parseBodyDeclaration(final String body)
      throws ParseException {
    StringReader sr = new StringReader(body);
    BodyDeclaration bd = new ASTParser(sr).AnnotationBodyDeclaration();
    sr.close();
    return bd;
  }

    /**
     * Comments are attributed to the thing the comment and are removed from
     * allComments.
     */
    private static void insertCommentsInCu(CompilationUnit cu, CommentsCollection commentsCollection){
        if (commentsCollection.size()==0) return;

        // I should sort all the direct children and the comments, if a comment is the first thing then it
        // a comment to the CompilationUnit
        // FIXME if there is no package it could be also a comment to the following class...
        // so I could use some heuristics in these cases to distinguish the two cases

        List<Comment> comments = commentsCollection.getAll();
        sortByBeginPosition(comments);
        List<Node> children = cu.getChildrenNodes();
        sortByBeginPosition(children);

        if (cu.getPackage()!=null && (children.size()==0 || areInOrder(comments.get(0), children.get(0)))){
            cu.setComment(comments.get(0));
            comments.remove(0);
        }

        insertCommentsInNode(cu,comments);
    }

    private static boolean attributeLineCommentToNodeOrChild(Node node, LineComment lineComment)
    {
        // The node start and end at the same line as the comment,
        // let's give to it the comment
        if (node.getBeginLine()==lineComment.getBeginLine() && !node.hasComment())
        {
            node.setComment(lineComment);
            return true;
        } else {
            // try with all the children, sorted by reverse position (so the
            // first one is the nearest to the comment
            List<Node> children = new LinkedList<Node>();
            children.addAll(node.getChildrenNodes());
            PositionUtils.sortByBeginPosition(children);
            Collections.reverse(children);

            for (Node child : children)
            {
                if (attributeLineCommentToNodeOrChild(child, lineComment))
                {
                    return true;
                }
            }

            return false;
        }
    }

    /**
     * This method try to attributes the nodes received to child of the node.
     * It returns the node that were not attributed.
     */
    private static void insertCommentsInNode(Node node, List<Comment> commentsToAttribute){
        if (commentsToAttribute.size()==0) return;

        // the comments can:
        // 1) Inside one of the child, then it is the child that have to associate them
        // 2) If they are not inside a child they could be preceeding nothing, a comment or a child
        //    if they preceed a child they are assigned to it, otherweise they remain "orphans"

        List<Node> children = node.getChildrenNodes();
        sortByBeginPosition(children);

        for (Node child : children){
            List<Comment> commentsInsideChild = new LinkedList<Comment>();
            for (Comment c : commentsToAttribute){
                if (PositionUtils.nodeContains(child, c, _doNotConsiderAnnotationsAsNodeStartForCodeAttribution)){
                    commentsInsideChild.add(c);
                }
            }
            commentsToAttribute.removeAll(commentsInsideChild);
            insertCommentsInNode(child,commentsInsideChild);
        }

        // I can attribute in line comments to elements preceeding them, if there
        // is something contained in their line
        List<Comment> attributedComments = new LinkedList<Comment>();
        for (Comment comment : commentsToAttribute)
        {
            if (comment.isLineComment())
            {
                for (Node child : children)
                {
                    if (child.getEndLine()==comment.getBeginLine())
                    {
                        if (attributeLineCommentToNodeOrChild(child, comment.asLineComment()))
                        {
                            attributedComments.add(comment);
                        }
                    }
                }
            }
        }

        // at this point I create an ordered list of all remaining comments and children
        Comment previousComment = null;
        attributedComments = new LinkedList<Comment>();
        List<Node> childrenAndComments = new LinkedList<Node>();
        childrenAndComments.addAll(children);
        childrenAndComments.addAll(commentsToAttribute);
        sortByBeginPosition(childrenAndComments, _doNotConsiderAnnotationsAsNodeStartForCodeAttribution);

        for (Node thing : childrenAndComments){
            if (thing instanceof Comment){
                previousComment = (Comment)thing;
                if (!previousComment.isOrphan())
                {
                    previousComment = null;
                }
            } else {
                if (previousComment != null && !thing.hasComment()){
                    if (!_doNotAssignCommentsPreceedingEmptyLines || !thereAreLinesBetween(previousComment, thing)) {
                        thing.setComment(previousComment);
                        attributedComments.add(previousComment);
                        previousComment = null;
                    }
                }
            }
        }

        commentsToAttribute.removeAll(attributedComments);

        // all the remaining are orphan nodes
        for (Comment c : commentsToAttribute){
            if (c.isOrphan()) {
                node.addOrphanComment(c);
            }
        }
    }

    private static boolean thereAreLinesBetween(Node a, Node b)
    {
        if (!PositionUtils.areInOrder(a, b))
        {
            return thereAreLinesBetween(b, a);
        }
        int endOfA = a.getEndLine();
        return b.getBeginLine()>(a.getEndLine()+1);
    }

    private static void insertComments(CompilationUnit cu, String code) throws IOException {
        CommentsParser commentsParser = new CommentsParser();
        CommentsCollection allComments = commentsParser.parse(code);

        insertCommentsInCu(cu,allComments);
    }

}
TOP

Related Classes of japa.parser.JavaParser

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.