text: /**
   * @fileoverview Rule to require sorting of import declarations
   * @author Christian Schuller
   * @copyright 2015 Christian Schuller. All rights reserved.
   * See LICENSE file in root directory for full license.
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = function(context) {
  
      var configuration = context.options[0] || {},
          ignoreCase = configuration.ignoreCase || false,
          ignoreMemberSort = configuration.ignoreMemberSort || false,
          memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"],
          previousDeclaration = null;
  
      /**
       * Gets the used member syntax style.
       *
       * import "my-module.js" --> none
       * import * as myModule from "my-module.js" --> all
       * import {myMember} from "my-module.js" --> single
       * import {foo, bar} from  "my-module.js" --> multiple
       *
       * @param {ASTNode} node - the ImportDeclaration node.
       * @returns {string} used member parameter style, ["all", "multiple", "single"]
       */
      function usedMemberSyntax(node) {
          if (node.specifiers.length === 0) {
              return "none";
          } else if (node.specifiers[0].type === "ImportNamespaceSpecifier") {
              return "all";
          } else if (node.specifiers.length === 1) {
              return "single";
          } else {
              return "multiple";
          }
      }
  
      /**
       * Gets the group by member parameter index for given declaration.
       * @param {ASTNode} node - the ImportDeclaration node.
       * @returns {number} the declaration group by member index.
       */
      function getMemberParameterGroupIndex(node) {
          return memberSyntaxSortOrder.indexOf(usedMemberSyntax(node));
      }
  
      /**
       * Gets the local name of the first imported module.
       * @param {ASTNode} node - the ImportDeclaration node.
       * @returns {?string} the local name of the first imported module.
       */
      function getFirstLocalMemberName(node) {
          if (node.specifiers[0]) {
              return node.specifiers[0].local.name;
          } else {
              return null;
          }
      }
  
      return {
          "ImportDeclaration": function(node) {
              if (previousDeclaration) {
                  var currentLocalMemberName = getFirstLocalMemberName(node),
                      currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node),
                      previousLocalMemberName = getFirstLocalMemberName(previousDeclaration),
                      previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration);
  
                  if (ignoreCase) {
                      previousLocalMemberName = previousLocalMemberName && previousLocalMemberName.toLowerCase();
                      currentLocalMemberName = currentLocalMemberName && currentLocalMemberName.toLowerCase();
                  }
  
                  // When the current declaration uses a different member syntax,
                  // then check if the ordering is correct.
                  // Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name.
                  if (currentMemberSyntaxGroupIndex !== previousMemberSyntaxGroupIndex) {
                      if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) {
                          context.report({
                              node: node,
                              message: "Expected '{{syntaxA}}' syntax before '{{syntaxB}}' syntax.",
                              data: {
                                  syntaxA: memberSyntaxSortOrder[currentMemberSyntaxGroupIndex],
                                  syntaxB: memberSyntaxSortOrder[previousMemberSyntaxGroupIndex]
                              }
                          });
                      }
                  } else {
                      if (previousLocalMemberName &&
                          currentLocalMemberName &&
                          currentLocalMemberName < previousLocalMemberName
                      ) {
                          context.report({
                              node: node,
                              message: "Imports should be sorted alphabetically."
                          });
                      }
                  }
              }
  
              // Multiple members of an import declaration should also be sorted alphabetically.
              if (!ignoreMemberSort && node.specifiers.length > 1) {
                  var previousSpecifier = null;
                  var previousSpecifierName = null;
  
                  for (var i = 0; i < node.specifiers.length; ++i) {
                      var currentSpecifier = node.specifiers[i];
                      if (currentSpecifier.type !== "ImportSpecifier") {
                          continue;
                      }
  
                      var currentSpecifierName = currentSpecifier.local.name;
                      if (ignoreCase) {
                          currentSpecifierName = currentSpecifierName.toLowerCase();
                      }
  
                      if (previousSpecifier && currentSpecifierName < previousSpecifierName) {
                          context.report({
                              node: currentSpecifier,
                              message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.",
                              data: {
                                  memberName: currentSpecifier.local.name
                              }
                          });
                      }
  
                      previousSpecifier = currentSpecifier;
                      previousSpecifierName = currentSpecifierName;
                  }
              }
  
              previousDeclaration = node;
          }
      };
  };
  
  module.exports.schema = [
      {
          "type": "object",
          "properties": {
              "ignoreCase": {
                  "type": "boolean"
              },
              "memberSyntaxSortOrder": {
                  "type": "array",
                  "items": {
                      "enum": ["none", "all", "multiple", "single"]
                  },
                  "uniqueItems": true,
                  "minItems": 4,
                  "maxItems": 4
              },
              "ignoreMemberSort": {
                  "type": "boolean"
              }
          },
          "additionalProperties": false
      }
  ];
  