//===--- IAMInference.cpp - Import as member inference system -------------===//
//
// 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 support for inferring when globals can be imported as
// members
//
//===----------------------------------------------------------------------===//
#include "CFTypeInfo.h"
#include "IAMInference.h"
#include "ImporterImpl.h"

#include "swift/AST/ASTContext.h"
#include "swift/Basic/StringExtras.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"

#include <array>
#include <tuple>

#define DEBUG_TYPE "Infer import as member"

// Statistics for failure to infer
STATISTIC(FailInferVar, "# of variables unable to infer");
STATISTIC(FailInferFunction, "# of functions unable to infer");

// Specifically skipped/avoided
STATISTIC(SkipLeadingUnderscore,
          "# of globals skipped due to leading underscore");
STATISTIC(SkipCFMemoryManagement,
          "# of CF memory management globals skipped");

// Success statistics
STATISTIC(SuccessImportAsTypeID, "# imported as 'typeID'");
STATISTIC(SuccessImportAsConstructor, "# imported as 'init'");
STATISTIC(SuccessImportAsInstanceComputedProperty,
          "# imported as instance computed property");
STATISTIC(SuccessImportAsStaticProperty,
          "# imported as static (stored) property");
STATISTIC(SuccessImportAsStaticComputedProperty,
          "# imported as static computed property");
STATISTIC(SuccessImportAsStaticMethod, "# imported as static method");
STATISTIC(SuccessImportAsInstanceMethod, "# imported as instance method");

// Statistics for why we couldn't infer in more specific ways, and fell back to
// methods
STATISTIC(InvalidPropertyStaticNumParams,
          "couldn't infer as static property: invalid number of parameters");
STATISTIC(InvalidPropertyInstanceNumParams,
          "couldn't infer as instance property: invalid number of parameters");
STATISTIC(InvalidPropertyStaticGetterSetterType,
          "couldn't infer as static property: getter/setter type mismatch");
STATISTIC(InvalidPropertyInstanceGetterSetterType,
          "couldn't infer as instance property: getter/setter type mismatch");
STATISTIC(InvalidPropertyInstanceNoSelf,
          "couldn't infer as instance property: couldn't find self");

// Omit needless words stats
STATISTIC(OmitNumTimes,
          "# of times omitNeedlessWords was able to fire on an API");

using namespace swift;
using namespace importer;

using NameBuffer = SmallString<32>;

static const std::array<StringRef, 2> InitSpecifiers{{
    StringRef("Create"), StringRef("Make"),
}};
static const std::array<StringRef, 2> PropertySpecifiers{{
    StringRef("Get"), StringRef("Set"),
}};

IAMOptions IAMOptions::getDefault() { return {}; }

// As append, but skip a repeated word at the boundary. First-letter-case
// insensitive.
// Example: appendUniq("FooBar", "barBaz") ==> "FooBarBaz"
static void appendUniq(NameBuffer &src, StringRef toAppend) {
  if (src.empty()) {
    src = toAppend;
    return;
  }

  auto appendWords = camel_case::getWords(toAppend);
  StringRef lastWord = *camel_case::getWords(src).rbegin();
  auto wI = appendWords.begin();
  while (wI != appendWords.end() && wI->equals_lower(lastWord))
    ++wI;
  src.append(wI.getRestOfStr());
}

static StringRef skipLeadingUnderscores(StringRef str) {
  while (!str.empty() && str.startswith("_"))
    str = str.drop_front(1);
  return str;
}

// Form a humble camel name from a string. Skips leading underscores.
static void formHumbleCamelName(StringRef str, NameBuffer &out) {
  str = skipLeadingUnderscores(str);
  auto newStr = camel_case::toLowercaseInitialisms(str, out);
  if (newStr == str)
    out = newStr;
}

// Form a humble camel by appending the two strings and adjusting case as
// needed. Skips leading underscores in either name, and skips a repeated word
// at the boundary. Example: formHumbleCamelName("__FooBar", "barBaz") ==>
// "fooBarBaz".
static void formHumbleCamelName(StringRef left, StringRef right,
                                NameBuffer &out) {
  left = skipLeadingUnderscores(left);
  if (left == "") {
    formHumbleCamelName(right, out);
    return;
  }
  right = skipLeadingUnderscores(right);
  if (right == "") {
    formHumbleCamelName(left, out);
    return;
  }

  StringRef lastWord = *camel_case::getWords(left).rbegin();
  auto rightWords = camel_case::getWords(right);
  auto wI = rightWords.begin();
  while (wI != rightWords.end() && wI->equals_lower(lastWord))
    ++wI;

  formHumbleCamelName(left, out);
  camel_case::appendSentenceCase(out, wI.getRestOfStr());
}

