// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../messages/codes.dart' as codes;
import '../scanner/token.dart' show Keyword, Token;
import 'formal_parameter_kind.dart';
import 'member_kind.dart' show MemberKind;
import 'parser_impl.dart' show Parser;
import 'util.dart' show optional;

bool isModifier(Token token) {
  if (!token.isModifier) {
    return false;
  } else if (token.type.isBuiltIn) {
    // A built-in keyword can only be a modifier as long as it is
    // followed by another keyword or an identifier. Otherwise, it is the
    // identifier.
    //
    // For example, `external` is a modifier in this declaration:
    //   external Foo foo();
    // but is the identifier in this declaration
    //   external() => true;
    // and in
    //   for (final external in list) { }
    Token next = token.next;
    Keyword keyword = next.keyword;
    if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
      return false;
    }
  }
  return true;
}

/// This class is used to parse modifiers in most locations where modifiers
/// can occur, but does not call handleModifier or handleModifiers.
class ModifierRecoveryContext {
  final Parser parser;
  Token abstractToken;
  Token constToken;
  Token covariantToken;
  Token externalToken;
  Token finalToken;
  Token lateToken;
  Token requiredToken;
  Token staticToken;
  Token varToken;

  // Set `true` when parsing modifiers after the `factory` token.
  bool afterFactory = false;

  // TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
  // with this class.

  ModifierRecoveryContext(this.parser);

  set staticOrCovariant(Token staticOrCovariant) {
    if (staticOrCovariant == null) {
      covariantToken = null;
      staticToken = null;
    } else if (optional('covariant', staticOrCovariant)) {
      covariantToken = staticOrCovariant;
      staticToken = null;
    } else if (optional('static', staticOrCovariant)) {
      covariantToken = null;
      staticToken = staticOrCovariant;
    } else {
      throw "Internal error: "
          "Unexpected staticOrCovariant '$staticOrCovariant'.";
    }
  }

  Token get varFinalOrConst => varToken ?? finalToken ?? constToken;

  set varFinalOrConst(Token varFinalOrConst) {
    if (varFinalOrConst == null) {
      varToken = null;
      finalToken = null;
      constToken = null;
    } else if (optional('var', varFinalOrConst)) {
      varToken = varFinalOrConst;
      finalToken = null;
      constToken = null;
    } else if (optional('final', varFinalOrConst)) {
      varToken = null;
      finalToken = varFinalOrConst;
      constToken = null;
    } else if (optional('const', varFinalOrConst)) {
      varToken = null;
      finalToken = null;
      constToken = varFinalOrConst;
    } else {
      throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
    }
  }

  /// Parse modifiers for class methods and fields.
  Token parseClassMemberModifiers(Token token) {
    token = parseModifiers(token);
    if (abstractToken != null) {
      parser.reportRecoverableError(
          abstractToken, codes.messageAbstractClassMember);
    }
    reportExtraneousModifier(requiredToken);
    return token;
  }

  /// Parse modifiers for formal parameters.
  Token parseFormalParameterModifiers(
      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
    token = parseModifiers(token);

    if (parameterKind != FormalParameterKind.optionalNamed) {
      reportExtraneousModifier(requiredToken);
    }
    if (memberKind == MemberKind.StaticMethod ||
        memberKind == MemberKind.TopLevelMethod) {
      reportExtraneousModifier(this.covariantToken);
    } else if (memberKind == MemberKind.ExtensionNonStaticMethod ||
        memberKind == MemberKind.ExtensionStaticMethod) {
      reportExtraneousModifierInExtension(this.covariantToken);
    }
    if (constToken != null) {
      reportExtraneousModifier(constToken);
    } else if (memberKind == MemberKind.GeneralizedFunctionType) {
      if (varFinalOrConst != null) {
        parser.reportRecoverableError(
            varFinalOrConst, codes.messageFunctionTypedParameterVar);
      }
    }
    reportExtraneousModifier(abstractToken);
    reportExtraneousModifier(externalToken);
    reportExtraneousModifier(lateToken);
    reportExtraneousModifier(staticToken);
    return token;
  }

  /// Parse modifiers after the `factory` token.
  Token parseModifiersAfterFactory(Token token) {
    afterFactory = true;
    token = parseModifiers(token);
    if (abstractToken != null) {
      parser.reportRecoverableError(
          abstractToken, codes.messageAbstractClassMember);
    }
    reportExtraneousModifier(lateToken);
    reportExtraneousModifier(requiredToken);
    return token;
  }

  /// Parse modifiers for top level functions and fields.
  Token parseTopLevelModifiers(Token token) {
    token = parseModifiers(token);
    reportExtraneousModifier(abstractToken);
    reportExtraneousModifier(covariantToken);
    reportExtraneousModifier(requiredToken);
    reportExtraneousModifier(staticToken);
    return token;
  }

