<s> package org . eclipse . jdt . core . dom ; import java . util . List ; import java . util . Vector ; import org . eclipse . jdt . core . compiler . CategorizedProblem ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . core . compiler . IProblem ; import org . eclipse . jdt . internal . compiler . parser . RecoveryScanner ; import org . eclipse . jdt . internal . compiler . parser . RecoveryScannerData ; import org . eclipse . jdt . internal . compiler . parser . TerminalTokens ; import org . eclipse . jdt . internal . compiler . util . HashtableOfObjectToIntArray ; class ASTRecoveryPropagator extends DefaultASTVisitor { private static final int NOTHING = - 1 ; HashtableOfObjectToIntArray endingTokens = new HashtableOfObjectToIntArray ( ) ; { this . endingTokens . put ( AnonymousClassDeclaration . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( ArrayAccess . class , new int [ ] { TerminalTokens . TokenNameRBRACKET } ) ; this . endingTokens . put ( ArrayCreation . class , new int [ ] { NOTHING , TerminalTokens . TokenNameRBRACKET } ) ; this . endingTokens . put ( ArrayInitializer . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( ArrayType . class , new int [ ] { TerminalTokens . TokenNameRBRACKET } ) ; this . endingTokens . put ( AssertStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( Block . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( BooleanLiteral . class , new int [ ] { TerminalTokens . TokenNamefalse , TerminalTokens . TokenNametrue } ) ; this . endingTokens . put ( BreakStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( CharacterLiteral . class , new int [ ] { TerminalTokens . TokenNameCharacterLiteral } ) ; this . endingTokens . put ( ClassInstanceCreation . class , new int [ ] { TerminalTokens . TokenNameRBRACE , TerminalTokens . TokenNameRPAREN } ) ; this . endingTokens . put ( ConstructorInvocation . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( ContinueStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( DoStatement . class , new int [ ] { TerminalTokens . TokenNameRPAREN } ) ; this . endingTokens . put ( EmptyStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( ExpressionStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( FieldDeclaration . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( ImportDeclaration . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( Initializer . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( MethodDeclaration . class , new int [ ] { NOTHING , TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( MethodInvocation . class , new int [ ] { TerminalTokens . TokenNameRPAREN } ) ; this . endingTokens . put ( NullLiteral . class , new int [ ] { TerminalTokens . TokenNamenull } ) ; this . endingTokens . put ( NumberLiteral . class , new int [ ] { TerminalTokens . TokenNameIntegerLiteral , TerminalTokens . TokenNameLongLiteral , TerminalTokens . TokenNameFloatingPointLiteral , TerminalTokens . TokenNameDoubleLiteral } ) ; this . endingTokens . put ( PackageDeclaration . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( ParenthesizedExpression . class , new int [ ] { TerminalTokens . TokenNameRPAREN } ) ; this . endingTokens . put ( PostfixExpression . class , new int [ ] { TerminalTokens . TokenNamePLUS_PLUS , TerminalTokens . TokenNameMINUS_MINUS } ) ; this . endingTokens . put ( PrimitiveType . class , new int [ ] { TerminalTokens . TokenNamebyte , TerminalTokens . TokenNameshort , TerminalTokens . TokenNamechar , TerminalTokens . TokenNameint , TerminalTokens . TokenNamelong , TerminalTokens . TokenNamefloat , TerminalTokens . TokenNameboolean , TerminalTokens . TokenNamedouble , TerminalTokens . TokenNamevoid } ) ; this . endingTokens . put ( ReturnStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( SimpleName . class , new int [ ] { TerminalTokens . TokenNameIdentifier } ) ; this . endingTokens . put ( SingleVariableDeclaration . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( StringLiteral . class , new int [ ] { TerminalTokens . TokenNameStringLiteral } ) ; this . endingTokens . put ( SuperConstructorInvocation . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( SuperMethodInvocation . class , new int [ ] { TerminalTokens . TokenNameRPAREN } ) ; this . endingTokens . put ( SwitchCase . class , new int [ ] { TerminalTokens . TokenNameCOLON } ) ; this . endingTokens . put ( SwitchStatement . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( SynchronizedStatement . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( ThisExpression . class , new int [ ] { TerminalTokens . TokenNamethis } ) ; this . endingTokens . put ( ThrowStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; this . endingTokens . put ( TypeDeclaration . class , new int [ ] { TerminalTokens . TokenNameRBRACE } ) ; this . endingTokens . put ( TypeLiteral . class , new int [ ] { TerminalTokens . TokenNameclass } ) ; this . endingTokens . put ( VariableDeclarationStatement . class , new int [ ] { TerminalTokens . TokenNameSEMICOLON } ) ; } private CategorizedProblem [ ] problems ; private boolean [ ] usedOrIrrelevantProblems ; private RecoveryScannerData data ; private int blockDepth = 0 ; private int lastEnd ; private int [ ] insertedTokensKind ; private int [ ] insertedTokensPosition ; private boolean [ ] insertedTokensFlagged ; private boolean [ ] removedTokensFlagged ; private boolean [ ] replacedTokensFlagged ; private Vector stack = new Vector ( ) ; ASTRecoveryPropagator ( CategorizedProblem [ ] problems , RecoveryScannerData data ) { this . problems = problems ; this . usedOrIrrelevantProblems = new boolean [ problems . length ] ; this . data = data ; if ( this . data != null ) { int length = 0 ; for ( int i = 0 ; i < data . insertedTokensPtr + 1 ; i ++ ) { length += data . insertedTokens [ i ] . length ; } this . insertedTokensKind = new int [ length ] ; this . insertedTokensPosition = new int [ length ] ; this . insertedTokensFlagged = new boolean [ length ] ; int tokenCount = 0 ; for ( int i = 0 ; i < data . insertedTokensPtr + 1 ; i ++ ) { for ( int j = 0 ; j < data . insertedTokens [ i ] . length ; j ++ ) { this . insertedTokensKind [ tokenCount ] = data . insertedTokens [ i ] [ j ] ; this . insertedTokensPosition [ tokenCount ] = data . insertedTokensPosition [ i ] ; tokenCount ++ ; } } if ( data . removedTokensPtr != - 1 ) { this . removedTokensFlagged = new boolean [ data . removedTokensPtr + 1 ] ; } if ( data . replacedTokensPtr != - 1 ) { this . replacedTokensFlagged = new boolean [ data . replacedTokensPtr + 1 ] ; } } } public void endVisit ( Block node ) { this . blockDepth -- ; if ( this . blockDepth <= 0 ) { flagNodeWithInsertedTokens ( ) ; } super . endVisit ( node ) ; } public boolean visit ( Block node ) { boolean visitChildren = super . visit ( node ) ; this . blockDepth ++ ; return visitChildren ; } protected boolean visitNode ( ASTNode node ) { if ( this . blockDepth > 0 ) { int start = node . getStartPosition ( ) ; int end = start + node . getLength ( ) - 1 ; if ( this . insertedTokensFlagged != null ) { for ( int i = 0 ; i < this . insertedTokensFlagged . length ; i ++ ) { if ( this . insertedTokensPosition [ i ] >= start && this . insertedTokensPosition [ i ] <= end ) { return true ; } } } if ( this . removedTokensFlagged != null ) { for ( int i = 0 ; i <= this . data . removedTokensPtr ; i ++ ) { if ( this . data . removedTokensStart [ i ] >= start && this . data . removedTokensEnd [ i ] <= end ) { return true ; } } } if ( this . replacedTokensFlagged != null ) { for ( int i = 0 ; i <= this . data . replacedTokensPtr ; i ++ ) { if ( this . data . replacedTokensStart [ i ] >= start && this . data . replacedTokensEnd [ i ] <= end ) { return true ; } } } return false ; } return true ; } protected void endVisitNode ( ASTNode node ) { int start = node . getStartPosition ( ) ; int end = start + node . getLength ( ) - 1 ; if ( this . blockDepth < 1 ) { switch ( node . getNodeType ( ) ) { case ASTNode . ANNOTATION_TYPE_DECLARATION : case ASTNode . COMPILATION_UNIT : case ASTNode . ENUM_DECLARATION : case ASTNode . FIELD_DECLARATION : case ASTNode . IMPORT_DECLARATION : case ASTNode . INITIALIZER : case ASTNode . METHOD_DECLARATION : case ASTNode . PACKAGE_DECLARATION : case ASTNode . TYPE_DECLARATION : case ASTNode . MARKER_ANNOTATION : case ASTNode . NORMAL_ANNOTATION : case ASTNode . SINGLE_MEMBER_ANNOTATION : case ASTNode . BLOCK : if ( markIncludedProblems ( start , end ) ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; } break ; } } else { markIncludedProblems ( start , end ) ; if ( this . insertedTokensFlagged != null ) { if ( this . lastEnd != end ) { flagNodeWithInsertedTokens ( ) ; } this . stack . add ( node ) ; } if ( this . removedTokensFlagged != null ) { for ( int i = 0 ; i <= this . data . removedTokensPtr ; i ++ ) { if ( ! this . removedTokensFlagged [ i ] && this . data . removedTokensStart [ i ] >= start && this . data . removedTokensEnd [ i ] <= end ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; this . removedTokensFlagged [ i ] = true ; } } } if ( this . replacedTokensFlagged != null ) { for ( int i = 0 ; i <= this . data . replacedTokensPtr ; i ++ ) { if ( ! this . replacedTokensFlagged [ i ] && this . data . replacedTokensStart [ i ] >= start && this . data . replacedTokensEnd [ i ] <= end ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; this . replacedTokensFlagged [ i ] = true ; } } } } this . lastEnd = end ; } private void flagNodeWithInsertedTokens ( ) { if ( this . insertedTokensKind != null && this . insertedTokensKind . length > 0 ) { int s = this . stack . size ( ) ; for ( int i = s - 1 ; i > - 1 ; i -- ) { flagNodesWithInsertedTokensAtEnd ( ( ASTNode ) this . stack . get ( i ) ) ; } for ( int i = 0 ; i < s ; i ++ ) { flagNodesWithInsertedTokensInside ( ( ASTNode ) this . stack . get ( i ) ) ; } this . stack = new Vector ( ) ; } } private boolean flagNodesWithInsertedTokensAtEnd ( ASTNode node ) { int [ ] expectedEndingToken = this . endingTokens . get ( node . getClass ( ) ) ; if ( expectedEndingToken != null ) { int start = node . getStartPosition ( ) ; int end = start + node . getLength ( ) - 1 ; boolean flagParent = false ; done : for ( int i = this . insertedTokensKind . length - 1 ; i > - 1 ; i -- ) { if ( ! this . insertedTokensFlagged [ i ] && this . insertedTokensPosition [ i ] == end ) { this . insertedTokensFlagged [ i ] = true ; for ( int j = 0 ; j < expectedEndingToken . length ; j ++ ) { if ( expectedEndingToken [ j ] == this . insertedTokensKind [ i ] ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; break done ; } } flagParent = true ; } } if ( flagParent ) { ASTNode parent = node . getParent ( ) ; while ( parent != null ) { parent . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; if ( ( parent . getStartPosition ( ) + parent . getLength ( ) - 1 ) != end ) { parent = null ; } else { parent = parent . getParent ( ) ; } } } } return true ; } private boolean flagNodesWithInsertedTokensInside ( ASTNode node ) { int start = node . getStartPosition ( ) ; int end = start + node . getLength ( ) - 1 ; for ( int i = 0 ; i < this . insertedTokensKind . length ; i ++ ) { if ( ! this . insertedTokensFlagged [ i ] && start <= this . insertedTokensPosition [ i ] && this . insertedTokensPosition [ i ] < end ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; this . insertedTokensFlagged [ i ] = true ; } } return true ; } private boolean markIncludedProblems ( int start , int end ) { boolean foundProblems = false ; next : for ( int i = 0 , max = this . problems . length ; i < max ; i ++ ) { CategorizedProblem problem = this . problems [ i ] ; if ( this . usedOrIrrelevantProblems [ i ] ) continue next ; switch ( problem . getID ( ) ) { case IProblem . ParsingErrorOnKeywordNoSuggestion : case IProblem . ParsingErrorOnKeyword : case IProblem . ParsingError : case IProblem . ParsingErrorNoSuggestion : case IProblem . ParsingErrorInsertTokenBefore : case IProblem . ParsingErrorInsertTokenAfter : case IProblem . ParsingErrorDeleteToken : case IProblem . ParsingErrorDeleteTokens : case IProblem . ParsingErrorMergeTokens : case IProblem . ParsingErrorInvalidToken : case IProblem . ParsingErrorMisplacedConstruct : case IProblem . ParsingErrorReplaceTokens : case IProblem . ParsingErrorNoSuggestionForTokens : case IProblem . ParsingErrorUnexpectedEOF : case IProblem . ParsingErrorInsertToComplete : case IProblem . ParsingErrorInsertToCompleteScope : case IProblem . ParsingErrorInsertToCompletePhrase : case IProblem . EndOfSource : case IProblem . InvalidHexa : case IProblem . InvalidOctal : case IProblem . InvalidCharacterConstant : case IProblem . InvalidEscape : case IProblem . InvalidInput : case IProblem . InvalidUnicodeEscape : case IProblem . InvalidFloat : case IProblem . NullSourceString : case IProblem . UnterminatedString : case IProblem . UnterminatedComment : case IProblem . InvalidDigit : break ; default : this . usedOrIrrelevantProblems [ i ] = true ; continue next ; } int problemStart = problem . getSourceStart ( ) ; int problemEnd = problem . getSourceEnd ( ) ; if ( ( start <= problemStart ) && ( problemStart <= end ) || ( start <= problemEnd ) && ( problemEnd <= end ) ) { this . usedOrIrrelevantProblems [ i ] = true ; foundProblems = true ; } } return foundProblems ; } public void endVisit ( ExpressionStatement node ) { endVisitNode ( node ) ; if ( ( node . getFlags ( ) & ASTNode . RECOVERED ) == 0 ) return ; Expression expression = node . getExpression ( ) ; if ( expression . getNodeType ( ) == ASTNode . ASSIGNMENT ) { Assignment assignment = ( Assignment ) expression ; Expression rightHandSide = assignment . getRightHandSide ( ) ; if ( rightHandSide . getNodeType ( ) == ASTNode . SIMPLE_NAME ) { SimpleName simpleName = ( SimpleName ) rightHandSide ; if ( CharOperation . equals ( RecoveryScanner . FAKE_IDENTIFIER , simpleName . getIdentifier ( ) . toCharArray ( ) ) ) { Expression expression2 = assignment . getLeftHandSide ( ) ; expression2 . setParent ( null , null ) ; expression2 . setFlags ( expression2 . getFlags ( ) | ASTNode . RECOVERED ) ; node . setExpression ( expression2 ) ; } } } } public void endVisit ( ForStatement node ) { endVisitNode ( node ) ; List initializers = node . initializers ( ) ; if ( initializers . size ( ) == 1 ) { Expression expression = ( Expression ) initializers . get ( 0 ) ; if ( expression . getNodeType ( ) == ASTNode . VARIABLE_DECLARATION_EXPRESSION ) { VariableDeclarationExpression variableDeclarationExpression = ( VariableDeclarationExpression ) expression ; List fragments = variableDeclarationExpression . fragments ( ) ; for ( int i = 0 , max = fragments . size ( ) ; i < max ; i ++ ) { VariableDeclarationFragment fragment = ( VariableDeclarationFragment ) fragments . get ( i ) ; SimpleName simpleName = fragment . getName ( ) ; if ( CharOperation . equals ( RecoveryScanner . FAKE_IDENTIFIER , simpleName . getIdentifier ( ) . toCharArray ( ) ) ) { fragments . remove ( fragment ) ; variableDeclarationExpression . setFlags ( variableDeclarationExpression . getFlags ( ) | ASTNode . RECOVERED ) ; } } } } } public void endVisit ( VariableDeclarationStatement node ) { endVisitNode ( node ) ; List fragments = node . fragments ( ) ; for ( int i = 0 , max = fragments . size ( ) ; i < max ; i ++ ) { VariableDeclarationFragment fragment = ( VariableDeclarationFragment ) fragments . get ( i ) ; Expression expression = fragment . getInitializer ( ) ; if ( expression == null ) continue ; if ( ( expression . getFlags ( ) & ASTNode . RECOVERED ) == 0 ) continue ; if ( expression . getNodeType ( ) == ASTNode . SIMPLE_NAME ) { SimpleName simpleName = ( SimpleName ) expression ; if ( CharOperation . equals ( RecoveryScanner . FAKE_IDENTIFIER , simpleName . getIdentifier ( ) . toCharArray ( ) ) ) { fragment . setInitializer ( null ) ; fragment . setFlags ( fragment . getFlags ( ) | ASTNode . RECOVERED ) ; } } } } public void endVisit ( NormalAnnotation node ) { endVisitNode ( node ) ; if ( this . blockDepth < 1 ) { List values = node . values ( ) ; int size = values . size ( ) ; if ( size > 0 ) { MemberValuePair lastMemberValuePair = ( MemberValuePair ) values . get ( size - 1 ) ; int annotationEnd = node . getStartPosition ( ) + node . getLength ( ) ; int lastMemberValuePairEnd = lastMemberValuePair . getStartPosition ( ) + lastMemberValuePair . getLength ( ) ; if ( annotationEnd == lastMemberValuePairEnd ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; } } } } public void endVisit ( SingleMemberAnnotation node ) { endVisitNode ( node ) ; if ( this . blockDepth < 1 ) { Expression value = node . getValue ( ) ; int annotationEnd = node . getStartPosition ( ) + node . getLength ( ) ; int valueEnd = value . getStartPosition ( ) + value . getLength ( ) ; if ( annotationEnd == valueEnd ) { node . setFlags ( node . getFlags ( ) | ASTNode . RECOVERED ) ; } } } } </s>