static bool hasWord(StringRef s, StringRef matchWord) {
  for (auto word : camel_case::getWords(s))
    if (word == matchWord)
      return true;
  return false;
}

// Drops the specified word, and returns the number of times it was dropped.
// When forming the resultant string, will call appendUniq to skip repeated
// words at the boundary.
static unsigned dropWordUniq(StringRef str, StringRef word, NameBuffer &out) {
  unsigned numDropped = 0;
  auto words = camel_case::getWords(str);
  for (auto wI = words.begin(), wE = words.end(); wI != wE; ++wI)
    if (*wI == word)
      ++numDropped;
    else
      appendUniq(out, *wI);

  return numDropped;
}

static clang::Module *getSubmodule(const clang::NamedDecl *decl, clang::Sema &clangSema) {
  if (auto m = decl->getImportedOwningModule())
    return m;
  if (auto m = decl->getLocalOwningModule())
    return m;
  if (auto m = clangSema.getPreprocessor().getCurrentModule())
    return m;
  if (auto m = clangSema.getPreprocessor().getCurrentSubmodule())
    return m;

  return nullptr;
}

static clang::Module *getTopModule(clang::Module *m) {
  while (m->Parent)
    m = m->Parent;
  return m;
}
static clang::Module *getTopModule(const clang::NamedDecl *decl, clang::Sema &clangSema) {
  auto m = getSubmodule(decl, clangSema);
  if (!m)
    return nullptr;
  return getTopModule(m);
}


namespace {
class IAMInference {
  ASTContext &context;
  clang::Sema &clangSema;
  IAMOptions options;

public:
  IAMInference(ASTContext &ctx, clang::Sema &sema, IAMOptions opts)
      : context(ctx), clangSema(sema), options(opts) {
    (void)options;
  }

  IAMResult infer(const clang::NamedDecl *);
  IAMResult inferVar(const clang::VarDecl *);

private:
  // typeID
  IAMResult importAsTypeID(const clang::QualType typeIDTy,
                           EffectiveClangContext effectiveDC) {
    ++SuccessImportAsTypeID;
    return {formDeclName("typeID"), IAMAccessorKind::Getter, effectiveDC};
  }

  // Init
  IAMResult importAsConstructor(StringRef name, StringRef initSpecifier,
                                ArrayRef<const clang::ParmVarDecl *> params,
                                EffectiveClangContext effectiveDC) {
    ++SuccessImportAsConstructor;
    NameBuffer buf;
    StringRef prefix = buf;
    if (name != initSpecifier) {
      assert(name.size() > initSpecifier.size() &&
             "should have more words in it");
      bool didDrop = dropWordUniq(name, initSpecifier, buf);
      (void)didDrop;
      prefix = buf;

      // Skip "with"
      auto prefixWords = camel_case::getWords(prefix);
      if (prefixWords.begin() != prefixWords.end() &&
          (*prefixWords.begin() == "With" || *prefixWords.begin() == "with")) {
        prefix = prefix.drop_front(4);
      }

      // Skip "CF" or "NS"
      prefixWords = camel_case::getWords(prefix);
      if (prefixWords.begin() != prefixWords.end() &&
          (*prefixWords.begin() == "CF" || *prefixWords.begin() == "NS")) {
        prefix = prefix.drop_front(2);
      }

      assert(didDrop != 0 && "specifier not present?");
    }
    return {formDeclName("init", params, prefix), effectiveDC};
  }

  // Instance computed property
  IAMResult
  importAsInstanceProperty(StringRef name, StringRef propSpec, unsigned selfIdx,
                           ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
                           const clang::FunctionDecl *pairedAccessor,
                           EffectiveClangContext effectiveDC) {
    ++SuccessImportAsInstanceComputedProperty;
    IAMAccessorKind kind =
        propSpec == "Get" ? IAMAccessorKind::Getter : IAMAccessorKind::Setter;
    assert(kind == IAMAccessorKind::Getter || pairedAccessor && "no set-only");

    return {formDeclName(name), kind, selfIdx, effectiveDC};
  }

