Package org.aspectj.org.eclipse.jdt.core.dom

Source Code of org.aspectj.org.eclipse.jdt.core.dom.ASTRecoveryPropagator

/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

package org.aspectj.org.eclipse.jdt.core.dom;

import java.util.List;
import java.util.Vector;

import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToIntArray;

/**
* Internal AST visitor for propagating syntax errors.
*/
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) {
    // visit Javadoc.tags() as well
    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;
     
      // continue to visit the node only if it contains tokens modifications
     
      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;
   
    // is inside diet part of the ast
    if(this.blockDepth < 1) {
      if(this.markIncludedProblems(start, end)) {
        node.setFlags(node.getFlags() | ASTNode.RECOVERED);
      }
    } else {     
      this.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();
          // unparent the expression to add it in the expression stateemnt
          expression2.setParent(null, null);
          expression2.setFlags(expression2.getFlags() | ASTNode.RECOVERED);
          node.setExpression(expression2);
        }
      }
    }
  }
 
  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(node.getFlags() | ASTNode.RECOVERED);
        }     
      }
    }
  }
}
TOP

Related Classes of org.aspectj.org.eclipse.jdt.core.dom.ASTRecoveryPropagator

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.