  /// Parse modifiers for variable declarations.
  Token parseVariableDeclarationModifiers(Token token) {
    token = parseModifiers(token);
    reportExtraneousModifier(abstractToken);
    reportExtraneousModifier(covariantToken);
    reportExtraneousModifier(externalToken);
    reportExtraneousModifier(requiredToken);
    reportExtraneousModifier(staticToken);
    return token;
  }

  /// Parse modifiers during recovery when modifiers are out of order
  /// or invalid. Typically clients call methods like
  /// [parseClassMemberModifiers] which in turn calls this method,
  /// rather than calling this method directly.
  ///
  /// The various modifier token parameters represent tokens of modifiers
  /// that have already been parsed prior to recovery. The [staticOrCovariant]
  /// parameter is for convenience if caller has a token that may be either
  /// `static` or `covariant`. The first non-null parameter of
  /// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
  /// in that order, and the others ignored.
  Token parseModifiers(Token token) {
    // Process invalid and out-of-order modifiers
    Token next = token.next;
    while (true) {
      final String value = next.stringValue;
      if (isModifier(next)) {
        if (identical('abstract', value)) {
          token = parseAbstract(token);
        } else if (identical('const', value)) {
          token = parseConst(token);
        } else if (identical('covariant', value)) {
          token = parseCovariant(token);
        } else if (identical('external', value)) {
          token = parseExternal(token);
        } else if (identical('final', value)) {
          token = parseFinal(token);
        } else if (identical('late', value)) {
          token = parseLate(token);
        } else if (identical('required', value)) {
          token = parseRequired(token);
        } else if (identical('static', value)) {
          token = parseStatic(token);
        } else if (identical('var', value)) {
          token = parseVar(token);
        } else {
          throw 'Internal Error: Unhandled modifier: $value';
        }
      } else if (afterFactory && identical('factory', value)) {
        parser.reportRecoverableErrorWithToken(
            next, codes.templateDuplicatedModifier);
        token = next;
      } else {
        break;
      }
      next = token.next;
    }
    return token;
  }

  Token parseAbstract(Token token) {
    Token next = token.next;
    assert(optional('abstract', next));
    if (abstractToken == null) {
      abstractToken = next;
      return next;
    }

    // Recovery
    parser.reportRecoverableErrorWithToken(
        next, codes.templateDuplicatedModifier);
    return next;
  }

  Token parseConst(Token token) {
    Token next = token.next;
    assert(optional('const', next));
    if (varFinalOrConst == null && covariantToken == null) {
      constToken = next;

      if (afterFactory) {
        reportModifierOutOfOrder(next, 'factory');
      } else if (lateToken != null) {
        reportConflictingModifiers(next, lateToken);
      }
      return next;
    }

    // Recovery
    if (constToken != null) {
      parser.reportRecoverableErrorWithToken(
          next, codes.templateDuplicatedModifier);
    } else if (covariantToken != null) {
      reportConflictingModifiers(next, covariantToken);
    } else if (finalToken != null) {
      parser.reportRecoverableError(next, codes.messageConstAndFinal);
    } else if (varToken != null) {
      reportConflictingModifiers(next, varToken);
    } else {
      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
    }
    return next;
  }

  Token parseCovariant(Token token) {
    Token next = token.next;
    assert(optional('covariant', next));
    if (constToken == null &&
        covariantToken == null &&
        staticToken == null &&
        !afterFactory) {
      covariantToken = next;

      if (varToken != null) {
        reportModifierOutOfOrder(next, varToken.lexeme);
      } else if (finalToken != null) {
        reportModifierOutOfOrder(next, finalToken.lexeme);
      } else if (lateToken != null) {
        reportModifierOutOfOrder(next, lateToken.lexeme);
      }
      return next;
    }

    // Recovery
    if (covariantToken != null) {
      parser.reportRecoverableErrorWithToken(
          next, codes.templateDuplicatedModifier);
    } else if (afterFactory) {
      reportExtraneousModifier(next);
    } else if (constToken != null) {
      reportConflictingModifiers(next, constToken);
    } else if (staticToken != null) {
      parser.reportRecoverableError(next, codes.messageCovariantAndStatic);
    } else {
      throw 'Internal Error: Unhandled recovery: $next';
    }
    return next;
  }

  Token parseExternal(Token token) {
    Token next = token.next;
    assert(optional('external', next));
    if (externalToken == null) {
      externalToken = next;

      if (afterFactory) {
        reportModifierOutOfOrder(next, 'factory');
      } else if (constToken != null) {
        reportModifierOutOfOrder(next, constToken.lexeme);
      } else if (staticToken != null) {
        reportModifierOutOfOrder(next, staticToken.lexeme);
      } else if (lateToken != null) {
        reportModifierOutOfOrder(next, lateToken.lexeme);
      }
      return next;
    }

    // Recovery
    parser.reportRecoverableErrorWithToken(
        next, codes.templateDuplicatedModifier);
    return next;
  }