  // Instance method
  IAMResult
  importAsInstanceMethod(StringRef name, unsigned selfIdx,
                         ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
                         EffectiveClangContext effectiveDC) {
    ++SuccessImportAsInstanceMethod;
    return {formDeclName(name, nonSelfParams), selfIdx, effectiveDC};
  }

  // Static stored property
  IAMResult importAsStaticProperty(StringRef name,
                                   EffectiveClangContext effectiveDC) {
    ++SuccessImportAsStaticProperty;
    return {formDeclName(name), effectiveDC};
  }

  // Static computed property
  IAMResult
  importAsStaticProperty(StringRef name, StringRef propSpec,
                         ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
                         const clang::FunctionDecl *pairedAccessor,
                         EffectiveClangContext effectiveDC) {
    ++SuccessImportAsStaticComputedProperty;
    IAMAccessorKind kind =
        propSpec == "Get" ? IAMAccessorKind::Getter : IAMAccessorKind::Setter;
    assert(kind == IAMAccessorKind::Getter || pairedAccessor && "no set-only");

    return {formDeclName(name), kind, effectiveDC};
  }

  // Static method
  IAMResult
  importAsStaticMethod(StringRef name,
                       ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
                       EffectiveClangContext effectiveDC) {
    ++SuccessImportAsStaticMethod;
    return {formDeclName(name, nonSelfParams), effectiveDC};
  }

  Identifier getIdentifier(StringRef str) {
    if (str == "")
      return Identifier();
    return context.getIdentifier(str);
  }

  template <typename DeclType>
  inline DeclType *clangLookup(StringRef name,
                               clang::Sema::LookupNameKind kind);

  clang::TypeDecl *clangLookupTypeDecl(StringRef name) {
    if (auto ty = clangLookup<clang::TypedefNameDecl>(
            name, clang::Sema::LookupNameKind::LookupOrdinaryName))
      return ty;

    return clangLookup<clang::TagDecl>(
        name, clang::Sema::LookupNameKind::LookupTagName);
  }

  clang::FunctionDecl *clangLookupFunction(StringRef name) {
    return clangLookup<clang::FunctionDecl>(
        name, clang::Sema::LookupNameKind::LookupOrdinaryName);
  }

  EffectiveClangContext findTypeAndMatch(StringRef workingName,
                                         NameBuffer &outStr) {
    // FIXME: drop mutable...

    // TODO: should we try some form of fuzzy or fuzzier matching?

    // Longest-prefix matching, alternate with checking for a trailing "Ref"
    // suffix and the prefix itself. We iterate from the back to the beginning.
    auto words = camel_case::getWords(workingName);
    for (auto rWordsIter = words.rbegin(), rWordsEnd = words.rend();
         rWordsIter != rWordsEnd; ++rWordsIter) {
      NameBuffer nameAttempt;
      nameAttempt.append(rWordsIter.base().getPriorStr());
      StringRef prefix = nameAttempt;
      nameAttempt.append("Ref");
      StringRef prefixWithRef = nameAttempt;

      if (auto tyDecl = clangLookupTypeDecl(prefixWithRef)) {
        outStr.append(workingName.drop_front(prefix.size()));
        return getEffectiveDC(clang::QualType(tyDecl->getTypeForDecl(), 0));
      }
      if (auto tyDecl = clangLookupTypeDecl(prefix)) {
        outStr.append(workingName.drop_front(prefix.size()));
        return getEffectiveDC(clang::QualType(tyDecl->getTypeForDecl(), 0));
      }
    }

    return {};
  }

  bool validToImportAsProperty(const clang::FunctionDecl *originalDecl,
                               StringRef propSpec, Optional<unsigned> selfIndex,
                               const clang::FunctionDecl *&pairedAccessor);

  const clang::FunctionDecl *findPairedAccessor(StringRef name,
                                                StringRef propSpec) {
    NameBuffer pairName;
    auto words = camel_case::getWords(name);
    for (auto word : words) {
      if (word == propSpec) {
        if (propSpec == "Get") {
          pairName.append("Set");
        } else {
          assert(propSpec == "Set");
          pairName.append("Get");
        }
      } else {
        pairName.append(word);
      }
    }

    return clangLookupFunction(pairName);
  }

