#!/usr/bin/env python
#
# Copyright 2011 The Closure Linter Authors. All Rights Reserved.
#
# 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.

"""Contains logic for sorting goog.provide and goog.require statements.

Closurized JavaScript files use goog.provide and goog.require statements at the
top of the file to manage dependencies. These statements should be sorted
alphabetically, however, it is common for them to be accompanied by inline
comments or suppression annotations. In order to sort these statements without
disrupting their comments and annotations, the association between statements
and comments/annotations must be maintained while sorting.

  RequireProvideSorter: Handles checking/fixing of provide/require statements.
"""



from closure_linter import javascripttokens
from closure_linter import tokenutil

# Shorthand
Type = javascripttokens.JavaScriptTokenType


class RequireProvideSorter(object):
  """Checks for and fixes alphabetization of provide and require statements.

  When alphabetizing, comments on the same line or comments directly above a
  goog.provide or goog.require statement are associated with that statement and
  stay with the statement as it gets sorted.
  """

  def CheckProvides(self, token):
    """Checks alphabetization of goog.provide statements.

    Iterates over tokens in given token stream, identifies goog.provide tokens,
    and checks that they occur in alphabetical order by the object being
    provided.

    Args:
      token: A token in the token stream before any goog.provide tokens.

    Returns:
      The first provide token in the token stream.

      None is returned if all goog.provide statements are already sorted.
    """
    provide_tokens = self._GetRequireOrProvideTokens(token, 'goog.provide')
    provide_strings = self._GetRequireOrProvideTokenStrings(provide_tokens)
    sorted_provide_strings = sorted(provide_strings)
    if provide_strings != sorted_provide_strings:
      return provide_tokens[0]
    return None

  def CheckRequires(self, token):
    """Checks alphabetization of goog.require statements.

    Iterates over tokens in given token stream, identifies goog.require tokens,
    and checks that they occur in alphabetical order by the dependency being
    required.

    Args:
      token: A token in the token stream before any goog.require tokens.

    Returns:
      The first require token in the token stream.

      None is returned if all goog.require statements are already sorted.
    """
    require_tokens = self._GetRequireOrProvideTokens(token, 'goog.require')
    require_strings = self._GetRequireOrProvideTokenStrings(require_tokens)
    sorted_require_strings = sorted(require_strings)
    if require_strings != sorted_require_strings:
      return require_tokens[0]
    return None

  def FixProvides(self, token):
    """Sorts goog.provide statements in the given token stream alphabetically.

    Args:
      token: The first token in the token stream.
    """
    self._FixProvidesOrRequires(
        self._GetRequireOrProvideTokens(token, 'goog.provide'))

  def FixRequires(self, token):
    """Sorts goog.require statements in the given token stream alphabetically.

    Args:
      token: The first token in the token stream.
    """
    self._FixProvidesOrRequires(
        self._GetRequireOrProvideTokens(token, 'goog.require'))

  def _FixProvidesOrRequires(self, tokens):
    """Sorts goog.provide or goog.require statements.

    Args:
      tokens: A list of goog.provide or goog.require tokens in the order they
              appear in the token stream. i.e. the first token in this list must
              be the first goog.provide or goog.require token.
    """
    strings = self._GetRequireOrProvideTokenStrings(tokens)
    sorted_strings = sorted(strings)

    # Make a separate pass to remove any blank lines between goog.require/
    # goog.provide tokens.
    first_token = tokens[0]
    last_token = tokens[-1]
    i = last_token
    while i != first_token and i is not None:
      if i.type is Type.BLANK_LINE:
        tokenutil.DeleteToken(i)
      i = i.previous

    # A map from required/provided object name to tokens that make up the line
    # it was on, including any comments immediately before it or after it on the
    # same line.
    tokens_map = self._GetTokensMap(tokens)

    # Iterate over the map removing all tokens.
    for name in tokens_map:
      tokens_to_delete = tokens_map[name]
      for i in tokens_to_delete:
        tokenutil.DeleteToken(i)

    # Save token to rest of file. Sorted token will be inserted before this.
    rest_of_file = tokens_map[strings[-1]][-1].next

    # Re-add all tokens in the map in alphabetical order.
    insert_after = tokens[0].previous
    for string in sorted_strings:
      for i in tokens_map[string]:
        if rest_of_file:
          tokenutil.InsertTokenBefore(i, rest_of_file)
        else:
          tokenutil.InsertTokenAfter(i, insert_after)
          insert_after = i

  def _GetRequireOrProvideTokens(self, token, token_string):
    """Gets all goog.provide or goog.require tokens in the given token stream.

    Args:
      token: The first token in the token stream.
      token_string: One of 'goog.provide' or 'goog.require' to indicate which
                    tokens to find.

    Returns:
      A list of goog.provide or goog.require tokens in the order they appear in
      the token stream.
    """
    tokens = []
    while token:
      if token.type == Type.IDENTIFIER:
        if token.string == token_string:
          tokens.append(token)
        elif token.string not in [
            'goog.provide', 'goog.require', 'goog.setTestOnly']:
          # These 3 identifiers are at the top of the file. So if any other
          # identifier is encountered, return.
          # TODO(user): Once it's decided what ordering goog.require
          # should use, add 'goog.module' to the list above and implement the
          # decision.
          break
      token = token.next

    return tokens

  def _GetRequireOrProvideTokenStrings(self, tokens):
    """Gets a list of strings corresponding to the given list of tokens.

    The string will be the next string in the token stream after each token in
    tokens. This is used to find the object being provided/required by a given
    goog.provide or goog.require token.

    Args:
      tokens: A list of goog.provide or goog.require tokens.

    Returns:
      A list of object names that are being provided or required by the given
      list of tokens. For example:

      ['object.a', 'object.c', 'object.b']
    """
    token_strings = []
    for token in tokens:
      if not token.is_deleted:
        name = tokenutil.GetStringAfterToken(token)
        token_strings.append(name)
    return token_strings

  def _GetTokensMap(self, tokens):
    """Gets a map from object name to tokens associated with that object.

    Starting from the goog.provide/goog.require token, searches backwards in the
    token stream for any lines that start with a comment. These lines are
    associated with the goog.provide/goog.require token. Also associates any
    tokens on the same line as the goog.provide/goog.require token with that
    token.

    Args:
      tokens: A list of goog.provide or goog.require tokens.

    Returns:
      A dictionary that maps object names to the tokens associated with the
      goog.provide or goog.require of that object name. For example:

      {
        'object.a': [JavaScriptToken, JavaScriptToken, ...],
        'object.b': [...]
      }

      The list of tokens includes any comment lines above the goog.provide or
      goog.require statement and everything after the statement on the same
      line. For example, all of the following would be associated with
      'object.a':

      /** @suppress {extraRequire} */
      goog.require('object.a'); // Some comment.
    """
    tokens_map = {}
    for token in tokens:
      object_name = tokenutil.GetStringAfterToken(token)
      # If the previous line starts with a comment, presume that the comment
      # relates to the goog.require or goog.provide and keep them together when
      # sorting.
      first_token = token
      previous_first_token = tokenutil.GetFirstTokenInPreviousLine(first_token)
      while (previous_first_token and
             previous_first_token.IsAnyType(Type.COMMENT_TYPES)):
        first_token = previous_first_token
        previous_first_token = tokenutil.GetFirstTokenInPreviousLine(
            first_token)

      # Find the last token on the line.
      last_token = tokenutil.GetLastTokenInSameLine(token)

      all_tokens = self._GetTokenList(first_token, last_token)
      tokens_map[object_name] = all_tokens
    return tokens_map

  def _GetTokenList(self, first_token, last_token):
    """Gets a list of all tokens from first_token to last_token, inclusive.

    Args:
      first_token: The first token to get.
      last_token: The last token to get.

    Returns:
      A list of all tokens between first_token and last_token, including both
      first_token and last_token.

    Raises:
      Exception: If the token stream ends before last_token is reached.
    """
    token_list = []
    token = first_token
    while token != last_token:
      if not token:
        raise Exception('ran out of tokens')
      token_list.append(token)
      token = token.next
    token_list.append(last_token)

    return token_list

  def GetFixedRequireString(self, token):
    """Get fixed/sorted order of goog.require statements.

    Args:
      token: The first token in the token stream.

    Returns:
      A string for correct sorted order of goog.require.
    """
    return self._GetFixedRequireOrProvideString(
        self._GetRequireOrProvideTokens(token, 'goog.require'))

  def GetFixedProvideString(self, token):
    """Get fixed/sorted order of goog.provide statements.

    Args:
      token: The first token in the token stream.

    Returns:
      A string for correct sorted order of goog.provide.
    """
    return self._GetFixedRequireOrProvideString(
        self._GetRequireOrProvideTokens(token, 'goog.provide'))

  def _GetFixedRequireOrProvideString(self, tokens):
    """Sorts goog.provide or goog.require statements.

    Args:
      tokens: A list of goog.provide or goog.require tokens in the order they
              appear in the token stream. i.e. the first token in this list must
              be the first goog.provide or goog.require token.

    Returns:
      A string for sorted goog.require or goog.provide statements
    """

    # A map from required/provided object name to tokens that make up the line
    # it was on, including any comments immediately before it or after it on the
    # same line.
    tokens_map = self._GetTokensMap(tokens)
    sorted_strings = sorted(tokens_map.keys())

    new_order = ''
    for string in sorted_strings:
      for i in tokens_map[string]:
        new_order += i.string
        if i.IsLastInLine():
          new_order += '\n'

    return new_order
