//===--- ParseGeneric.cpp - Swift Language Parser for Generics ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Generic Parsing
//
//===----------------------------------------------------------------------===//

#include "swift/Parse/Parser.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Parse/ParsedSyntaxBuilders.h"
#include "swift/Parse/ParsedSyntaxRecorder.h"
#include "swift/Parse/SyntaxParsingContext.h"

using namespace swift;
using namespace swift::syntax;

/// Parse a list of generic parameters.
///
///   generic-parameter-clause-list:
///     generic-parameter-clause generic-parameter-clause*
ParserStatus Parser::parseSILGenericParamsSyntax(
    Optional<ParsedGenericParameterClauseListSyntax> &result) {
  assert(isInSILMode());
  ParserStatus status;
  if (!startsWithLess(Tok))
    return status;

  SmallVector<ParsedGenericParameterClauseSyntax, 1> clauses;
  do {
    auto result = parseGenericParameterClauseSyntax();
    status |= result.getStatus();
    if (!result.isNull())
      clauses.push_back(result.get());
  } while (startsWithLess(Tok));

  result = ParsedSyntaxRecorder::makeGenericParameterClauseList(clauses,
                                                                *SyntaxContext);
  return status;
}

/// Parse a sequence of generic parameters, e.g. '<T: Comparable, U: Container>'
/// along with an optional requires clause.
///
///   generic-parameter-clause:
///     '<' generic-paramter (',' generic-parameter)* where-clause? '>'
///
///   generic-parameter:
///     identifier
///     identifier ':' type
ParsedSyntaxResult<ParsedGenericParameterClauseSyntax>
Parser::parseGenericParameterClauseSyntax() {
  assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
  ParsedGenericParameterClauseSyntaxBuilder builder(*SyntaxContext);
  ParserStatus status;

  // Parse '<'.
  SourceLoc LAngleLoc = Tok.getLoc();
  builder.useLeftAngleBracket(consumeStartingLessSyntax());

  // Parse parameters.
  bool hasNext = true;
  do {
    ParsedGenericParameterSyntaxBuilder paramBuilder(*SyntaxContext);

    // Parse attributes.
    // TODO: Implement syntax attribute parsing.
    Optional<ParsedAttributeListSyntax> attrs;
    if (Tok.is(tok::at_sign)) {
      SyntaxParsingContext TmpCtxt(SyntaxContext);
      TmpCtxt.setTransparent();

      auto AttrsLoc = Tok.getLoc();
      DeclAttributes attrsAST;
      parseDeclAttributeList(attrsAST);
      if (!attrsAST.isEmpty())
        Generator.addDeclAttributes(attrsAST, AttrsLoc);
      attrs = SyntaxContext->popIf<ParsedAttributeListSyntax>();
    }

    // Parse the name of the parameter.
    auto ident = Context.getIdentifier(Tok.getText());
    auto name = parseIdentifierSyntax(diag::expected_generics_parameter_name);
    if (!name) {
      if (attrs) {
        paramBuilder.useAttributes(std::move(*attrs));
        builder.addGenericParameterListMember(paramBuilder.build());
      }
      status.setIsParseError();
      break;
    }

    if (attrs)
      paramBuilder.useAttributes(std::move(*attrs));
    paramBuilder.useName(std::move(*name));

    // Parse the ':' followed by a type.
    if (Tok.is(tok::colon)) {
      paramBuilder.useColon(consumeTokenSyntax(tok::colon));
      if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol,
                    tok::kw_Any)) {
        auto tyResult = parseTypeSyntax();
        status |= tyResult.getStatus();
        if (auto ty = tyResult.getOrNull())
          paramBuilder.useInheritedType(std::move(*ty));
      } else {
        if (Tok.is(tok::kw_class)) {
          diagnose(Tok, diag::unexpected_class_constraint);
          diagnose(Tok, diag::suggest_anyobject)
              .fixItReplace(Tok.getLoc(), "AnyObject");
          auto ty = ParsedSyntaxRecorder::makeClassRestrictionType(
              consumeTokenSyntax(tok::kw_class), *SyntaxContext);
          paramBuilder.useInheritedType(std::move(ty));
        } else {
          diagnose(Tok, diag::expected_generics_type_restriction, ident);

          paramBuilder.useInheritedType(
              ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));
        }
        status.setIsParseError();
      }
    }

    // Parse ','
    hasNext = Tok.is(tok::comma);
    if (hasNext)
      paramBuilder.useTrailingComma(consumeTokenSyntax(tok::comma));

    builder.addGenericParameterListMember(paramBuilder.build());
  } while (hasNext);

  // Parse optional where clause.
  SourceLoc whereLoc;
  if (Tok.is(tok::kw_where)) {
    SmallVector<RequirementRepr, 2> requirementAST;
    bool FirstTypeInComplete = false;
    auto where = parseGenericWhereClauseSyntax(FirstTypeInComplete);
    builder.useObsoletedWhereClause(where.get());
  }

  // Parse the closing '>'.
  if (startsWithGreater(Tok)) {
    builder.useRightAngleBracket(consumeStartingGreaterSyntax());
  } else {
    if (!status.isError()) {
      diagnose(Tok, diag::expected_rangle_generics_param);
      diagnose(LAngleLoc, diag::opening_angle);
    }

    // Skip until we hit the '>'.
    if (ignoreUntilGreaterInTypeList())
      builder.useRightAngleBracket(consumeStartingGreaterSyntax());
    status.setIsParseError();
  }

  return makeParsedResult(builder.build(), status);
}