  Identifier getHumbleIdentifier(StringRef name) {
    // Lower-camel-case the incoming name
    NameBuffer buf;
    formHumbleCamelName(name, buf);
    return getIdentifier(buf);
  }

  DeclName formDeclName(StringRef baseName) {
    return {getHumbleIdentifier(baseName)};
  }

  DeclName formDeclName(StringRef baseName,
                        ArrayRef<const clang::ParmVarDecl *> params,
                        StringRef firstPrefix = "") {

    // TODO: redesign from a SmallString to a StringScratchBuffer design for all
    // of this name mangling, since we have to use one for omit needless words
    // anyways

    if (params.empty() && firstPrefix != "") {
      // We need to form an argument label, despite there being no argument
      NameBuffer paramName;
      formHumbleCamelName(firstPrefix, paramName);
      return {context, getHumbleIdentifier(baseName),
              getIdentifier(paramName)};
    }

    StringScratchSpace scratch;
    SmallVector<StringRef, 8> argStrs;
    for (unsigned i = 0; i < params.size(); ++i) {
      NameBuffer paramName;
      if (i == 0 && firstPrefix != "") {
        formHumbleCamelName(firstPrefix, params[i]->getName(), paramName);
      } else {
        // TODO: strip leading underscores
        formHumbleCamelName(params[i]->getName(), paramName);
      }

      argStrs.push_back(scratch.copyString(paramName));
    }

    DeclName beforeOmit;
    (void)beforeOmit;
    {
      SmallVector<Identifier, 8> argLabels;
      for (auto str : argStrs)
        argLabels.push_back(getIdentifier(str));
      DEBUG((beforeOmit = {context, getHumbleIdentifier(baseName), argLabels}));
    }

    SmallVector<OmissionTypeName, 8> paramTypeNames;
    for (auto param : params) {
      paramTypeNames.push_back(getClangTypeNameForOmission(
          clangSema.getASTContext(), param->getType()));
    }

    auto humbleBaseName = getHumbleIdentifier(baseName);
    baseName = humbleBaseName.str();
    bool didOmit =
        omitNeedlessWords(baseName, argStrs, "", "", "", paramTypeNames, false,
                          false, nullptr, scratch);
    SmallVector<Identifier, 8> argLabels;
    for (auto str : argStrs)
      argLabels.push_back(getIdentifier(str));

    DeclName ret = {context, getHumbleIdentifier(baseName), argLabels};

    if (didOmit) {
      ++OmitNumTimes;
      DEBUG(llvm::dbgs() << "omission detected: " << beforeOmit << " ==> "
                         << ret << "\n");
    }

    return ret;
  }

  bool matchTypeName(StringRef str, clang::QualType qt, NameBuffer &outStr);
  bool match(StringRef str, StringRef toMatch, NameBuffer &outStr);

  EffectiveClangContext getEffectiveDC(clang::QualType qt) {
    // Read through some attributes
    while (qt.getTypePtrOrNull() && isa<clang::AttributedType>(qt.getTypePtr()))
      qt = qt.getSingleStepDesugaredType(clangSema.getASTContext());

    // Read through typedefs until we get to a CF typedef or a non-typedef-ed
    // type
    while (qt.getTypePtrOrNull() && isa<clang::TypedefType>(qt.getTypePtr())) {
      auto typedefType = cast<clang::TypedefType>(qt.getTypePtr());
      if (auto pointeeInfo = CFPointeeInfo::classifyTypedef(
              typedefType->getDecl()->getCanonicalDecl())) {
        if (pointeeInfo.isRecord() || pointeeInfo.isTypedef())
          return {typedefType->getDecl()->getCanonicalDecl()};
        assert(pointeeInfo.isVoid() && "no other type");
        return {};
      }
      qt = qt.getSingleStepDesugaredType(clangSema.getASTContext());
    }

    auto pointeeQT = qt.getTypePtr()->getPointeeType();
    if (pointeeQT != clang::QualType())
      // Retry on the pointee
      return getEffectiveDC(pointeeQT);

    if (auto tagDecl = qt.getTypePtr()->getAsTagDecl()) {
      auto canon = tagDecl->getCanonicalDecl();
      if (canon->getDefinition())
        return {canon};

      // TODO: Once the importer learns how to import un-defined structs, then
      // we will be able to infer them. Until that point, we have to bail
      // because ImportDecl won't be able to re-map this.
      return {};
    }

    // Failed to find a type we can extend
    return {};
  }
};
} // end anonymous namespace

