예제 #1
0
  protected CompilationUnitDeclaration endParse(int act) {
    if (this.hasRecoveredOnExpression) {
      CompilationResult unitResult = this.compilationUnit.compilationResult;
      if (act != ERROR_ACTION) { // expression recovery worked
        // flush previously recorded problems
        for (int i = 0; i < unitResult.problemCount; i++) {
          unitResult.problems[i] = null; // discard problem
        }
        unitResult.problemCount = 0;
        if (this.referenceContext instanceof AbstractMethodDeclaration) {
          ((AbstractMethodDeclaration) this.referenceContext).ignoreFurtherInvestigation = false;
        }
        if (this.referenceContext instanceof CompilationUnitDeclaration) {
          ((CompilationUnitDeclaration) this.referenceContext).ignoreFurtherInvestigation = false;
        }

        // consume expresion as a return statement
        consumeStatementReturn();
        int fieldsCount =
            (this.evaluationContext.localVariableNames == null
                    ? 0
                    : this.evaluationContext.localVariableNames.length)
                + (this.evaluationContext.declaringTypeName == null ? 0 : 1);
        if (this.astPtr > (this.diet ? 0 : 2 + fieldsCount)) {
          // in diet mode, the ast stack was empty when we went for method body
          // otherwise it contained the type, the generated fields for local variables,
          // the generated field for 'this' and the method
          consumeBlockStatements();
        }
        consumeMethodBody();
        if (!this.diet) {
          consumeMethodDeclaration(true);
          if (fieldsCount > 0) {
            consumeClassBodyDeclarations();
          }
          consumeClassBodyDeclarationsopt();
          consumeClassDeclaration();
          consumeInternalCompilationUnitWithTypes();
          consumeCompilationUnit();
        }
        this.lastAct = ACCEPT_ACTION;
      } else {
        // might have more than one error recorded:
        // 1. during regular parse
        // 2. during expression recovery
        // -> must filter out one of them, the earliest one is less accurate
        int maxRegularPos = 0, problemCount = unitResult.problemCount;
        for (int i = 0; i < this.problemCountBeforeRecovery; i++) {
          // skip unmatched bracket problems
          if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;

          int start = unitResult.problems[i].getSourceStart();
          if (start > maxRegularPos && start <= this.codeSnippetEnd) {
            maxRegularPos = start;
          }
        }
        int maxRecoveryPos = 0;
        for (int i = this.problemCountBeforeRecovery; i < problemCount; i++) {
          // skip unmatched bracket problems
          if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;

          int start = unitResult.problems[i].getSourceStart();
          if (start > maxRecoveryPos && start <= this.codeSnippetEnd) {
            maxRecoveryPos = start;
          }
        }
        if (maxRecoveryPos > maxRegularPos) {
          System.arraycopy(
              unitResult.problems,
              this.problemCountBeforeRecovery,
              unitResult.problems,
              0,
              problemCount - this.problemCountBeforeRecovery);
          unitResult.problemCount -= this.problemCountBeforeRecovery;
        } else {
          unitResult.problemCount -= (problemCount - this.problemCountBeforeRecovery);
        }
        for (int i = unitResult.problemCount; i < problemCount; i++) {
          unitResult.problems[i] = null; // discard problem
        }
      }
    }
    return super.endParse(act);
  }
  /**
   * Bytecode generation for a method
   *
   * @param classScope
   * @param classFile
   */
  public void generateCode(ClassScope classScope, ClassFile classFile) {

    classFile.codeStream.wideMode = false; // reset wideMode to false
    if (this.ignoreFurtherInvestigation) {
      // method is known to have errors, dump a problem method
      if (this.binding == null) return; // handle methods with invalid signature or duplicates
      int problemsLength;
      CategorizedProblem[] problems =
          this.scope.referenceCompilationUnit().compilationResult.getProblems();
      CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
      System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
      classFile.addProblemMethod(this, this.binding, problemsCopy);
      return;
    }
    int problemResetPC = 0;
    CompilationResult unitResult = null;
    int problemCount = 0;
    if (classScope != null) {
      TypeDeclaration referenceContext = classScope.referenceContext;
      if (referenceContext != null) {
        unitResult = referenceContext.compilationResult();
        problemCount = unitResult.problemCount;
      }
    }
    boolean restart = false;
    boolean abort = false;
    // regular code generation
    do {
      try {
        problemResetPC = classFile.contentsOffset;
        this.generateCode(classFile);
        restart = false;
      } catch (AbortMethod e) {
        // a fatal error was detected during code generation, need to restart code gen if possible
        if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
          // a branch target required a goto_w, restart code gen in wide mode.
          classFile.contentsOffset = problemResetPC;
          classFile.methodCount--;
          classFile.codeStream.resetInWideMode(); // request wide mode
          // reset the problem count to prevent reporting the same warning twice
          if (unitResult != null) {
            unitResult.problemCount = problemCount;
          }
          restart = true;
        } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
          classFile.contentsOffset = problemResetPC;
          classFile.methodCount--;
          classFile.codeStream.resetForCodeGenUnusedLocals();
          // reset the problem count to prevent reporting the same warning twice
          if (unitResult != null) {
            unitResult.problemCount = problemCount;
          }
          restart = true;
        } else {
          restart = false;
          abort = true;
        }
      }
    } while (restart);
    // produce a problem method accounting for this fatal error
    if (abort) {
      int problemsLength;
      CategorizedProblem[] problems =
          this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
      CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
      System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
      classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
    }
  }