ParserResult<GenericParamList> Parser::parseGenericParameters() {
  auto loc = leadingTriviaLoc();
  auto syntaxResult = parseGenericParameterClauseSyntax();
  if (syntaxResult.isNull())
    return syntaxResult.getStatus();
  SyntaxContext->addSyntax(syntaxResult.get());

  auto clause = SyntaxContext->topNode<GenericParameterClauseSyntax>();
  if (clause.getGenericParameterList().empty())
    return nullptr;
  return makeParserResult(syntaxResult.getStatus(),
                          Generator.generate(clause, loc));
}

ParserResult<GenericParamList> Parser::maybeParseGenericParams() {
  if (!startsWithLess(Tok))
    return nullptr;
  return parseGenericParameters();
}

ParserResult<GenericParamList> Parser::parseSILGenericParams() {
  assert(isInSILMode());
  auto loc = leadingTriviaLoc();
  Optional<ParsedGenericParameterClauseListSyntax> result;
  auto status = parseSILGenericParamsSyntax(result);
  if (!result.hasValue()) {
    status.setIsParseError();
    return status;
  }

  SyntaxContext->addSyntax(std::move(*result));
  auto list = SyntaxContext->topNode<GenericParameterClauseListSyntax>();
  auto ret = Generator.generate(list, loc);
  if (!ret)
    return nullptr;
  return makeParserResult(status, ret);
}

void Parser::diagnoseWhereClauseInGenericParamList(
    const GenericParamList *GenericParams, SourceLoc whereLoc) {
  if (GenericParams == nullptr || GenericParams->getWhereLoc().isInvalid())
    return;



  auto WhereRangeInsideBrackets = GenericParams->getWhereClauseSourceRange();

  // Move everything immediately following the last generic parameter
  // as written all the way to the right angle bracket (">")
  auto LastGenericParam = GenericParams->getParams().back();
  auto EndOfLastGenericParam =
      Lexer::getLocForEndOfToken(SourceMgr, LastGenericParam->getEndLoc());

  CharSourceRange RemoveWhereRange { SourceMgr,
    EndOfLastGenericParam,
    GenericParams->getRAngleLoc()
  };

  auto WhereCharRange =
    Lexer::getCharSourceRangeFromSourceRange(SourceMgr,
                                  GenericParams->getWhereClauseSourceRange());

  SmallString<64> Buffer;
  llvm::raw_svector_ostream WhereClauseText(Buffer);
  WhereClauseText << SourceMgr.extractText(whereLoc.isValid()
                                           ? WhereCharRange
                                           : RemoveWhereRange);

  // If, for some reason, there was a where clause in both locations, we're
  // adding to the list of requirements, so tack on a comma here before
  // inserting it at the head of the later where clause.
  if (Tok.is(tok::kw_where))
    WhereClauseText << ',';

  auto Diag = diagnose(WhereRangeInsideBrackets.Start,
                       diag::where_inside_brackets);

  Diag.fixItRemoveChars(RemoveWhereRange.getStart(),
                        RemoveWhereRange.getEnd());

  if (whereLoc.isValid()) {
    Diag.fixItReplace(whereLoc, WhereClauseText.str());
  } else {
    Diag.fixItInsert(Lexer::getLocForEndOfToken(SourceMgr, PreviousLoc),
                     WhereClauseText.str());
  }
}