static StringRef getTypeName(clang::QualType qt) {
  if (auto typedefTy = qt->getAs<clang::TypedefType>()) {
    // Check for a CF type name (drop the "Ref")
    auto cfName = getCFTypeName(typedefTy->getDecl()->getCanonicalDecl());
    if (cfName != StringRef())
      return cfName;
  }

  auto identInfo = qt.getBaseTypeIdentifier();
  if (identInfo)
    return identInfo->getName();

  // Otherwise, no name
  return {};
}

bool IAMInference::matchTypeName(StringRef str, clang::QualType qt,
                                 NameBuffer &outStr) {
  StringRef typeName = getTypeName(qt);
  if (typeName == "")
    return false;

  // Special case: Mutable can appear in both and may screw up word order. Or,
  // Mutable can occur in the type name only. Either way, we want to have the
  // potential of successfully matching the type.
  NameBuffer nonMutableStr;
  NameBuffer nonMutableTypeName;
  if (hasWord(typeName, "Mutable")) {
    dropWordUniq(typeName, "Mutable", nonMutableTypeName);
    typeName = nonMutableTypeName;
    if (hasWord(str, "Mutable")) {
      dropWordUniq(str, "Mutable", nonMutableStr);
      str = nonMutableStr;
    }
  }

  return match(str, typeName, outStr);
}

bool IAMInference::match(StringRef str, StringRef toMatch, NameBuffer &outStr) {
  // TODO: let options dictate fuzzy matching...

  auto strWords = camel_case::getWords(str);
  auto matchWords = camel_case::getWords(toMatch);

  auto strIter = strWords.begin();
  auto matchIter = matchWords.begin();

  // Match in order, but allowing interjected words
  while (strIter != strWords.end()) {
    if (matchIter == matchWords.end()) {
      // We matched them all!
      appendUniq(outStr, strIter.getRestOfStr());
      return true;
    }
    if (*strIter == *matchIter) {
      // It's a match!
      ++strIter;
      ++matchIter;
      continue;
    }
    // Move on to the next one
    appendUniq(outStr, *strIter);
    ++strIter;
  }

  return false;
}

// A loose type equality check that disregards all sugar, qualification, looks
// through pointers, etc.
static bool roughlyEqual(clang::QualType left, clang::QualType right) {
  auto leftPointee = left->getPointeeType();
  if (leftPointee != clang::QualType())
    left = leftPointee;
  auto rightPointee = right->getPointeeType();
  if (rightPointee != clang::QualType())
    right = rightPointee;
  return left->getUnqualifiedDesugaredType() ==
         right->getUnqualifiedDesugaredType();
}

static bool
isValidAsStaticProperty(const clang::FunctionDecl *getterDecl,
                        const clang::FunctionDecl *setterDecl = nullptr) {
  // Getter has none, setter has one arg
  if (getterDecl->getNumParams() != 0 ||
      (setterDecl && setterDecl->getNumParams() != 1)) {
    ++InvalidPropertyStaticNumParams;
    return false;
  }

  // Setter's arg type should be same as getter's return type
  auto getterTy = getterDecl->getReturnType();
  if (setterDecl &&
      !roughlyEqual(getterTy, setterDecl->getParamDecl(0)->getType())) {
    ++InvalidPropertyStaticGetterSetterType;
    return false;
  }

  return true;
}

static bool
isValidAsInstanceProperty(const clang::FunctionDecl *getterDecl,
                          const clang::FunctionDecl *setterDecl = nullptr) {
  // Instance property, look beyond self
  if (getterDecl->getNumParams() != 1 ||
      (setterDecl && setterDecl->getNumParams() != 2)) {
    ++InvalidPropertyInstanceNumParams;
    return false;
  }

  if (!setterDecl)
    return true;

  // Make sure they pair up
  auto getterTy = getterDecl->getReturnType();
  auto selfTy = getterDecl->getParamDecl(0)->getType();

  clang::QualType setterTy = {};
  auto setterParam0Ty = setterDecl->getParamDecl(0)->getType();
  auto setterParam1Ty = setterDecl->getParamDecl(1)->getType();

  if (roughlyEqual(setterParam0Ty, selfTy)) {
    setterTy = setterParam1Ty;
  } else if (roughlyEqual(setterParam1Ty, selfTy)) {
    setterTy = setterParam0Ty;
  } else {
    ++InvalidPropertyInstanceNoSelf;
    return false;
  }

  if (!roughlyEqual(setterTy, getterTy)) {
    ++InvalidPropertyInstanceGetterSetterType;
    return false;
  }

  return true;
}

