/*
* Copyright 2014 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.services.datamodeller.parser;
import java.util.Stack;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Parser;
import org.antlr.runtime.RecognizerSharedState;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenStream;
import org.kie.workbench.common.services.datamodeller.parser.descr.ClassDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ClassOrInterfaceTypeDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ElementDescriptor;
import org.kie.workbench.common.services.datamodeller.parser.descr.ElementDescriptor.ElementType;
import org.kie.workbench.common.services.datamodeller.parser.descr.EllipsisParameterDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.FieldDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.FileDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.HasClassOrInterfaceType;
import org.kie.workbench.common.services.datamodeller.parser.descr.HasModifiers;
import org.kie.workbench.common.services.datamodeller.parser.descr.HasPrimitiveType;
import org.kie.workbench.common.services.datamodeller.parser.descr.HasType;
import org.kie.workbench.common.services.datamodeller.parser.descr.HasTypeArguments;
import org.kie.workbench.common.services.datamodeller.parser.descr.IdentifierWithTypeArgumentsDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ImportDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.JavaTokenDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.MethodDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ModifierListDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.NormalParameterDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.PackageDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ParameterDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.ParameterListDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.QualifiedNameDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeArgumentDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeArgumentListDescr;
import org.kie.workbench.common.services.datamodeller.parser.descr.TypeDescr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavaParserBase extends Parser {
private static final Logger logger = LoggerFactory.getLogger( JavaParserBase.class );
public static enum ParserMode {
PARSE_CLASS,
PARSE_METHOD,
PARSE_FIELD,
PARSE_ANNOTATION,
PARSE_PACKAGE, PARSE_QUALIFIED_NAME, PARSE_TYPE
}
public JavaParserBase( TokenStream input, RecognizerSharedState state ) {
super( input, state );
}
protected FileDescr fileDescr = new FileDescr( );
protected MethodDescr methodDescr;
protected FieldDescr fieldDescr;
protected Stack<ElementDescriptor> context = new Stack<ElementDescriptor>( );
protected boolean declaringMethodReturnType = false;
protected boolean declaringSuperClass = false;
protected int classLevel = 0;
protected ParserMode mode = ParserMode.PARSE_CLASS;
protected StringBuilder sourceBuffer;
public FileDescr getFileDescr( ) {
return fileDescr;
}
public ParserMode getMode( ) {
return mode;
}
public MethodDescr getMethodDescr( ) {
return methodDescr;
}
public FieldDescr getFieldDescr( ) {
return fieldDescr;
}
public void setMode( ParserMode mode ) {
this.mode = mode;
}
public StringBuilder getSourceBuffer( ) {
return sourceBuffer;
}
public void setSourceBuffer( StringBuilder sourceBuffer ) {
this.sourceBuffer = sourceBuffer;
}
private ClassDescr getClassDescr( ) {
return fileDescr.getClassDescr( );
}
protected void initContext( ) {
context.push( fileDescr );
if ( sourceBuffer != null && sourceBuffer.length( ) > 0 ) {
fileDescr.setStop( sourceBuffer.length( ) - 1 );
}
}
protected void log( String message ) {
if (logger.isDebugEnabled()) logger.debug( message );
}
protected boolean isFieldOnTop( ) {
return isOnTop( ElementType.FIELD );
}
protected boolean isMethodOnTop( ) {
return isOnTop( ElementType.METHOD );
}
protected boolean isTypeOnTop( ) {
return isOnTop( ElementType.TYPE );
}
protected boolean isClassOrInterfaceTypeOnTop( ) {
return isOnTop( ElementType.CLASS_OR_INTERFACE_TYPE );
}
protected boolean isTypeArgumentOnTop( ) {
return isOnTop( ElementType.TYPE_ARGUMENT );
}
protected boolean isParameterOnTop( ) {
return isOnTop( ElementType.NORMAL_PARAMETER ) || isOnTop( ElementType.ELLIPSIS_PARAMETER );
}
protected boolean isNormalParameterOnTop( ) {
return isOnTop( ElementType.NORMAL_PARAMETER );
}
protected boolean isEllipsisParameterOnTop( ) {
return isOnTop( ElementType.ELLIPSIS_PARAMETER );
}
protected boolean isModifierListOnTop( ) {
return isOnTop( ElementType.MODIFIER_LIST );
}
protected boolean isClassOnTop( ) {
return isOnTop( ElementType.CLASS );
}
protected boolean isFileOnTop( ) {
return isOnTop( ElementType.FILE );
}
protected boolean isQualifiedNameOnTop( ) {
return isOnTop( ElementType.QUALIFIED_NAME );
}
protected boolean isPackageOnTop( ) {
return isOnTop( ElementType.PACKAGE );
}
protected boolean isImportOnTop( ) {
return isOnTop( ElementType.IMPORT );
}
protected boolean isIdentifierWithTypeArgumentsOnTop( ) {
return isOnTop( ElementType.IDENTIFIER_WITH_TYPE_ARGUMENTS );
}
protected boolean isTypeArgumentListOnTop( ) {
return isOnTop( ElementType.TYPE_ARGUMENT_LIST );
}
protected boolean isOnTop( ElementType elementType ) {
return !context.empty( ) && context.peek( ).isElementType( elementType );
}
protected MethodDescr popMethod( ) {
return isMethodOnTop( ) ? ( MethodDescr ) context.pop( ) : null;
}
protected MethodDescr peekMethod( ) {
return isMethodOnTop( ) ? ( MethodDescr ) context.peek( ) : null;
}
protected FieldDescr popField( ) {
return isFieldOnTop( ) ? ( FieldDescr ) context.pop( ) : null;
}
protected FieldDescr peekField( ) {
return isFieldOnTop( ) ? ( FieldDescr ) context.peek( ) : null;
}
protected TypeDescr popType( ) {
return isTypeOnTop( ) ? ( TypeDescr ) context.pop( ) : null;
}
protected TypeDescr peekType( ) {
return isTypeOnTop( ) ? ( TypeDescr ) context.peek( ) : null;
}
protected ClassOrInterfaceTypeDescr popClassOrInterfaceType( ) {
return isClassOrInterfaceTypeOnTop( ) ? ( ClassOrInterfaceTypeDescr ) context.pop( ) : null;
}
protected ClassOrInterfaceTypeDescr peekClassOrInterfaceType( ) {
return isClassOrInterfaceTypeOnTop( ) ? ( ClassOrInterfaceTypeDescr ) context.peek( ) : null;
}
protected TypeArgumentDescr popTypeArgument( ) {
return isTypeArgumentOnTop( ) ? ( TypeArgumentDescr ) context.pop( ) : null;
}
protected ParameterDescr popParameter( ) {
return isParameterOnTop( ) ? ( ParameterDescr ) context.pop( ) : null;
}
protected ParameterDescr peekParameter( ) {
return isParameterOnTop( ) ? ( ParameterDescr ) context.peek( ) : null;
}
protected NormalParameterDescr popNormalParameter( ) {
return isNormalParameterOnTop( ) ? ( NormalParameterDescr ) context.pop( ) : null;
}
protected NormalParameterDescr peekNormalParameter( ) {
return isNormalParameterOnTop( ) ? ( NormalParameterDescr ) context.peek( ) : null;
}
protected EllipsisParameterDescr popEllipsisParameter( ) {
return isEllipsisParameterOnTop( ) ? ( EllipsisParameterDescr ) context.pop( ) : null;
}
protected EllipsisParameterDescr peekEllipsisParameter( ) {
return isEllipsisParameterOnTop( ) ? ( EllipsisParameterDescr ) context.peek( ) : null;
}
protected TypeArgumentListDescr popTypeArgumentList( ) {
return isTypeArgumentListOnTop( ) ? ( TypeArgumentListDescr ) context.pop( ) : null;
}
protected TypeArgumentListDescr peekTypeArgumentList( ) {
return isTypeArgumentListOnTop( ) ? ( TypeArgumentListDescr ) context.peek( ) : null;
}
protected ModifierListDescr popModifierList( ) {
return isModifierListOnTop( ) ? ( ModifierListDescr ) context.pop( ) : null;
}
protected ModifierListDescr peekModifierList( ) {
return isModifierListOnTop( ) ? ( ModifierListDescr ) context.peek( ) : null;
}
protected ClassDescr popClass( ) {
return isClassOnTop( ) ? ( ClassDescr ) context.pop( ) : null;
}
protected ClassDescr peekClass( ) {
return isClassOnTop( ) ? ( ClassDescr ) context.peek( ) : null;
}
protected FileDescr popFile( ) {
return isFileOnTop( ) ? ( FileDescr ) context.pop( ) : null;
}
protected FileDescr peekFile( ) {
return isFileOnTop( ) ? ( FileDescr ) context.peek( ) : null;
}
protected PackageDescr popPackage( ) {
return isPackageOnTop( ) ? ( PackageDescr ) context.pop( ) : null;
}
protected PackageDescr peekPackage( ) {
return isPackageOnTop( ) ? ( PackageDescr ) context.peek( ) : null;
}
protected ImportDescr popImport( ) {
return isImportOnTop( ) ? ( ImportDescr ) context.pop( ) : null;
}
protected ImportDescr peekImport( ) {
return isImportOnTop( ) ? ( ImportDescr ) context.peek( ) : null;
}
protected QualifiedNameDescr popQualifiedName( ) {
return isQualifiedNameOnTop( ) ? ( QualifiedNameDescr ) context.pop( ) : null;
}
protected QualifiedNameDescr peekQualifiedName( ) {
return isQualifiedNameOnTop( ) ? ( QualifiedNameDescr ) context.peek( ) : null;
}
protected IdentifierWithTypeArgumentsDescr popIdentifierWithTypeArguments( ) {
return isIdentifierWithTypeArgumentsOnTop( ) ? ( IdentifierWithTypeArgumentsDescr ) context.pop( ) : null;
}
protected IdentifierWithTypeArgumentsDescr peekIdentifierWithTypeArguments( ) {
return isIdentifierWithTypeArgumentsOnTop( ) ? ( IdentifierWithTypeArgumentsDescr ) context.peek( ) : null;
}
protected TypeArgumentDescr peekTypeArgument( ) {
return isTypeArgumentOnTop( ) ? ( TypeArgumentDescr ) context.peek( ) : null;
}
protected HasModifiers peekHasModifiers( ) {
return !context.empty( ) && ( context.peek( ) instanceof HasModifiers ) ? ( HasModifiers ) context.peek( ) : null;
}
protected HasType peekHasType( ) {
return !context.empty( ) && ( context.peek( ) instanceof HasType ) ? ( HasType ) context.peek( ) : null;
}
protected HasClassOrInterfaceType peekHasClassOrInterfaceType( ) {
return !context.empty( ) && ( context.peek( ) instanceof HasClassOrInterfaceType ) ? ( HasClassOrInterfaceType ) context.peek( ) : null;
}
protected HasPrimitiveType peekHasPrimitiveType( ) {
return !context.empty( ) && ( context.peek( ) instanceof HasPrimitiveType ) ? ( HasPrimitiveType ) context.peek( ) : null;
}
protected HasTypeArguments peekHasTypeArguments( ) {
return !context.empty( ) && ( context.peek( ) instanceof HasTypeArguments ) ? ( HasTypeArguments ) context.peek( ) : null;
}
protected int start( CommonToken token ) {
return token != null ? token.getStartIndex( ) : -1;
}
protected int stop( CommonToken token ) {
return token != null ? token.getStopIndex( ) : -1;
}
protected int line( Token token ) {
return token != null ? token.getLine( ) : -1;
}
protected int position( Token token ) {
return token != null ? token.getCharPositionInLine( ) : -1;
}
protected int calcStart( String text, Token token ) {
return 1;
}
protected int calcStop( String text, Token token ) {
return 1;
}
protected int calcStop( ) {
return 0;
}
protected boolean isBacktracking( ) {
return state.backtracking > 0;
}
protected void updateOnAfter( ElementDescriptor element, String text, CommonToken stop ) {
element.setText( text );
element.setStop( stop( stop ) );
}
protected void updateOnAfter( ElementDescriptor element, String text, CommonToken start, CommonToken stop ) {
element.setText( text );
element.setStart( start( start ) );
element.setLine( line( start ) );
element.setPosition( position( start ) );
element.setStop( stop( stop ) );
}
protected boolean isDeclaringMethodReturnType( ) {
return declaringMethodReturnType;
}
protected void setDeclaringMethodReturnType( boolean declaringMethodReturnType ) {
this.declaringMethodReturnType = declaringMethodReturnType;
}
public void setDeclaringSuperClass( boolean declaringSuperClass ) {
this.declaringSuperClass = declaringSuperClass;
}
public boolean isDeclaringMainClass( ) {
return classLevel == 1 && mode == ParserMode.PARSE_CLASS;
}
public int increaseClassLevel( ) {
return ++classLevel;
}
public int decreaseClassLevel( ) {
return --classLevel;
}
protected void processType( TypeDescr type ) {
//if we are processing a method declaration return type, or a method parameter, or a field type
if ( isDeclaringMainClass( ) || mode == ParserMode.PARSE_FIELD || mode == ParserMode.PARSE_METHOD || mode == ParserMode.PARSE_TYPE ) {
if ( isTypeArgumentOnTop( ) ) {
peekTypeArgument( ).setType( type );
} else if ( isFieldOnTop( ) ) {
peekField( ).setType( type );
} else if ( isMethodOnTop( ) && declaringMethodReturnType ) {
peekMethod( ).setType( type );
} else if ( isParameterOnTop( ) ) {
peekParameter( ).setType( type );
} else if ( isClassOnTop( ) && declaringSuperClass ) {
peekClass( ).setSuperClass( type );
}
}
}
protected void processModifiers( ModifierListDescr modifiers ) {
if ( isDeclaringMainClass( ) || mode == ParserMode.PARSE_FIELD || mode == ParserMode.PARSE_METHOD ) {
if ( isTypeArgumentOnTop( ) || isMethodOnTop( ) || isFieldOnTop( ) || isParameterOnTop( ) || isClassOnTop( ) ) {
peekHasModifiers( ).setModifiers( modifiers );
}
}
}
protected void processMethod( MethodDescr methodDescr ) {
if ( isDeclaringMainClass( ) ) {
getClassDescr( ).addMember( methodDescr );
} else if ( mode == ParserMode.PARSE_METHOD ) {
this.methodDescr = methodDescr;
}
}
protected void setFormalParamsStart( ElementType type, String text, int start, int stop, int line, int position ) {
if ( isDeclaringMainClass( ) || mode == ParserMode.PARSE_METHOD ) {
if ( isMethodOnTop( ) ) {
peekMethod( ).setParamsStartParen( new JavaTokenDescr( type, text, start, stop, line, position ) );
}
}
}
protected void setFormalParamsStop( ElementType type, String text, int start, int stop, int line, int position ) {
if ( isDeclaringMainClass( ) || mode == ParserMode.PARSE_METHOD ) {
if ( isMethodOnTop( ) ) {
peekMethod( ).setParamsStopParen( new JavaTokenDescr( type, text, start, stop, line, position ) );
}
}
}
protected void processParameterList( ParameterListDescr params ) {
if ( isDeclaringMainClass( ) || mode == ParserMode.PARSE_METHOD ) {
if ( isMethodOnTop( ) ) {
peekMethod( ).setParamsList( params );
}
}
}
protected void processField( FieldDescr fieldDescr ) {
if ( isDeclaringMainClass( ) ) {
getClassDescr( ).addMember( fieldDescr );
} else if ( mode == ParserMode.PARSE_FIELD ) {
this.fieldDescr = fieldDescr;
}
}
protected void processClass( ClassDescr classDescr ) {
if ( isDeclaringMainClass( ) ) {
fileDescr.setClassDescr( classDescr );
context.push( classDescr );
}
}
protected void processQualifiedName( QualifiedNameDescr nameDescr ) {
/**
if (isPackageOnTop()) {
PackageDescr packageDescr = peekPackage();
packageDescr.setQualifiedName(nameDescr);
}
**/
}
protected void processPackage( PackageDescr packageDescr ) {
fileDescr.setPackageDescr( packageDescr );
}
protected void processImport( ImportDescr importDescr ) {
fileDescr.addImport( importDescr );
}
/*
protected void processTypeArgumentList( TypeArgumentListDescr arguments ) {
if ( isDeclaringMainClass( ) ) {
if ( isIdentifierWithTypeArgumentsOnTop( ) ) {
peekIdentifierWithTypeArguments( ).setArguments( arguments );
}
}
}
*/
protected void processClassBodyStart( JavaTokenDescr bodyStart ) {
if (isDeclaringMainClass()) {
peekClass().setBodyStartBrace( bodyStart );
}
}
protected void processClassBodyStop( JavaTokenDescr bodyStop ) {
if (isDeclaringMainClass()) {
peekClass().setBodyStopBrace( bodyStop );
}
}
}