// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "fake_decl_source.h"

#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/Lookup.h>

FakeDeclSource::FakeDeclSource(const clang::CompilerInstance &ci) : ci_(ci) {}

clang::CXXRecordDecl *
FakeDeclSource::CreateCXXRecordDecl(const clang::DeclarationName &name,
                                    clang::DeclContext *decl_context) {
  clang::CXXRecordDecl *cxx_record_decl = clang::CXXRecordDecl::Create(
      ci_.getASTContext(), clang::TTK_Struct, decl_context,
      clang::SourceLocation(), clang::SourceLocation(),
      name.getAsIdentifierInfo(), /* PrevDecl */ nullptr);
  cxx_record_decl->setInvalidDecl(true);

  return cxx_record_decl;
}

clang::ClassTemplateDecl *
FakeDeclSource::CreateClassTemplateDecl(clang::CXXRecordDecl *cxx_record_decl,
                                        clang::DeclContext *decl_context) {
  clang::ASTContext &ast = ci_.getASTContext();

  // Declare `template<typename ...T> struct RecordName` in decl_context.
  clang::TemplateTypeParmDecl *parm = clang::TemplateTypeParmDecl::Create(
      ast, decl_context, clang::SourceLocation(), clang::SourceLocation(),
      /* Depth */ 0, /* Position */ 0, /* Id */ nullptr,
      /* Typename */ true, /* ParameterPack */ true);
  parm->setInvalidDecl(true);

  clang::NamedDecl *parm_array[1] = {parm};
  clang::TemplateParameterList *parm_list =
      clang::TemplateParameterList::Create(
          ast, clang::SourceLocation(), clang::SourceLocation(), parm_array,
          clang::SourceLocation(), /* RequiresClause */ nullptr);

  clang::ClassTemplateDecl *class_template_decl =
      clang::ClassTemplateDecl::Create(
          ast, decl_context, clang::SourceLocation(),
          cxx_record_decl->getDeclName(), parm_list, cxx_record_decl,
          /* AssociatedConstraints */ nullptr);

  cxx_record_decl->setDescribedClassTemplate(class_template_decl);
  class_template_decl->setInvalidDecl(true);

  return class_template_decl;
}

clang::NamespaceDecl *
FakeDeclSource::CreateNamespaceDecl(const clang::DeclarationName &name,
                                    clang::DeclContext *decl_context) {
  clang::NamespaceDecl *namespace_decl = clang::NamespaceDecl::Create(
      ci_.getASTContext(), decl_context, /* Inline */ false,
      clang::SourceLocation(), clang::SourceLocation(),
      name.getAsIdentifierInfo(), /* PrevDecl */ nullptr);
  namespace_decl->setInvalidDecl(true);

  return namespace_decl;
}

clang::NamedDecl *
FakeDeclSource::CreateDecl(clang::Sema::LookupNameKind kind,
                           const clang::DeclarationNameInfo &name_info,
                           clang::DeclContext *decl_context) {
  const clang::DeclarationName &name = name_info.getName();
  if (name.getNameKind() != clang::DeclarationName::Identifier) {
    return nullptr;
  }

  clang::NamedDecl *decl;
  switch (kind) {
  case clang::Sema::LookupOrdinaryName:
  case clang::Sema::LookupTagName: {
    clang::CXXRecordDecl *cxx_record_decl =
        CreateCXXRecordDecl(name, decl_context);
    // If `<` follows the type name, the type must be a template.
    // Otherwise, the compiler takes it as a syntax error.
    const clang::Token &next_token = ci_.getPreprocessor().LookAhead(0);
    if (next_token.is(clang::tok::less)) {
      decl = CreateClassTemplateDecl(cxx_record_decl, decl_context);
    } else {
      decl = cxx_record_decl;
    }
    break;
  }
  case clang::Sema::LookupNestedNameSpecifierName:
    decl = CreateNamespaceDecl(name, decl_context);
    break;
  default:
    decl = nullptr;
  }

  if (decl) {
    decl_context->addDecl(decl);
  }
  return decl;
}

clang::DeclContext *
FakeDeclSource::ResolveDeclContext(clang::DeclContext *member_context,
                                   clang::Scope *scope,
                                   clang::NestedNameSpecifier *nns) {
  if (member_context) {
    return member_context;
  }

  if (nns) {
    switch (nns->getKind()) {
    case clang::NestedNameSpecifier::Namespace:
      return nns->getAsNamespace();
    case clang::NestedNameSpecifier::NamespaceAlias:
      return nns->getAsNamespaceAlias()->getNamespace();
    case clang::NestedNameSpecifier::TypeSpec:
    case clang::NestedNameSpecifier::TypeSpecWithTemplate:
      return nns->getAsRecordDecl();
    case clang::NestedNameSpecifier::Global:
      return ci_.getASTContext().getTranslationUnitDecl();
    case clang::NestedNameSpecifier::Identifier:
    case clang::NestedNameSpecifier::Super:
      break;
    }
  }

  if (scope && scope->getEntity()) {
    return scope->getEntity();
  }

  return ci_.getASTContext().getTranslationUnitDecl();
}

clang::TypoCorrection FakeDeclSource::CorrectTypo(
    const clang::DeclarationNameInfo &typo, int lookup_kind,
    clang::Scope *scope, clang::CXXScopeSpec *scope_spec,
    clang::CorrectionCandidateCallback &ccc, clang::DeclContext *member_context,
    bool entering_context, const clang::ObjCObjectPointerType *opt) {
  // Skip function bodies.
  if (scope && scope->getFnParent()) {
    return clang::TypoCorrection();
  }

  clang::NestedNameSpecifier *nns = nullptr;
  if (scope_spec && !scope_spec->isEmpty()) {
    nns = scope_spec->getScopeRep();
  }

  clang::DeclContext *decl_context =
      ResolveDeclContext(member_context, scope, nns);

  clang::NamedDecl *decl =
      CreateDecl(clang::Sema::LookupNameKind(lookup_kind), typo, decl_context);
  if (decl == nullptr) {
    return clang::TypoCorrection();
  }

  return clang::TypoCorrection(decl, nns);
}

bool FakeDeclSource::LookupUnqualified(clang::LookupResult &result,
                                       clang::Scope *scope) {
  // The compiler looks for redeclaration when it parses a known name.
  if (result.isForRedeclaration()) {
    return false;
  }
  // Skip function bodies.
  if (scope && scope->getFnParent()) {
    return false;
  }

  clang::DeclContext *decl_context;
  if (scope && scope->getEntity()) {
    decl_context = scope->getEntity();
  } else {
    decl_context = ci_.getASTContext().getTranslationUnitDecl();
  }

  clang::NamedDecl *decl = CreateDecl(result.getLookupKind(),
                                      result.getLookupNameInfo(), decl_context);
  if (decl == nullptr) {
    return false;
  }

  result.addDecl(decl);
  result.resolveKind();
  return true;
}
