//===--- DerivedConformanceKeyPathIterable.cpp ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//
//
// This file implements explicit derivation of the KeyPathIterable protocol for
// a nominal type.
//
//===----------------------------------------------------------------------===//

#include "CodeSynthesis.h"
#include "TypeChecker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Types.h"
#include "DerivedConformances.h"

using namespace swift;

bool DerivedConformance::canDeriveKeyPathIterable(NominalTypeDecl *nominal) {
  // Note: we could extend synthesis to support classes.
  // Subclasses need to append `allKeyPaths` to `super.allKeyPaths`.
  return isa<StructDecl>(nominal);
}

// Compute `PartialKeyPath<Nominal>`, bound to the given nominal
// declaration's type.
static Type computePartialKeyPathType(NominalTypeDecl *nominal) {
  auto &C = nominal->getASTContext();
  auto nominalType = nominal->getDeclaredInterfaceType();
  if (!nominalType || nominalType->hasError())
    return nullptr;
  auto *partialKeyPathDecl = cast<ClassDecl>(C.getPartialKeyPathDecl());
  return BoundGenericClassType::get(partialKeyPathDecl, /*parent*/ Type(),
                                    {nominal->getDeclaredInterfaceType()});
}

// Compute `AllKeyPaths` associated type for the given nominal declaration.
// It should be `[PartialKeyPath<Nominal>]`.
static ArraySliceType *computeAllKeyPathsType(NominalTypeDecl *nominal) {
  auto partialKeyPathType = computePartialKeyPathType(nominal);
  return ArraySliceType::get(partialKeyPathType);
}

// Compute `KeyPath<Nominal, Member>`.
static Type computeKeyPathType(NominalTypeDecl *nominal, Type memberType) {
  auto &C = nominal->getASTContext();
  auto nominalType = nominal->getDeclaredInterfaceType();
  if (!nominalType || nominalType->hasError())
    return nullptr;
  auto *keyPathDecl = cast<ClassDecl>(C.getKeyPathDecl());
  return BoundGenericClassType::get(
      keyPathDecl, /*parent*/ Type(),
      {nominal->getDeclaredInterfaceType(), memberType});
}

// Mark the given `ValueDecl` as `@inlinable`, if the conformance context's
// module is not resilient and the `ValueDecl` is effectively public.
// TODO: Dedupe with DerivedConformanceRawRepresentable.cpp.
static void maybeMarkAsInlinable(DerivedConformance &derived, ValueDecl *decl) {
  ASTContext &C = derived.Context;
  auto parentDC = derived.getConformanceContext();
  if (!parentDC->getParentModule()->isResilient()) {
    auto access = decl->getFormalAccessScope(
        nullptr, /*treatUsableFromInlineAsPublic*/ true);
    if (access.isPublic()) {
      decl->getAttrs().add(new (C) InlinableAttr(/*implicit*/ false));
      if (auto *attr = decl->getAttrs().getAttribute<UsableFromInlineAttr>())
        attr->setInvalid();
    }
  }
}

