HHH-12511 Make ASTPrinter threadsafe and have code reuse their instances

This commit is contained in:
Sanne Grinovero 2018-04-12 18:40:31 +01:00
parent 782f023a5a
commit 0546eaac3b
11 changed files with 56 additions and 69 deletions

View File

@ -20,6 +20,7 @@ import org.hibernate.hql.internal.antlr.HqlBaseParser;
import org.hibernate.hql.internal.antlr.HqlTokenTypes;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.ASTUtil;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -41,11 +42,6 @@ public final class HqlParser extends HqlBaseParser {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HqlParser.class );
private final ParseErrorHandler parseErrorHandler;
private final ASTPrinter printer = getASTPrinter();
private static ASTPrinter getASTPrinter() {
return new ASTPrinter( org.hibernate.hql.internal.antlr.HqlTokenTypes.class );
}
/**
* Get a HqlParser instance for the given HQL string.
@ -362,7 +358,7 @@ public final class HqlParser extends HqlBaseParser {
}
private void showAst(AST ast, PrintWriter pw) {
printer.showAst( ast, pw );
TokenPrinters.HQL_TOKEN_PRINTER.showAst( ast, pw );
}
@Override

View File

@ -65,6 +65,7 @@ import org.hibernate.hql.internal.ast.util.LiteralProcessor;
import org.hibernate.hql.internal.ast.util.NodeTraverser;
import org.hibernate.hql.internal.ast.util.SessionFactoryHelper;
import org.hibernate.hql.internal.ast.util.SyntheticAndFactory;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.hql.spi.QueryTranslator;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
@ -118,7 +119,6 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
private final AliasGenerator aliasGenerator = new AliasGenerator();
private final LiteralProcessor literalProcessor;
private final ParseErrorHandler parseErrorHandler;
private final ASTPrinter printer;
private final String collectionFilterRole;
private FromClause currentFromClause;
@ -171,7 +171,6 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
this.tokenReplacements = tokenReplacements;
this.collectionFilterRole = collectionRole;
this.hqlParser = parser;
this.printer = new ASTPrinter( SqlTokenTypes.class );
}
// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -194,7 +193,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
private String buildTraceNodeName(AST tree) {
return tree == null
? "???"
: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
: tree.getText() + " [" + TokenPrinters.SQL_TOKEN_PRINTER.getTokenTypeName( tree.getType() ) + "]";
}
@Override
@ -1337,7 +1336,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
}
public ASTPrinter getASTPrinter() {
return printer;
return TokenPrinters.SQL_TOKEN_PRINTER;
}
public ArrayList<ParameterSpecification> getParameterSpecs() {

View File

@ -42,6 +42,7 @@ import org.hibernate.hql.internal.ast.tree.UpdateStatement;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.ASTUtil;
import org.hibernate.hql.internal.ast.util.NodeTraverser;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.hql.spi.FilterTranslator;
import org.hibernate.hql.spi.ParameterTranslations;
import org.hibernate.internal.CoreMessageLogger;
@ -262,8 +263,6 @@ public class QueryTranslatorImpl implements FilterTranslator {
}
}
private static final ASTPrinter SQL_TOKEN_PRINTER = new ASTPrinter( SqlTokenTypes.class );
private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
final HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
final AST hqlAst = parser.getAST();
@ -272,7 +271,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
w.statement( hqlAst );
if ( LOG.isDebugEnabled() ) {
LOG.debug( SQL_TOKEN_PRINTER.showAsString( w.getAST(), "--- SQL AST ---" ) );
LOG.debug( TokenPrinters.SQL_TOKEN_PRINTER.showAsString( w.getAST(), "--- SQL AST ---" ) );
}
w.getParseErrorHandler().throwQueryException();
@ -304,11 +303,9 @@ public class QueryTranslatorImpl implements FilterTranslator {
return parser;
}
private static final ASTPrinter HQL_TOKEN_PRINTER = new ASTPrinter( HqlTokenTypes.class );
void showHqlAst(AST hqlAst) {
if ( LOG.isDebugEnabled() ) {
LOG.debug( HQL_TOKEN_PRINTER.showAsString( hqlAst, "--- HQL AST ---" ) );
LOG.debug( TokenPrinters.HQL_TOKEN_PRINTER.showAsString( hqlAst, "--- HQL AST ---" ) );
}
}

View File

@ -23,6 +23,7 @@ import org.hibernate.hql.internal.ast.tree.Node;
import org.hibernate.hql.internal.ast.tree.ParameterContainer;
import org.hibernate.hql.internal.ast.tree.ParameterNode;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -57,7 +58,6 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
private ParseErrorHandler parseErrorHandler;
private SessionFactoryImplementor sessionFactory;
private LinkedList<SqlWriter> outputStack = new LinkedList<SqlWriter>();
private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
private List<ParameterSpecification> collectedParameters = new ArrayList<ParameterSpecification>();
@ -81,7 +81,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
private String buildTraceNodeName(AST tree) {
return tree == null
? "???"
: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
: tree.getText() + " [" + TokenPrinters.SQL_TOKEN_PRINTER.getTokenTypeName( tree.getType() ) + "]";
}
@Override

View File

@ -16,6 +16,7 @@ import org.hibernate.hql.internal.antlr.SqlTokenTypes;
import org.hibernate.hql.internal.ast.util.ASTAppender;
import org.hibernate.hql.internal.ast.util.ASTIterator;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.type.Type;
import antlr.SemanticException;
@ -157,7 +158,7 @@ public class SelectClause extends SelectExpressionList {
if ( type == null ) {
throw new QueryException(
"No data type for node: " + selectExpression.getClass().getName() + " "
+ new ASTPrinter( SqlTokenTypes.class ).showAsString( (AST) selectExpression, "" )
+ TokenPrinters.SQL_TOKEN_PRINTER.showAsString( (AST) selectExpression, "" )
);
}
//sqlResultTypeList.add( type );

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import antlr.collections.AST;
@ -44,7 +45,7 @@ public abstract class SelectExpressionList extends HqlSqlWalkerNode {
else {
throw new IllegalStateException(
"Unexpected AST: " + n.getClass().getName() + " "
+ new ASTPrinter( SqlTokenTypes.class ).showAsString( n, "" )
+ TokenPrinters.SQL_TOKEN_PRINTER.showAsString( n, "" )
);
}
p++;

View File

@ -20,52 +20,24 @@ import antlr.collections.AST;
/**
* Utility for generating pretty "ASCII art" representations of syntax trees.
*
* This class is threadsafe: reuse instances as needed.
*
* @author Joshua Davis
* @author Steve Ebersole
*/
public class ASTPrinter {
private final Map<Integer,String> tokenTypeNameCache;
private final boolean showClassNames;
/**
* Constructs a printer.
* <p/>
* Delegates to {@link #ASTPrinter(Class, boolean)} with {@link #isShowClassNames showClassNames} as <tt>true</tt>
* Constructs a printer. Package protected: use the constants from {TokenPrinters}
* @see TokenPrinters
*
* @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java
* interface generated by ANTLR.
*/
public ASTPrinter(Class tokenTypeConstants) {
this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), true );
}
public ASTPrinter(boolean showClassNames) {
this( (Map) null, showClassNames );
}
/**
* Constructs a printer.
*
* @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java
* interface generated by ANTLR.
* @param showClassNames Should the AST class names be shown.
*/
public ASTPrinter(Class tokenTypeConstants, boolean showClassNames) {
this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), showClassNames );
}
private ASTPrinter(Map<Integer,String> tokenTypeNameCache, boolean showClassNames) {
this.tokenTypeNameCache = tokenTypeNameCache;
this.showClassNames = showClassNames;
}
/**
* Getter for property 'showClassNames'.
*
* @return Value for property 'showClassNames'.
*/
public boolean isShowClassNames() {
return showClassNames;
ASTPrinter(Class tokenTypeConstants) {
this.tokenTypeNameCache = ASTUtil.generateTokenNameCache( tokenTypeConstants );
}
/**
@ -117,10 +89,7 @@ public class ASTPrinter {
*/
public String getTokenTypeName(int type) {
final Integer typeInteger = type;
String value = null;
if ( tokenTypeNameCache != null ) {
value = tokenTypeNameCache.get( typeInteger );
}
String value = tokenTypeNameCache.get( typeInteger );
if ( value == null ) {
value = typeInteger.toString();
}
@ -161,19 +130,17 @@ public class ASTPrinter {
}
private void showNode(PrintWriter pw, AST ast) {
String s = nodeToString( ast, isShowClassNames() );
String s = nodeToString( ast );
pw.println( s );
}
public String nodeToString(AST ast, boolean showClassName) {
public String nodeToString(AST ast) {
if ( ast == null ) {
return "{node:null}";
}
StringBuilder buf = new StringBuilder();
buf.append( "[" ).append( getTokenTypeName( ast.getType() ) ).append( "] " );
if ( showClassName ) {
buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " );
}
buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " );
buf.append( "'" );
String text = ast.getText();

View File

@ -0,0 +1,24 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.hql.internal.ast.util;
import org.hibernate.hql.internal.antlr.HqlTokenTypes;
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
import org.hibernate.sql.ordering.antlr.GeneratedOrderByFragmentRendererTokenTypes;
/**
* Commonly used token printers expressed as constants.
*/
public interface TokenPrinters {
ASTPrinter HQL_TOKEN_PRINTER = new ASTPrinter( HqlTokenTypes.class );
ASTPrinter SQL_TOKEN_PRINTER = new ASTPrinter( SqlTokenTypes.class );
ASTPrinter ORDERBY_FRAGMENT_PRINTER = new ASTPrinter( GeneratedOrderByFragmentRendererTokenTypes.class );
}

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.ordering.antlr;
import org.hibernate.NullPrecedence;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;
@ -25,7 +26,6 @@ import antlr.collections.AST;
public class OrderByFragmentRenderer extends GeneratedOrderByFragmentRenderer {
private static final Logger LOG = Logger.getLogger( OrderByFragmentRenderer.class.getName() );
private static final ASTPrinter printer = new ASTPrinter( GeneratedOrderByFragmentRendererTokenTypes.class );
private final SessionFactoryImplementor sessionFactory;
@ -56,7 +56,7 @@ public class OrderByFragmentRenderer extends GeneratedOrderByFragmentRenderer {
private String buildTraceNodeName(AST tree) {
return tree == null
? "???"
: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
: tree.getText() + " [" + TokenPrinters.ORDERBY_FRAGMENT_PRINTER.getTokenTypeName( tree.getType() ) + "]";
}
@Override

View File

@ -11,6 +11,7 @@ import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.jboss.logging.Logger;
@ -55,8 +56,7 @@ public class OrderByFragmentTranslator {
}
if ( LOG.isTraceEnabled() ) {
ASTPrinter printer = new ASTPrinter( OrderByTemplateTokenTypes.class );
LOG.trace( printer.showAsString( parser.getAST(), "--- {order-by fragment} ---" ) );
LOG.trace( TokenPrinters.ORDERBY_FRAGMENT_PRINTER.showAsString( parser.getAST(), "--- {order-by fragment} ---" ) );
}
// Render the parsed tree to text.

View File

@ -18,6 +18,8 @@ import org.hibernate.hql.internal.ast.util.ASTIterator;
import org.hibernate.hql.internal.ast.util.ASTParentsFirstIterator;
import org.hibernate.hql.internal.ast.util.ASTPrinter;
import org.hibernate.hql.internal.ast.util.ASTUtil;
import org.hibernate.hql.internal.ast.util.TokenPrinters;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
@ -36,7 +38,7 @@ public class ASTIteratorTest extends BaseUnitTestCase {
HqlParser parser = HqlParser.getInstance( input );
parser.statement();
AST ast = parser.getAST();
ASTPrinter printer = new ASTPrinter( HqlTokenTypes.class );
ASTPrinter printer = TokenPrinters.HQL_TOKEN_PRINTER;
printer.showAst( ast, new PrintWriter( System.out ) );
ASTIterator iterator = new ASTIterator( ast );
int count = 0;