void Parser::diagnoseWhereClauseInGenericParamList(
    const GenericParamList *GenericParams) {
  SourceLoc whereLoc;
  if (Tok.is(tok::kw_where))
    whereLoc = Tok.getLoc();
  diagnoseWhereClauseInGenericParamList(GenericParams, whereLoc);
}

/// Parse a 'where' clause, which places additional constraints on generic
/// parameters or types based on them.
///
///   where-clause:
///     'where' generic-requirement (',' generic-requirement) *
///
///   generic-requirement:
///     conformance-requirement
///     same-type-requirement
///     layout-requirement
///
///   conformance-requirement:
///     type ':' type
///
///   same-type-requirement:
///     type '==' type
///
///   layout-requirement:
///     type ':' layout-constraint
ParsedSyntaxResult<ParsedGenericWhereClauseSyntax>
Parser::parseGenericWhereClauseSyntax(bool &FirstTypeInComplete,
                                      bool allowLayoutConstraints) {
  ParsedGenericWhereClauseSyntaxBuilder builder(*SyntaxContext);
  ParserStatus status;

  // Parse 'where'.
  builder.useWhereKeyword(consumeTokenSyntax(tok::kw_where));

  bool hasNext = true;
  do {
    auto firstType = parseTypeSyntax();
    status |= firstType.getStatus();
    FirstTypeInComplete = firstType.hasCodeCompletion();
    if (firstType.isNull())
      break;

    ParsedGenericRequirementSyntaxBuilder elementBuilder(*SyntaxContext);

    if (Tok.is(tok::colon)) {
      auto colon = consumeTokenSyntax(tok::colon);

      if (Tok.is(tok::identifier) &&
          getLayoutConstraint(Context.getIdentifier(Tok.getText()), Context)
              ->isKnownLayout()) {
        // Layout constraint.
        ParsedLayoutRequirementSyntaxBuilder layoutReqBuilder(*SyntaxContext);
        layoutReqBuilder.useLeftTypeIdentifier(firstType.get());
        layoutReqBuilder.useColon(std::move(colon));
        SourceLoc layoutLoc = Tok.getLoc();
        auto layout = parseLayoutConstraintSyntax();
        status |= layout.getStatus();

        if (!allowLayoutConstraints && !isInSILMode())
          diagnose(layoutLoc,
                   diag::layout_constraints_only_inside_specialize_attr);
        assert(!layout.isNull());
        layoutReqBuilder.useLayoutConstraint(layout.get());
        elementBuilder.useBody(layoutReqBuilder.build());
      } else {
        // Conformance requirement.
        ParsedConformanceRequirementSyntaxBuilder conformanceReqBuilder(
            *SyntaxContext);
        conformanceReqBuilder.useLeftTypeIdentifier(firstType.get());
        conformanceReqBuilder.useColon(std::move(colon));
        auto secondType = parseTypeSyntax();
        status |= secondType.getStatus();
        if (!secondType.isNull())
          conformanceReqBuilder.useRightTypeIdentifier(secondType.get());
        else
          conformanceReqBuilder.useRightTypeIdentifier(
              ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));
        elementBuilder.useBody(conformanceReqBuilder.build());
      }
    } else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
               Tok.is(tok::equal)) {
      // Same type requirement.
      ParsedSameTypeRequirementSyntaxBuilder sametypeReqBuilder(*SyntaxContext);
      sametypeReqBuilder.useLeftTypeIdentifier(firstType.get());
      if (Tok.is(tok::equal)) {
        diagnose(Tok, diag::requires_single_equal)
            .fixItReplace(SourceRange(Tok.getLoc()), "==");
        ignoreToken();
      } else {
        sametypeReqBuilder.useEqualityToken(consumeTokenSyntax());
      }

      auto secondType = parseTypeSyntax();
      status |= secondType.getStatus();
      if (!secondType.isNull())
        sametypeReqBuilder.useRightTypeIdentifier(secondType.get());
      else
        sametypeReqBuilder.useRightTypeIdentifier(
            ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));
      elementBuilder.useBody(sametypeReqBuilder.build());
    } else {
      diagnose(Tok, diag::expected_requirement_delim);
      status.setIsParseError();

      // Fallback to conformance requirement with missing right type.
      ParsedConformanceRequirementSyntaxBuilder conformanceReqBuilder(
          *SyntaxContext);
      conformanceReqBuilder.useLeftTypeIdentifier(firstType.get());
      conformanceReqBuilder.useRightTypeIdentifier(
          ParsedSyntaxRecorder::makeUnknownType({}, *SyntaxContext));
      elementBuilder.useBody(conformanceReqBuilder.build());
    }

    // Parse ','.
    hasNext = (status.isSuccess() && Tok.is(tok::comma));
    if (hasNext)
      elementBuilder.useTrailingComma(consumeTokenSyntax());

    builder.addRequirementListMember(elementBuilder.build());
  } while (hasNext && status.isSuccess());

  return makeParsedResult(builder.build(), status);
}