// Synthesize body for the `allKeyPaths` computed property getter.
static std::pair<BraceStmt *, bool>
deriveBodyKeyPathIterable_allKeyPaths(AbstractFunctionDecl *funcDecl, void *) {
  auto *parentDC = funcDecl->getDeclContext();
  auto *nominal = parentDC->getSelfNominalTypeDecl();
  auto &C = nominal->getASTContext();

  auto *nominalTypeExpr = TypeExpr::createImplicitForDecl(
      DeclNameLoc(), nominal, funcDecl,
      funcDecl->mapTypeIntoContext(nominal->getInterfaceType()));

  // Create array of key path expressions to stored properties.
  llvm::SmallVector<Expr *, 2> keyPathExprs;
  for (auto member : nominal->getStoredProperties()) {
    // FIXME(TF-123): Skip generating keypaths to `@differentiable` functions
    // because of SILGen crash. Robust fix involves changing
    // `createAutoDiffThunk`.
    if (auto fnType = member->getType()->getAs<AnyFunctionType>())
      if (fnType->getExtInfo().isDifferentiable())
        continue;

    auto *dotExpr = new (C)
        UnresolvedDotExpr(nominalTypeExpr, SourceLoc(),
                          DeclNameRef(member->getName()), DeclNameLoc(),
                          /*Implicit*/ true);
    Expr *keyPathExpr =
        new (C) KeyPathExpr(SourceLoc(), dotExpr, nullptr, /*Implicit*/ true);
    // NOTE(TF-575): Adding an explicit coercion expression to
    // `KeyPath<Nominal, Member>` here is necessary due to type-checker changes.
    auto keyPathInterfaceType =
        computeKeyPathType(nominal, member->getInterfaceType());
    auto keyPathType = parentDC->mapTypeIntoContext(keyPathInterfaceType);
    keyPathExpr = CoerceExpr::createImplicit(C, keyPathExpr, keyPathType);
    keyPathExprs.push_back(keyPathExpr);
  }
  // Return array of all key path expressions.
  Expr *keyPathsArrayExpr =
      ArrayExpr::create(C, SourceLoc(), keyPathExprs, {}, SourceLoc());
  keyPathsArrayExpr->setImplicit();
  auto *returnStmt = new (C) ReturnStmt(SourceLoc(), keyPathsArrayExpr);
  auto *body = BraceStmt::create(C, SourceLoc(), {returnStmt}, SourceLoc(),
                                 /*Implicit*/ true);
  auto *braceStmt = BraceStmt::create(C, SourceLoc(), {body}, SourceLoc(),
                                      /*Implicit*/ true);
  return std::pair<BraceStmt *, bool>(braceStmt, false);
}

// Synthesize the `allKeyPaths` computed property declaration.
static ValueDecl *
deriveKeyPathIterable_allKeyPaths(DerivedConformance &derived) {
  auto nominal = derived.Nominal;
  auto &C = derived.Context;

  auto returnInterfaceTy = computeAllKeyPathsType(nominal);
  auto returnTy =
      derived.getConformanceContext()->mapTypeIntoContext(returnInterfaceTy);

  // Create `allKeyPaths` property declaration.
  VarDecl *allKeyPathsDecl;
  PatternBindingDecl *pbDecl;
  std::tie(allKeyPathsDecl, pbDecl) = derived.declareDerivedProperty(
      C.Id_allKeyPaths, returnInterfaceTy, returnTy, /*isStatic*/ false,
      /*isFinal*/ true);

  // Maybe add `@inlinable` to the `allKeyPaths` declaration.
  if (llvm::all_of(nominal->getStoredProperties(), [](VarDecl *vd) {
    return vd->getFormalAccessScope(
        nullptr, /*treatUsableFromInlineAsPublic*/ true).isPublic();
  })) {
    maybeMarkAsInlinable(derived, allKeyPathsDecl);
  }

  // Create `allKeyPaths` getter.
  auto *getterDecl = derived.addGetterToReadOnlyDerivedProperty(
      allKeyPathsDecl, returnTy);
  getterDecl->setBodySynthesizer(
      deriveBodyKeyPathIterable_allKeyPaths, nullptr);
  derived.addMembersToConformanceContext({allKeyPathsDecl, pbDecl});

  return allKeyPathsDecl;
}

static Type deriveKeyPathIterable_AllKeyPaths(DerivedConformance &derived) {
  auto *rawInterfaceType = computeAllKeyPathsType(derived.Nominal);
  return derived.getConformanceContext()->mapTypeIntoContext(rawInterfaceType);
}

ValueDecl *DerivedConformance::deriveKeyPathIterable(ValueDecl *requirement) {
  // Diagnose conformances in disallowed contexts.
  if (checkAndDiagnoseDisallowedContext(requirement))
    return nullptr;
  if (requirement->getBaseName() == Context.Id_allKeyPaths)
    return deriveKeyPathIterable_allKeyPaths(*this);
  Context.Diags.diagnose(requirement->getLoc(),
              diag::broken_key_path_iterable_requirement);
  return nullptr;
}

Type DerivedConformance::deriveKeyPathIterable(
    AssociatedTypeDecl *requirement) {
  // Diagnose conformances in disallowed contexts.
  if (checkAndDiagnoseDisallowedContext(requirement))
    return nullptr;
  if (requirement->getBaseName() == Context.Id_AllKeyPaths)
    return deriveKeyPathIterable_AllKeyPaths(*this);
  Context.Diags.diagnose(requirement->getLoc(),
              diag::broken_key_path_iterable_requirement);
  return nullptr;
}
