Package groovy.text.markup

Source Code of groovy.text.markup.AutoNewLineTransformer

/*
* Copyright 2003-2014 the original author or authors.
*
* 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 groovy.text.markup;

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.VariableScope;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;

import java.util.Arrays;
import java.util.List;

/**
* This transformer is responsible for adding calls to the <i>newLine</i> method
* depending on the layout of the source code, inside builder like blocks.
*
* @author Cedric Champeau
*/
class AutoNewLineTransformer extends ClassCodeVisitorSupport {
    private final SourceUnit unit;
    private boolean inBuilderMethod;

    public AutoNewLineTransformer(final SourceUnit unit) {
        this.unit = unit;
    }

    @Override
    protected SourceUnit getSourceUnit() {
        return unit;
    }

    @Override
    public void visitMethodCallExpression(final MethodCallExpression call) {
        boolean old = inBuilderMethod;
        inBuilderMethod = false;
        if (call.isImplicitThis() && call.getArguments() instanceof TupleExpression) {
            List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
            if (!expressions.isEmpty()) {
                Expression lastArg = expressions.get(expressions.size() - 1);
                if (lastArg instanceof ClosureExpression) {
                    call.getObjectExpression().visit(this);
                    call.getMethod().visit(this);
                    for (Expression expression : expressions) {
                        inBuilderMethod =  (expression == lastArg);
                        expression.visit(this);
                    }
                }
            }
        } else {
            super.visitMethodCallExpression(call);
        }
        inBuilderMethod = old;
    }

    @Override
    public void visitClosureExpression(final ClosureExpression expression) {
        super.visitClosureExpression(expression);
        if (inBuilderMethod) {
            Statement oldCode = expression.getCode();
            BlockStatement block = oldCode instanceof BlockStatement?
                    ((BlockStatement)oldCode):
                    new BlockStatement(Arrays.asList(oldCode), new VariableScope());
            List<Statement> statements = block.getStatements();
            if (!statements.isEmpty()) {
                Statement first = statements.get(0);
                Statement last = statements.get(statements.size()-1);
                if (expression.getLineNumber()<first.getLineNumber()) {
                    // there's a new line between { -> ... and the first statement
                    statements.add(0,createNewLine(expression));
                }
                if (expression.getLastLineNumber()>last.getLastLineNumber()) {
                    // there's a new line between { -> ... and the first statement
                    statements.add(createNewLine(expression));
                }
            }
            expression.setCode(block);
        }
    }

    private Statement createNewLine(final ASTNode node) {
        MethodCallExpression mce = new MethodCallExpression(
                new VariableExpression("this"),
                "newLine",
                ArgumentListExpression.EMPTY_ARGUMENTS
        );
        mce.setImplicitThis(true);
        mce.setSourcePosition(node);
        ExpressionStatement stmt = new ExpressionStatement(mce);
        stmt.setSourcePosition(node);
        return stmt;
    }
}
TOP

Related Classes of groovy.text.markup.AutoNewLineTransformer

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.