ParserStatus Parser::parseGenericWhereClause(
    SourceLoc &whereLoc, SmallVectorImpl<RequirementRepr> &requirements,
    bool &FirstTypeInComplete, bool AllowLayoutConstraints) {
  auto loc = leadingTriviaLoc();
  auto syntaxResult = parseGenericWhereClauseSyntax(FirstTypeInComplete,
                                                    AllowLayoutConstraints);
  if (syntaxResult.isNull())
    return syntaxResult.getStatus();

  SyntaxContext->addSyntax(syntaxResult.get());
  auto clause = SyntaxContext->topNode<GenericWhereClauseSyntax>();

  whereLoc = Generator.generate(clause.getWhereKeyword(), loc);
  requirements.reserve(clause.getRequirementList().size());
  for (auto elem : clause.getRequirementList()) {
    if (auto req = Generator.generate(elem, loc))
      requirements.push_back(*req);
  }

  return syntaxResult.getStatus();
}

/// Parse a free-standing where clause attached to a declaration, adding it to
/// a generic parameter list that may (or may not) already exist.
ParserStatus Parser::
parseFreestandingGenericWhereClause(GenericParamList *genericParams,
                                    WhereClauseKind kind) {
  assert(Tok.is(tok::kw_where) && "Shouldn't call this without a where");
  
  // Push the generic arguments back into a local scope so that references will
  // find them.
  Scope S(this, ScopeKind::Generics);
  
  if (genericParams)
    for (auto pd : genericParams->getParams())
      addToScope(pd);
  
  SmallVector<RequirementRepr, 4> Requirements;
  SourceLoc WhereLoc;
  bool FirstTypeInComplete;
  auto result = parseGenericWhereClause(WhereLoc, Requirements,
                                        FirstTypeInComplete);
  if (result.shouldStopParsing() || Requirements.empty())
    return result;

  if (!genericParams)
    diagnose(WhereLoc, diag::where_without_generic_params, unsigned(kind));
  else
    genericParams->addTrailingWhereClause(Context, WhereLoc, Requirements);
  return ParserStatus();
}

/// Parse a where clause after a protocol or associated type declaration.
ParserStatus Parser::parseProtocolOrAssociatedTypeWhereClause(
    TrailingWhereClause *&trailingWhere, bool isProtocol) {
  assert(Tok.is(tok::kw_where) && "Shouldn't call this without a where");
  SourceLoc whereLoc;
  SmallVector<RequirementRepr, 4> requirements;
  bool firstTypeInComplete;
  auto whereStatus =
      parseGenericWhereClause(whereLoc, requirements, firstTypeInComplete);
  if (whereStatus.isSuccess()) {
    trailingWhere =
        TrailingWhereClause::create(Context, whereLoc, requirements);
  } else if (whereStatus.hasCodeCompletion()) {
    return whereStatus;
  }

  return ParserStatus();
}