bool IAMInference::validToImportAsProperty(
    const clang::FunctionDecl *originalDecl, StringRef propSpec,
    Optional<unsigned> selfIndex, const clang::FunctionDecl *&pairedAccessor) {
  bool isGet = propSpec == "Get";
  pairedAccessor = findPairedAccessor(originalDecl->getName(), propSpec);
  if (!pairedAccessor) {
    if (!isGet)
      return false;
    if (!selfIndex)
      return isValidAsStaticProperty(originalDecl);
    return isValidAsInstanceProperty(originalDecl);
  }

  auto getterDecl = isGet ? originalDecl : pairedAccessor;
  auto setterDecl = isGet ? pairedAccessor : originalDecl;

  if (getTopModule(getterDecl, clangSema) !=
      getTopModule(setterDecl, clangSema)) {
    // We paired up decls from two different modules, so either we still infer
    // as a getter with no setter, or we cannot be a property
    if (isGet) {
      pairedAccessor = nullptr;
      setterDecl = nullptr;
    } else  {
      // This is set-only as far as we're concerned
      return false;
    }
  }

  if (!selfIndex)
    return isValidAsStaticProperty(getterDecl, setterDecl);

  return isValidAsInstanceProperty(getterDecl, setterDecl);
}

IAMResult IAMInference::inferVar(const clang::VarDecl *varDecl) {
  auto fail = [varDecl]() -> IAMResult {
    DEBUG(llvm::dbgs() << "failed to infer variable: ");
    DEBUG(varDecl->print(llvm::dbgs()));
    DEBUG(llvm::dbgs() << "\n");
    ++FailInferVar;
    return {};
  };

  // Try to find a type to add this as a static property to
  StringRef workingName = varDecl->getName();
  if (workingName.empty())
    return fail();

  // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with
  // property "Baz"
  if (*camel_case::getWords(workingName).begin() == "k")
    workingName = workingName.drop_front(1);

  NameBuffer remainingName;
  if (auto effectiveDC = findTypeAndMatch(workingName, remainingName))

    return importAsStaticProperty(remainingName, effectiveDC);

  return fail();
}

IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) {
  if (clangDecl->getName().startswith("_")) {
    ++SkipLeadingUnderscore;
    return {};
  }

  // Try to infer a member variable
  if (auto varDecl = dyn_cast<clang::VarDecl>(clangDecl))
    return inferVar(varDecl);

  // Try to infer a member function
  auto funcDecl = dyn_cast<clang::FunctionDecl>(clangDecl);
  if (!funcDecl) {
    // TODO: Do we want to collects stats here? Should it be assert?
    return {};
  }

  auto fail = [funcDecl]() -> IAMResult {
    DEBUG(llvm::dbgs() << "failed to infer function: ");
    DEBUG(funcDecl->print(llvm::dbgs()));
    DEBUG(llvm::dbgs() << "\n");
    ++FailInferFunction;
    return {};
  };

  // Can't really import variadics well
  if (funcDecl->isVariadic())
    return fail();

  // FIXME: drop "Mutable"...

  StringRef workingName = funcDecl->getName();
  auto retTy = funcDecl->getReturnType();
  unsigned numParams = funcDecl->getNumParams();

  // 0) Special cases are specially handled
  //
  StringRef getTypeID = "GetTypeID";
  StringRef cfSpecials[] = {"Release", "Retain", "Autorelease"};
  // *GetTypeID
  if (numParams == 0 && workingName.endswith(getTypeID)) {
    NameBuffer remainingName;
    if (auto effectiveDC = findTypeAndMatch(
            workingName.drop_back(getTypeID.size()), remainingName)) {
      // We shouldn't have anything else left in our name for typeID
      if (remainingName.empty()) {

        return importAsTypeID(retTy, effectiveDC);
      }
    }
    // *Release/*Retain/*Autorelease
  } else if (numParams == 1 &&
             std::any_of(std::begin(cfSpecials), std::end(cfSpecials),
                         [workingName](StringRef suffix) {
                           return workingName.endswith(suffix);
                         })) {
    if (auto type =
            funcDecl->getParamDecl(0)->getType()->getAs<clang::TypedefType>()) {
      if (CFPointeeInfo::classifyTypedef(type->getDecl())) {
        ++SkipCFMemoryManagement;
        return {};
      }
    }
  }

  // 1) If we find an init specifier and our name matches the return type, we
  //    import as some kind of constructor
  //
  if (!retTy->isVoidType()) {
    NameBuffer remainingName;
    if (matchTypeName(workingName, retTy, remainingName))
      for (auto initSpec : InitSpecifiers)
        if (hasWord(remainingName, initSpec))
          if (auto effectiveDC = getEffectiveDC(retTy))
            return importAsConstructor(
                remainingName, initSpec,
                {funcDecl->param_begin(), funcDecl->param_end()}, effectiveDC);
  }

  // 2) If we find a likely self reference in the parameters, make an instance
  //    member (method or property)
  //
  SmallVector<const clang::ParmVarDecl *, 8> nonSelfParams;
  unsigned selfIdx = 0;
  for (auto paramI = funcDecl->param_begin(), paramE = funcDecl->param_end();
       paramI != paramE; ++paramI, ++selfIdx) {
    auto param = *paramI;
    NameBuffer remainingName;
    if (matchTypeName(workingName, param->getType(), remainingName)) {
      auto effectiveDC = getEffectiveDC(param->getType());
      if (!effectiveDC)
        continue;
      nonSelfParams.append(funcDecl->param_begin(), paramI);
      nonSelfParams.append(++paramI, paramE);
      // See if it's a property
      for (auto propSpec : PropertySpecifiers) {
        NameBuffer propName;
        if (match(remainingName, propSpec, propName)) {
          const clang::FunctionDecl *pairedAccessor;
          if (validToImportAsProperty(funcDecl, propSpec, selfIdx,
                                      pairedAccessor))
            return importAsInstanceProperty(propName, propSpec, selfIdx,
                                            nonSelfParams, pairedAccessor,
                                            effectiveDC);
        }
      }

      return importAsInstanceMethod(remainingName, selfIdx, nonSelfParams,
                                    effectiveDC);
    }
  }

  // No self, must be static
  nonSelfParams = {funcDecl->param_begin(), funcDecl->param_end()};

  // 3) Finally, try to find a class to put this on as a static function
  NameBuffer remainingName;
  if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) {
    ArrayRef<const clang::ParmVarDecl *> params = {funcDecl->param_begin(),
                                                   funcDecl->param_end()};
    // See if it's a property
    for (auto propSpec : PropertySpecifiers) {
      NameBuffer propName;
      if (match(remainingName, propSpec, propName)) {
        const clang::FunctionDecl *pairedAccessor;
        if (validToImportAsProperty(funcDecl, propSpec, None, pairedAccessor))
          return importAsStaticProperty(propName, propSpec, nonSelfParams,
                                        pairedAccessor, effectiveDC);
      }
    }
    StringRef methodName =
        remainingName == "" ? workingName : StringRef(remainingName);
    return importAsStaticMethod(methodName, nonSelfParams, effectiveDC);
  }

  return fail();
}

template <typename DeclType>
DeclType *IAMInference::clangLookup(StringRef name,
                                    clang::Sema::LookupNameKind kind) {
  clang::IdentifierInfo *nameII = &clangSema.getASTContext().Idents.get(name);
  clang::LookupResult lookupResult(clangSema, clang::DeclarationName(nameII),
                                   clang::SourceLocation(), kind);
  if (!clangSema.LookupName(lookupResult, clangSema.TUScope))
    return nullptr;
  auto res = lookupResult.getAsSingle<DeclType>();
  if (!res)
    return nullptr;
  return res->getCanonicalDecl();
}

IAMResult IAMResult::infer(ASTContext &ctx, clang::Sema &clangSema,
                           const clang::NamedDecl *decl, IAMOptions opts) {
  IAMInference inference(ctx, clangSema, opts);
  return inference.infer(decl);
}
