// CHECKSTYLE_OFF:Must use GNU license for code based on checkstyle
// /////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2005 Oliver Burn
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// //////////////////////////////////////////////////////////////////////////////
// CHECKSTYLE_ON

// This class is based upon the
// com.puppycrawl.tools.checkstyle.checks.coding.DeclarationOrderCheck

package com.google.gwt.checkstyle;

import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.Scope;
import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

import java.util.Stack;

/**
 * Checks that the parts of a class or interface declaration appear in the order
 * specified by the 'Making GWT better' style guide.
 */

public class OrderCheck extends Check {
  /**
   * Encapsulate the state in each class scope in order to handle inner classes.
   */
  private class ScopeState {
    /**
     * Current state.
     */
    private int state = State.TYPE;

    /**
     * Current access modifier for state.
     */
    private Scope visibility = Scope.PUBLIC;
  }

  /**
   * Ordered category states for code elements.
   */
  private static class State {
    private static final int TYPE = 0;
    private static final int STATIC_FIELDS = 1;
    private static final int STATIC_INITS = 2;
    private static final int STATIC_METHODS = 3;
    private static final int INSTANCE_FIELDS = 4;
    private static final int INSTANCE_INITS = 5;
    private static final int CONSTRUCTORS = 6;
    private static final int INSTANCE_METHODS = 7;
  }

  /**
   * List of Declaration States. This is necessary due to inner classes that
   * have their own state.
   */
  private final Stack classScopes = new Stack();

  /**
   * Previous method name, used for alphabetical ordering.
   */
  private String previousMethodName;

  public int[] getDefaultTokens() {
    return new int[] {
        TokenTypes.CTOR_DEF, TokenTypes.METHOD_DEF, TokenTypes.MODIFIERS,
        TokenTypes.STATIC_INIT, TokenTypes.INSTANCE_INIT, TokenTypes.OBJBLOCK};
  }

  public void leaveToken(DetailAST aAST) {
    switch (aAST.getType()) {
      case TokenTypes.OBJBLOCK:
        classScopes.pop();
        previousMethodName = null;
        break;
      case TokenTypes.METHOD_DEF:
        // If the previous method was in the same class, with the same
        // modifiers, check that it is alphabetically before the current
        // method.
        String methodName = aAST.findFirstToken(TokenTypes.IDENT).getText();
        if (previousMethodName != null
            && (previousMethodName.compareToIgnoreCase(methodName)) > 0) {
          log(aAST, methodName + " is not alphabetical.");
        }
        previousMethodName = methodName;
        break;
      default:
    }
  }

  public void visitToken(DetailAST aAST) {
    try {
      int parentType = 0;
      if (aAST.getParent() != null) {
        parentType = aAST.getParent().getType();
      }
      switch (aAST.getType()) {
        case TokenTypes.OBJBLOCK:
          classScopes.push(new ScopeState());
          previousMethodName = null;
          break;

        case TokenTypes.CTOR_DEF:
          if (parentType != TokenTypes.OBJBLOCK) {
            return;
          }
          checkState(aAST, State.CONSTRUCTORS, "Constructor");
          break;

        case TokenTypes.MODIFIERS:
          if (parentType == TokenTypes.VARIABLE_DEF) {
            checkVariable(aAST);
          }
          if (parentType == TokenTypes.METHOD_DEF) {
            checkMethod(aAST);
          }
          break;
        case TokenTypes.STATIC_INIT: {
          checkState(aAST, State.STATIC_INITS, "Static initializer");
          break;
        }
        case TokenTypes.INSTANCE_INIT: {
          checkState(aAST, State.INSTANCE_INITS, "Instance initializer");
        }
          break;
        default:
      }
    } catch (Throwable t) {
      // CheckStyle swallows errors in general, we want OrderCheck errors to be
      // visible.
      t.printStackTrace();
      throw new RuntimeException("Exception/Error in OrderCheck", t);
    }
  }

  /**
   * Check the modifiers of a method for order conflicts.
   */
  private void checkMethod(DetailAST aAST) {
    if (aAST.getParent().getParent().getType() != TokenTypes.OBJBLOCK) {
      return;
    }
    if (aAST.findFirstToken(TokenTypes.LITERAL_STATIC) != null) {
      if (checkState(aAST, State.STATIC_METHODS, "Static method")) {
        previousMethodName = null;
      }
    } else {
      if (checkState(aAST, State.INSTANCE_METHODS, "Instance method")) {
        previousMethodName = null;
      }
    }
  }

  /**
   * Checks the category and visibility of declarations.
   * 
   * @return whether the state or visibility modifiers have changed
   */
  private boolean checkState(DetailAST aAST, int curState, String type) {
    ScopeState scope = (ScopeState) classScopes.peek();
    if (scope.state > curState) {
      log(aAST, type + " in wrong order.");
      // Wrong type implies at least a temporary state switch.
      return true;
    } else if (scope.state == curState) {
      final Scope curVisibility = ScopeUtils.getScopeFromMods(aAST);
      if (scope.visibility.compareTo(curVisibility) > 0) {
        log(aAST, curVisibility.getName() + " " + type
            + " should not occur after " + scope.visibility.getName() + " "
            + type);
        return false;
      } else if (scope.visibility != curVisibility) {
        scope.visibility = curVisibility;
        return true;
      } else {
        return false;
      }
    } else {
      scope.state = curState;
      scope.visibility = Scope.PUBLIC;
      return true;
    }
  }

  /**
   * Check the modifiers of a variable for order conflicts.
   */
  private void checkVariable(DetailAST aAST) {
    if (aAST.getParent().getParent().getType() != TokenTypes.OBJBLOCK) {
      return;
    }
    if (aAST.findFirstToken(TokenTypes.LITERAL_STATIC) != null) {
      checkState(aAST, State.STATIC_FIELDS, "Static field");
    } else {
      checkState(aAST, State.INSTANCE_FIELDS, "Instance field");
    }
  }
}