Package com.google.gwt.dev.javac

Source Code of com.google.gwt.dev.javac.CompilationUnitInvalidator$InvalidatorState

/*
* Copyright 2008 Google Inc.
*
* 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 com.google.gwt.dev.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.javac.CompilationUnit.State;
import com.google.gwt.dev.util.Util;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
* Helper class to invalidate units in a set based on errors or references to
* other invalidate units.
*
* TODO: ClassFileReader#hasStructuralChanges(byte[]) could help us optimize
* this process!
*/
public class CompilationUnitInvalidator {

  /**
   * Maintain cross-validation state.
   */
  public static class InvalidatorState {
    private final JSORestrictionsChecker.CheckerState jsoState = new JSORestrictionsChecker.CheckerState();

    public void retainAll(Collection<CompilationUnit> toRetain) {
      jsoState.retainAll(toRetain);
    }
  }

  /**
   * For all units containing one or more errors whose state is currently
   * {@link State#COMPILED}, each unit's error(s) will be logged to
   * <code>logger</code> and each unit's state will be set to
   * {@link State#ERROR}.
   *
   * @return <code>true</code> if any units changed state
   */
  public static boolean invalidateUnitsWithErrors(TreeLogger logger,
      Collection<CompilationUnit> units) {
    logger = logger.branch(TreeLogger.TRACE, "Removing units with errors");
    // Start by removing units with a known problem.
    boolean anyRemoved = false;
    for (CompilationUnit unit : units) {
      if (unit.getState() != State.COMPILED) {
        continue;
      }
      CompilationResult result = unit.getJdtCud().compilationResult();
      if (result.hasProblems()) {

        // Log the errors and GWT warnings.
        TreeLogger branch = null;
        for (CategorizedProblem problem : result.getProblems()) {
          TreeLogger.Type logLevel;
          if (problem.isError()) {
            // Log errors.
            logLevel = TreeLogger.ERROR;
            // Only log GWT-specific warnings.
          } else if (problem.isWarning() && problem instanceof GWTProblem) {
            logLevel = TreeLogger.WARN;
          } else {
            // Ignore all other problems.
            continue;
          }
          // Append 'Line #: msg' to the error message.
          StringBuffer msgBuf = new StringBuffer();
          int line = problem.getSourceLineNumber();
          if (line > 0) {
            msgBuf.append("Line ");
            msgBuf.append(line);
            msgBuf.append(": ");
          }
          msgBuf.append(problem.getMessage());

          HelpInfo helpInfo = null;
          if (problem instanceof GWTProblem) {
            GWTProblem gwtProblem = (GWTProblem) problem;
            helpInfo = gwtProblem.getHelpInfo();
          }
          if (branch == null) {
            Type branchType = result.hasErrors() ? TreeLogger.ERROR
                : TreeLogger.WARN;
            String branchString = result.hasErrors() ? "Errors" : "Warnings";
            branch = logger.branch(branchType, branchString + " in '"
                + unit.getDisplayLocation() + "'", null);
          }
          branch.log(logLevel, msgBuf.toString(), null, helpInfo);
        }

        if (branch != null) {
          Util.maybeDumpSource(branch, unit.getDisplayLocation(),
              unit.getSource(), unit.getTypeName());
        }

        // Invalidate the unit if there are errors.
        if (result.hasErrors()) {
          unit.setError();
          anyRemoved = true;
        }
      }
    }

    return anyRemoved;
  }

  /**
   * Invalidate any units that contain either a) references to non-compiled
   * units or b) references to unknown units.
   *
   * @param logger
   * @param unitsToCheck to units that might be invalid, this should be a closed
   *          set that reference each other
   */
  public static void invalidateUnitsWithInvalidRefs(TreeLogger logger,
      Collection<CompilationUnit> unitsToCheck) {
    invalidateUnitsWithInvalidRefs(logger, unitsToCheck,
        Collections.<CompilationUnit> emptySet());
  }

  /**
   * Invalidate any units that contain either a) references to non-compiled
   * units or b) references to unknown units.
   *
   * @param logger
   * @param unitsToCheck to units that might be invalid, these will be the only
   *          units we will invalidate
   * @param knownUnits a set of reference units (may contain invalid units) (set
   *          may be empty)
   */
  public static void invalidateUnitsWithInvalidRefs(TreeLogger logger,
      Collection<CompilationUnit> unitsToCheck,
      Collection<CompilationUnit> knownUnits) {
    logger = logger.branch(TreeLogger.TRACE, "Removing invalidated units");

    Set<String> knownValidRefs = new HashSet<String>();
    for (CompilationUnit unit : knownUnits) {
      if (unit.isCompiled()) {
        knownValidRefs.add(unit.getDisplayLocation());
      }
    }

    // Assume all compiled units are valid at first.
    Set<CompilationUnit> currentlyValidUnitsToCheck = new HashSet<CompilationUnit>();
    for (CompilationUnit unit : unitsToCheck) {
      if (unit.isCompiled()) {
        currentlyValidUnitsToCheck.add(unit);
        knownValidRefs.add(unit.getDisplayLocation());
      }
    }

    boolean changed;
    do {
      changed = false;
      for (Iterator<CompilationUnit> it = currentlyValidUnitsToCheck.iterator(); it.hasNext();) {
        CompilationUnit currentlyValidUnitToCheck = it.next();
        TreeLogger branch = null;
        for (String ref : currentlyValidUnitToCheck.getFileNameRefs()) {
          if (!knownValidRefs.contains(ref)) {
            if (branch == null) {
              branch = logger.branch(TreeLogger.DEBUG, "Compilation unit '"
                  + currentlyValidUnitToCheck
                  + "' is removed due to invalid reference(s):");
              it.remove();
              knownValidRefs.remove(currentlyValidUnitToCheck.getDisplayLocation());
              currentlyValidUnitToCheck.setFresh();
              changed = true;
            }
            branch.log(TreeLogger.DEBUG, ref);
          }
        }
      }
    } while (changed);
  }

  public static void validateCompilationUnits(InvalidatorState state,
      Collection<CompilationUnit> units) {
    for (CompilationUnit unit : units) {
      if (unit.getState() == State.COMPILED) {
        CompilationUnitDeclaration jdtCud = unit.getJdtCud();
        JSORestrictionsChecker.check(state.jsoState, jdtCud);
        JsniChecker.check(jdtCud);
        ArtificialRescueChecker.check(jdtCud, unit.isGenerated());
        BinaryTypeReferenceRestrictionsChecker.check(jdtCud);
      }
    }
    state.jsoState.finalCheck();
  }
}
TOP

Related Classes of com.google.gwt.dev.javac.CompilationUnitInvalidator$InvalidatorState

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.