//===--- RemoveUsingNamespace.cpp --------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "AST.h"
#include "FindTarget.h"
#include "Selection.h"
#include "SourceCode.h"
#include "refactor/Tweak.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
#include "llvm/ADT/ScopeExit.h"

namespace clang {
namespace clangd {
namespace {
/// Removes the 'using namespace' under the cursor and qualifies all accesses in
/// the current file. E.g.,
///   using namespace std;
///   vector<int> foo(std::map<int, int>);
/// Would become:
///   std::vector<int> foo(std::map<int, int>);
/// Currently limited to using namespace directives inside global namespace to
/// simplify implementation. Also the namespace must not contain using
/// directives.
class RemoveUsingNamespace : public Tweak {
public:
  const char *id() const override;

  bool prepare(const Selection &Inputs) override;
  Expected<Effect> apply(const Selection &Inputs) override;
  std::string title() const override;
  Intent intent() const override { return Refactor; }

private:
  const UsingDirectiveDecl *TargetDirective = nullptr;
};
REGISTER_TWEAK(RemoveUsingNamespace)

class FindSameUsings : public RecursiveASTVisitor<FindSameUsings> {
public:
  FindSameUsings(const UsingDirectiveDecl &Target,
                 std::vector<const UsingDirectiveDecl *> &Results)
      : TargetNS(Target.getNominatedNamespace()),
        TargetCtx(Target.getDeclContext()), Results(Results) {}

  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
    if (D->getNominatedNamespace() != TargetNS ||
        D->getDeclContext() != TargetCtx)
      return true;
    Results.push_back(D);
    return true;
  }

private:
  const NamespaceDecl *TargetNS;
  const DeclContext *TargetCtx;
  std::vector<const UsingDirectiveDecl *> &Results;
};

/// Produce edit removing 'using namespace xxx::yyy' and the trailing semicolon.
llvm::Expected<tooling::Replacement>
removeUsingDirective(ASTContext &Ctx, const UsingDirectiveDecl *D) {
  auto &SM = Ctx.getSourceManager();
  llvm::Optional<Token> NextTok =
      Lexer::findNextToken(D->getEndLoc(), SM, Ctx.getLangOpts());
  if (!NextTok || NextTok->isNot(tok::semi))
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "no semicolon after using-directive");
  // FIXME: removing the semicolon may be invalid in some obscure cases, e.g.
  //        if (x) using namespace std; else using namespace bar;
  return tooling::Replacement(
      SM,
      CharSourceRange::getTokenRange(D->getBeginLoc(), NextTok->getLocation()),
      "", Ctx.getLangOpts());
}

// Returns true iff the parent of the Node is a TUDecl.
bool isTopLevelDecl(const SelectionTree::Node *Node) {
  return Node->Parent && Node->Parent->ASTNode.get<TranslationUnitDecl>();
}

// Returns the first visible context that contains this DeclContext.
// For example: Returns ns1 for S1 and a.
// namespace ns1 {
// inline namespace ns2 { struct S1 {}; }
// enum E { a, b, c, d };
// }
const DeclContext *visibleContext(const DeclContext *D) {
  while (D->isInlineNamespace() || D->isTransparentContext())
    D = D->getParent();
  return D;
}

bool RemoveUsingNamespace::prepare(const Selection &Inputs) {
  // Find the 'using namespace' directive under the cursor.
  auto *CA = Inputs.ASTSelection.commonAncestor();
  if (!CA)
    return false;
  TargetDirective = CA->ASTNode.get<UsingDirectiveDecl>();
  if (!TargetDirective)
    return false;
  if (!dyn_cast<Decl>(TargetDirective->getDeclContext()))
    return false;
  // FIXME: Unavailable for namespaces containing using-namespace decl.
  // It is non-trivial to deal with cases where identifiers come from the inner
  // namespace. For example map has to be changed to aa::map.
  // namespace aa {
  //   namespace bb { struct map {}; }
  //   using namespace bb;
  // }
  // using namespace a^a;
  // int main() { map m; }
  // We need to make this aware of the transitive using-namespace decls.
  if (!TargetDirective->getNominatedNamespace()->using_directives().empty())
    return false;
  return isTopLevelDecl(CA);
}

Expected<Tweak::Effect> RemoveUsingNamespace::apply(const Selection &Inputs) {
  auto &Ctx = Inputs.AST.getASTContext();
  auto &SM = Ctx.getSourceManager();
  // First, collect *all* using namespace directives that redeclare the same
  // namespace.
  std::vector<const UsingDirectiveDecl *> AllDirectives;
  FindSameUsings(*TargetDirective, AllDirectives).TraverseAST(Ctx);

  SourceLocation FirstUsingDirectiveLoc;
  for (auto *D : AllDirectives) {
    if (FirstUsingDirectiveLoc.isInvalid() ||
        SM.isBeforeInTranslationUnit(D->getBeginLoc(), FirstUsingDirectiveLoc))
      FirstUsingDirectiveLoc = D->getBeginLoc();
  }

  // Collect all references to symbols from the namespace for which we're
  // removing the directive.
  std::vector<SourceLocation> IdentsToQualify;
  for (auto &D : Inputs.AST.getLocalTopLevelDecls()) {
    findExplicitReferences(D, [&](ReferenceLoc Ref) {
      if (Ref.Qualifier)
        return; // This reference is already qualified.

      for (auto *T : Ref.Targets) {
        if (!visibleContext(T->getDeclContext())
                 ->Equals(TargetDirective->getNominatedNamespace()))
          return;
      }
      SourceLocation Loc = Ref.NameLoc;
      if (Loc.isMacroID()) {
        // Avoid adding qualifiers before macro expansions, it's probably
        // incorrect, e.g.
        //   namespace std { int foo(); }
        //   #define FOO 1 + foo()
        //   using namespace foo; // provides matrix
        //   auto x = FOO; // Must not changed to auto x = std::FOO
        if (!SM.isMacroArgExpansion(Loc))
          return; // FIXME: report a warning to the users.
        Loc = SM.getFileLoc(Ref.NameLoc);
      }
      assert(Loc.isFileID());
      if (SM.getFileID(Loc) != SM.getMainFileID())
        return; // FIXME: report these to the user as warnings?
      if (SM.isBeforeInTranslationUnit(Loc, FirstUsingDirectiveLoc))
        return; // Directive was not visible before this point.
      IdentsToQualify.push_back(Loc);
    });
  }
  // Remove duplicates.
  llvm::sort(IdentsToQualify);
  IdentsToQualify.erase(
      std::unique(IdentsToQualify.begin(), IdentsToQualify.end()),
      IdentsToQualify.end());

  // Produce replacements to remove the using directives.
  tooling::Replacements R;
  for (auto *D : AllDirectives) {
    auto RemoveUsing = removeUsingDirective(Ctx, D);
    if (!RemoveUsing)
      return RemoveUsing.takeError();
    if (auto Err = R.add(*RemoveUsing))
      return std::move(Err);
  }
  // Produce replacements to add the qualifiers.
  std::string Qualifier = printUsingNamespaceName(Ctx, *TargetDirective) + "::";
  for (auto Loc : IdentsToQualify) {
    if (auto Err = R.add(tooling::Replacement(Ctx.getSourceManager(), Loc,
                                              /*Length=*/0, Qualifier)))
      return std::move(Err);
  }
  return Effect::mainFileEdit(SM, std::move(R));
}

std::string RemoveUsingNamespace::title() const {
  return llvm::formatv("Remove using namespace, re-qualify names instead.");
}
} // namespace
} // namespace clangd
} // namespace clang
