//===--- TypeCheckExprObjC.cpp - Type Checking for ObjC Expressions -------===//
//
// 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 semantic analysis for Objective-C-specific
// expressions.
//
//===----------------------------------------------------------------------===//
#include "TypeChecker.h"
#include "TypoCorrection.h"
#include "swift/Basic/Range.h"

using namespace swift;

Optional<Type> TypeChecker::checkObjCKeyPathExpr(DeclContext *dc,
                                                 KeyPathExpr *expr,
                                                 bool requireResultType) {
  // TODO: Native keypaths
  assert(expr->isObjC() && "native keypaths not type-checked this way");
  
  // If there is already a semantic expression, do nothing.
  if (expr->getObjCStringLiteralExpr() && !requireResultType) return None;

  // ObjC #keyPath only makes sense when we have the Objective-C runtime.
  if (!Context.LangOpts.EnableObjCInterop) {
    diagnose(expr->getLoc(), diag::expr_keypath_no_objc_runtime);

    expr->setObjCStringLiteralExpr(
      new (Context) StringLiteralExpr("", expr->getSourceRange(),
                                      /*Implicit=*/true));
    return None;
  }

  // The key path string we're forming.
  SmallString<32> keyPathScratch;
  llvm::raw_svector_ostream keyPathOS(keyPathScratch);

  // Captures the state of semantic resolution.
  enum State {
    Beginning,
    ResolvingType,
    ResolvingProperty,
    ResolvingArray,
    ResolvingSet,
    ResolvingDictionary,
  } state = Beginning;
  
  /// Determine whether we are currently resolving a property.
  auto isResolvingProperty = [&] {
    switch (state) {
    case Beginning:
    case ResolvingType:
      return false;

    case ResolvingProperty:
    case ResolvingArray:
    case ResolvingSet:
    case ResolvingDictionary:
      return true;
    }

    llvm_unreachable("Unhandled State in switch.");
  };

  // The type of AnyObject, which is used whenever we don't have
  // sufficient type information.
  Type anyObjectType = Context.getAnyObjectType();

  // Local function to update the state after we've resolved a
  // component.
  Type currentType;
  auto updateState = [&](bool isProperty, Type newType) {
    // Strip off optionals.
    newType = newType->lookThroughAllOptionalTypes();

    // If updating to a type, just set the new type; there's nothing
    // more to do.
    if (!isProperty) {
      assert(state == Beginning || state == ResolvingType);
      state = ResolvingType;
      currentType = newType;
      return;
    }

    // We're updating to a property. Determine whether we're looking
    // into a bridged Swift collection of some sort.
    if (auto boundGeneric = newType->getAs<BoundGenericType>()) {
      auto nominal = boundGeneric->getDecl();

      // Array<T>
      if (nominal == Context.getArrayDecl()) {
        // Further lookups into the element type.
        state = ResolvingArray;
        currentType = boundGeneric->getGenericArgs()[0];
        return;
      }

      // Set<T>
      if (nominal == Context.getSetDecl()) {
        // Further lookups into the element type.
        state = ResolvingSet;
        currentType = boundGeneric->getGenericArgs()[0];
        return;
      }

      // Dictionary<K, V>
      if (nominal == Context.getDictionaryDecl()) {
        // Key paths look into the keys of a dictionary; further
        // lookups into the value type.
        state = ResolvingDictionary;
        currentType = boundGeneric->getGenericArgs()[1];
        return;
      }
    }

    // Determine whether we're looking into a Foundation collection.
    if (auto classDecl = newType->getClassOrBoundGenericClass()) {
      if (classDecl->isObjC() && classDecl->hasClangNode()) {
        SmallString<32> scratch;
        StringRef objcClassName = classDecl->getObjCRuntimeName(scratch);

        // NSArray
        if (objcClassName == "NSArray") {
          // The element type is unknown, so use AnyObject.
          state = ResolvingArray;
          currentType = anyObjectType;
          return;
        }

        // NSSet
        if (objcClassName == "NSSet") {
          // The element type is unknown, so use AnyObject.
          state = ResolvingSet;
          currentType = anyObjectType;
          return;
        }

        // NSDictionary
        if (objcClassName == "NSDictionary") {
          // Key paths look into the keys of a dictionary; there's no
          // type to help us here.
          state = ResolvingDictionary;
          currentType = anyObjectType;
          return;
        }
      }
    }

    // It's just a property.
    state = ResolvingProperty;
    currentType = newType;
  };
  
  // Local function to perform name lookup for the current index.
  auto performLookup = [&](DeclBaseName componentName,
                           SourceLoc componentNameLoc,
                           Type &lookupType) -> LookupResult {
    if (state == Beginning)
      return lookupUnqualified(dc, componentName, componentNameLoc);

    assert(currentType && "Non-beginning state must have a type");
    if (!currentType->mayHaveMembers())
      return LookupResult();

    // Determine the type in which the lookup should occur. If we have
    // a bridged value type, this will be the Objective-C class to
    // which it is bridged.
    if (auto bridgedClass = Context.getBridgedToObjC(dc, currentType))
      lookupType = bridgedClass;
    else
      lookupType = currentType;

    // Look for a member with the given name within this type.
    return lookupMember(dc, lookupType, componentName);
  };

  // Local function to print a component to the string.
  bool needDot = false;
  auto printComponent = [&](DeclBaseName component) {
    if (needDot)
      keyPathOS << ".";
    else
      needDot = true;

    keyPathOS << component;
  };

  bool isInvalid = false;
  SmallVector<KeyPathExpr::Component, 4> resolvedComponents;
  
  for (auto &component : expr->getComponents()) {
    auto componentNameLoc = component.getLoc();
    
    // ObjC keypaths only support named segments.
    // TODO: Perhaps we can map subscript components to dictionary keys.
    switch (auto kind = component.getKind()) {
    case KeyPathExpr::Component::Kind::Invalid:
      continue;

    case KeyPathExpr::Component::Kind::UnresolvedProperty:
      break;
    case KeyPathExpr::Component::Kind::UnresolvedSubscript:
    case KeyPathExpr::Component::Kind::OptionalChain:
    case KeyPathExpr::Component::Kind::OptionalForce:
      diagnose(componentNameLoc,
               diag::expr_unsupported_objc_key_path_component,
               (unsigned)kind);
      continue;
    case KeyPathExpr::Component::Kind::OptionalWrap:
    case KeyPathExpr::Component::Kind::Property:
    case KeyPathExpr::Component::Kind::Subscript:
      llvm_unreachable("already resolved!");
    }
    
    auto componentFullName = component.getUnresolvedDeclName();
    if (!componentFullName.isSimpleName()) {
      diagnose(componentNameLoc,
               diag::expr_unsupported_objc_key_path_compound_name);
      continue;
    }
    auto componentName = componentFullName.getBaseName();

    // If we are resolving into a dictionary, any component is
    // well-formed because the keys are unknown dynamically.
    if (state == ResolvingDictionary) {
      // Just print the component unchanged; there's no checking we
      // can do here.
      printComponent(componentName);

      // From here, we're resolving a property. Use the current type.
      updateState(/*isProperty=*/true, currentType);

      continue;
    }

    // Look for this component.
    Type lookupType;
    LookupResult lookup = performLookup(componentName, componentNameLoc,
                                        lookupType);

    // If we didn't find anything, try to apply typo-correction.
    bool resultsAreFromTypoCorrection = false;
    if (!lookup) {
      TypoCorrectionResults corrections(*this, componentName,
                                        DeclNameLoc(componentNameLoc));
      performTypoCorrection(dc, DeclRefKind::Ordinary, lookupType,
                            (lookupType ? defaultMemberTypeLookupOptions
                                        : defaultUnqualifiedLookupOptions),
                            corrections);

      if (currentType)
        diagnose(componentNameLoc, diag::could_not_find_type_member,
                 currentType, componentName);
      else
        diagnose(componentNameLoc, diag::use_unresolved_identifier,
                 componentName, false);

      // Note all the correction candidates.
      corrections.noteAllCandidates();
      corrections.addAllCandidatesToLookup(lookup);

      isInvalid = true;
      if (!lookup) break;

      // Remember that these are from typo correction.
      resultsAreFromTypoCorrection = true;
    }

    // If we have more than one result, filter out unavailable or
    // obviously unusable candidates.
    if (lookup.size() > 1) {
      lookup.filter([&](LookupResultEntry result, bool isOuter) -> bool {
          // Drop unavailable candidates.
          if (result.getValueDecl()->getAttrs().isUnavailable(Context))
            return false;

          // Drop non-property, non-type candidates.
          if (!isa<VarDecl>(result.getValueDecl()) &&
              !isa<TypeDecl>(result.getValueDecl()))
            return false;

          return true;
      });
    }

    // If we *still* have more than one result, fail.
    if (lookup.size() > 1) {
      // Don't diagnose ambiguities if the results are from typo correction.
      if (resultsAreFromTypoCorrection)
        break;

      if (lookupType)
        diagnose(componentNameLoc, diag::ambiguous_member_overload_set,
                 componentName);
      else
        diagnose(componentNameLoc, diag::ambiguous_decl_ref,
                 componentName);

      for (auto result : lookup) {
        diagnose(result.getValueDecl(), diag::decl_declared_here,
                 result.getValueDecl()->getFullName());
      }
      isInvalid = true;
      break;
    }

    auto found = lookup.front().getValueDecl();

    // Handle property references.
    if (auto var = dyn_cast<VarDecl>(found)) {
      validateDecl(var);

      // Resolve this component to the variable we found.
      auto varRef = ConcreteDeclRef(var);
      auto resolved =
        KeyPathExpr::Component::forProperty(varRef, Type(), componentNameLoc);
      resolvedComponents.push_back(resolved);
      updateState(/*isProperty=*/true,
                  var->getInterfaceType()->getRValueObjectType());

      // Check that the property is @objc.
      if (!var->isObjC()) {
        diagnose(componentNameLoc, diag::expr_keypath_non_objc_property,
                 componentName);
        if (var->getLoc().isValid() && var->getDeclContext()->isTypeContext()) {
          diagnose(var, diag::make_decl_objc,
                   var->getDescriptiveKind())
            .fixItInsert(var->getAttributeInsertionLoc(false),
                         "@objc ");
        }
      } else if (auto attr = var->getAttrs().getAttribute<ObjCAttr>()) {
        // If this attribute was inferred based on deprecated Swift 3 rules,
        // complain.
        if (attr->isSwift3Inferred() &&
            Context.LangOpts.WarnSwift3ObjCInference ==
              Swift3ObjCInferenceWarnings::Minimal) {
          diagnose(componentNameLoc, diag::expr_keypath_swift3_objc_inference,
                   var->getFullName(),
                   var->getDeclContext()
                    ->getAsNominalTypeOrNominalTypeExtensionContext()
                   ->getName());
          diagnose(var, diag::make_decl_objc, var->getDescriptiveKind())
            .fixItInsert(var->getAttributeInsertionLoc(false),
                         "@objc ");
        }
      } else {
        // FIXME: Warn about non-KVC-compliant getter/setter names?
      }

      // Print the Objective-C property name.
      printComponent(var->getObjCPropertyName());
      continue;
    }

    // Handle type references.
    if (auto type = dyn_cast<TypeDecl>(found)) {
      // We cannot refer to a type via a property.
      if (isResolvingProperty()) {
        diagnose(componentNameLoc, diag::expr_keypath_type_of_property,
                 componentName, currentType);
        isInvalid = true;
        break;
      }

      // We cannot refer to a generic type.
      if (type->getDeclaredInterfaceType()->hasTypeParameter()) {
        diagnose(componentNameLoc, diag::expr_keypath_generic_type,
                 componentName);
        isInvalid = true;
        break;
      }

      Type newType;
      if (lookupType && !lookupType->isAnyObject()) {
        newType = lookupType->getTypeOfMember(dc->getParentModule(), type,
                                              type->getDeclaredInterfaceType());
      } else {
        newType = type->getDeclaredInterfaceType();
      }
      if (!newType) {
        isInvalid = true;
        break;
      }

      updateState(/*isProperty=*/false, newType);
      continue;
    }

    // Declarations that cannot be part of a key-path.
    diagnose(componentNameLoc, diag::expr_keypath_not_property,
             found->getDescriptiveKind(), found->getFullName());
    isInvalid = true;
    break;
  }
  // A successful check of an ObjC keypath shouldn't add or remove components,
  // currently.
  if (resolvedComponents.size() == expr->getComponents().size())
    expr->resolveComponents(Context, resolvedComponents);

  // Check for an empty key-path string.
  auto keyPathString = keyPathOS.str();
  if (keyPathString.empty() && !isInvalid)
    diagnose(expr->getLoc(), diag::expr_keypath_empty);

  // Set the string literal expression for the ObjC key path.
  if (!expr->getObjCStringLiteralExpr()) {
    expr->setObjCStringLiteralExpr(
      new (Context) StringLiteralExpr(Context.AllocateCopy(keyPathString),
                                      expr->getSourceRange(),
                                      /*Implicit=*/true));
  }

  if (!currentType) return None;
  return currentType;
}