  Token parseFinal(Token token) {
    Token next = token.next;
    assert(optional('final', next));
    if (varFinalOrConst == null && !afterFactory) {
      finalToken = next;
      return next;
    }

    // Recovery
    if (finalToken != null) {
      parser.reportRecoverableErrorWithToken(
          next, codes.templateDuplicatedModifier);
    } else if (afterFactory) {
      reportExtraneousModifier(next);
    } else if (constToken != null) {
      parser.reportRecoverableError(next, codes.messageConstAndFinal);
    } else if (varToken != null) {
      parser.reportRecoverableError(next, codes.messageFinalAndVar);
    } else if (lateToken != null) {
      reportModifierOutOfOrder(next, lateToken.lexeme);
    } else {
      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
    }
    return next;
  }

  Token parseLate(Token token) {
    Token next = token.next;
    assert(optional('late', next));
    if (lateToken == null) {
      lateToken = next;

      if (constToken != null) {
        reportConflictingModifiers(next, constToken);
      } else if (varToken != null) {
        reportModifierOutOfOrder(next, varToken.lexeme);
      } else if (finalToken != null) {
        reportModifierOutOfOrder(next, finalToken.lexeme);
      }
      return next;
    }

    // Recovery
    parser.reportRecoverableErrorWithToken(
        next, codes.templateDuplicatedModifier);
    return next;
  }

  Token parseRequired(Token token) {
    Token next = token.next;
    assert(optional('required', next));
    if (requiredToken == null) {
      requiredToken = next;

      if (constToken != null) {
        reportModifierOutOfOrder(requiredToken, constToken.lexeme);
      } else if (covariantToken != null) {
        reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
      } else if (finalToken != null) {
        reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
      } else if (varToken != null) {
        reportModifierOutOfOrder(requiredToken, varToken.lexeme);
      }
      return next;
    }

    // Recovery
    parser.reportRecoverableErrorWithToken(
        next, codes.templateDuplicatedModifier);
    return next;
  }

  Token parseStatic(Token token) {
    Token next = token.next;
    assert(optional('static', next));
    if (covariantToken == null && staticToken == null && !afterFactory) {
      staticToken = next;

      if (constToken != null) {
        reportModifierOutOfOrder(next, constToken.lexeme);
      } else if (finalToken != null) {
        reportModifierOutOfOrder(next, finalToken.lexeme);
      } else if (varToken != null) {
        reportModifierOutOfOrder(next, varToken.lexeme);
      } else if (lateToken != null) {
        reportModifierOutOfOrder(next, lateToken.lexeme);
      }
      return next;
    }

    // Recovery
    if (covariantToken != null) {
      parser.reportRecoverableError(next, codes.messageCovariantAndStatic);
    } else if (staticToken != null) {
      parser.reportRecoverableErrorWithToken(
          next, codes.templateDuplicatedModifier);
    } else if (afterFactory) {
      reportExtraneousModifier(next);
    } else {
      throw 'Internal Error: Unhandled recovery: $next';
    }
    return next;
  }

  Token parseVar(Token token) {
    Token next = token.next;
    assert(optional('var', next));
    if (varFinalOrConst == null && !afterFactory) {
      varToken = next;
      return next;
    }

    // Recovery
    if (varToken != null) {
      parser.reportRecoverableErrorWithToken(
          next, codes.templateDuplicatedModifier);
    } else if (afterFactory) {
      reportExtraneousModifier(next);
    } else if (constToken != null) {
      reportConflictingModifiers(next, constToken);
    } else if (finalToken != null) {
      parser.reportRecoverableError(next, codes.messageFinalAndVar);
    } else {
      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
    }
    return next;
  }

  void reportConflictingModifiers(Token modifier, Token earlierModifier) {
    parser.reportRecoverableError(
        modifier,
        codes.templateConflictingModifiers
            .withArguments(modifier.lexeme, earlierModifier.lexeme));
  }

  void reportExtraneousModifier(Token modifier) {
    if (modifier != null) {
      parser.reportRecoverableErrorWithToken(
          modifier, codes.templateExtraneousModifier);
    }
  }

  void reportExtraneousModifierInExtension(Token modifier) {
    if (modifier != null) {
      parser.reportRecoverableErrorWithToken(
          modifier, codes.templateExtraneousModifierInExtension);
    }
  }

  void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
    parser.reportRecoverableError(
        modifier,
        codes.templateModifierOutOfOrder
            .withArguments(modifier.lexeme, beforeModifier));
  }
}
