[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-10-16 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov abandoned this revision.
ilya-biryukov added a comment.

This was finalized and landed as D68562 


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-29 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 184043.
ilya-biryukov added a comment.

- Update license header


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp

Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,203 @@
+//===--- 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 "ClangdUnit.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/RecursiveASTVisitor.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 foo(std::map);
+/// Would become:
+///   std::vector foo(std::map);
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() const override;
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+for (auto R : NameRanges) {
+  if (!Ctx.getSourceManager().isWrittenInMainFile(R.getBegin()))
+continue; // we can't fix refences outside our file.
+  // FIXME: this might be a conflict that we need to report.
+  ResultIdents.push_back(R.getBegin());
+}
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+if (!Ctx.getSourceManager().isWrittenInMainFile(D->getLocation()) &&
+!isa(D))
+  return true; // skip decls outside main file.
+return RecursiveSymbolVisitor::TraverseDecl(D);
+  }
+
+private:
+  ASTContext 
+  NamespaceDecl 
+  std::vector 
+};
+
+// Produces an edit to remove 'using namespace xxx::yyy' and the trailing
+// semicolon.
+llvm::Expected
+removeUsingDirective(ASTContext , UsingDirectiveDecl *D) {
+  auto  = Ctx.getSourceManager();
+  auto R =
+  Lexer::getAsCharRange(D->getSourceRange(), SrcMgr, Ctx.getLangOpts());
+  if (R.isInvalid())
+

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-22 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182873.
ilya-biryukov added a comment.

- Rebase


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp

Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,204 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/RecursiveASTVisitor.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 foo(std::map);
+/// Would become:
+///   std::vector foo(std::map);
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() const override;
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+for (auto R : NameRanges) {
+  if (!Ctx.getSourceManager().isWrittenInMainFile(R.getBegin()))
+continue; // we can't fix refences outside our file.
+  // FIXME: this might be a conflict that we need to report.
+  ResultIdents.push_back(R.getBegin());
+}
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+if (!Ctx.getSourceManager().isWrittenInMainFile(D->getLocation()) &&
+!isa(D))
+  return true; // skip decls outside main file.
+return RecursiveSymbolVisitor::TraverseDecl(D);
+  }
+
+private:
+  ASTContext 
+  NamespaceDecl 
+  std::vector 
+};
+
+// Produces an edit to remove 'using namespace xxx::yyy' and the trailing
+// semicolon.
+llvm::Expected
+removeUsingDirective(ASTContext , UsingDirectiveDecl *D) {
+  auto  = Ctx.getSourceManager();
+  auto R =
+  Lexer::getAsCharRange(D->getSourceRange(), SrcMgr, Ctx.getLangOpts());
+  if (R.isInvalid())
+return 

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-18 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182547.
ilya-biryukov added a comment.

- Move to the monorepo


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp

Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,206 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/RecursiveASTVisitor.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 foo(std::map);
+/// Would become:
+///   std::vector foo(std::map);
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() const override {
+return llvm::StringLiteral("remove-using-namespace");
+  }
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+for (auto R : NameRanges) {
+  if (!Ctx.getSourceManager().isWrittenInMainFile(R.getBegin()))
+continue; // we can't fix refences outside our file.
+  // FIXME: this might be a conflict that we need to report.
+  ResultIdents.push_back(R.getBegin());
+}
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+if (!Ctx.getSourceManager().isWrittenInMainFile(D->getLocation()) &&
+!isa(D))
+  return true; // skip decls outside main file.
+return RecursiveSymbolVisitor::TraverseDecl(D);
+  }
+
+private:
+  ASTContext 
+  NamespaceDecl 
+  std::vector 
+};
+
+// Produces an edit to remove 'using namespace xxx::yyy' and the trailing
+// semicolon.
+llvm::Expected
+removeUsingDirective(ASTContext , UsingDirectiveDecl *D) {
+  auto  = Ctx.getSourceManager();
+  auto R =
+  Lexer::getAsCharRange(D->getSourceRange(), SrcMgr, 

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-17 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182322.
ilya-biryukov added a comment.

- Remove the header file


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clangd/AST.cpp
  clangd/AST.h
  clangd/refactor/tweaks/CMakeLists.txt
  clangd/refactor/tweaks/RemoveUsingNamespace.cpp

Index: clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,206 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/RecursiveASTVisitor.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 foo(std::map);
+/// Would become:
+///   std::vector foo(std::map);
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() const override {
+return llvm::StringLiteral("remove-using-namespace");
+  }
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+for (auto R : NameRanges) {
+  if (!Ctx.getSourceManager().isWrittenInMainFile(R.getBegin()))
+continue; // we can't fix refences outside our file.
+  // FIXME: this might be a conflict that we need to report.
+  ResultIdents.push_back(R.getBegin());
+}
+return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+if (!Ctx.getSourceManager().isWrittenInMainFile(D->getLocation()) &&
+!isa(D))
+  return true; // skip decls outside main file.
+return RecursiveSymbolVisitor::TraverseDecl(D);
+  }
+
+private:
+  ASTContext 
+  NamespaceDecl 
+  std::vector 
+};
+
+// Produces an edit to remove 'using namespace xxx::yyy' and the trailing
+// semicolon.
+llvm::Expected
+removeUsingDirective(ASTContext , UsingDirectiveDecl *D) {
+  auto  = Ctx.getSourceManager();
+  auto R =
+  Lexer::getAsCharRange(D->getSourceRange(), SrcMgr, Ctx.getLangOpts());
+  if (R.isInvalid())
+return 

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-17 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182318.
ilya-biryukov added a comment.

- Update to reflect changes in parent revision


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clangd/AST.cpp
  clangd/AST.h
  clangd/refactor/tweaks/CMakeLists.txt
  clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clangd/refactor/tweaks/RemoveUsingNamespace.h

Index: clangd/refactor/tweaks/RemoveUsingNamespace.h
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.h
@@ -0,0 +1,42 @@
+//===--- RemoveUsingNamespace.h --*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+// Removes the 'using namespace' under the cursor and qualifies all accesses in
+// the current file. E.g.,
+//   using namespace std;
+//   vector foo(std::map);
+// Would become:
+//   std::vector foo(std::map);
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+
+#include "refactor/Tweak.h"
+
+namespace clang {
+namespace clangd {
+
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() const override {
+return llvm::StringLiteral("remove-using-namespace");
+  }
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,188 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "RemoveUsingNamespace.h"
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
+#include "llvm/ADT/ScopeExit.h"
+
+namespace clang {
+namespace clangd {
+
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+namespace {
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references 

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-17 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182276.
ilya-biryukov added a comment.

- Rebase after parent change


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clangd/AST.cpp
  clangd/AST.h
  clangd/refactor/tweaks/CMakeLists.txt
  clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clangd/refactor/tweaks/RemoveUsingNamespace.h

Index: clangd/refactor/tweaks/RemoveUsingNamespace.h
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.h
@@ -0,0 +1,42 @@
+//===--- RemoveUsingNamespace.h --*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+// Removes the 'using namespace' under the cursor and qualifies all accesses in 
+// the current file. E.g.,
+//   using namespace std;
+//   vector foo(std::map);
+// Would become:
+//   std::vector foo(std::map);
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+
+#include "refactor/Tweak.h"
+
+namespace clang {
+namespace clangd {
+
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() override {
+return llvm::StringLiteral("remove-using-namespace");
+  }
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,188 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "RemoveUsingNamespace.h"
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
+#include "llvm/ADT/ScopeExit.h"
+
+namespace clang {
+namespace clangd {
+
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+namespace {
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-16 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov updated this revision to Diff 182082.
ilya-biryukov added a comment.

- Update after changes to parent revision


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612

Files:
  clangd/AST.cpp
  clangd/AST.h
  clangd/CMakeLists.txt
  clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clangd/refactor/tweaks/RemoveUsingNamespace.h

Index: clangd/refactor/tweaks/RemoveUsingNamespace.h
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.h
@@ -0,0 +1,42 @@
+//===--- RemoveUsingNamespace.h --*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+// Removes the 'using namespace' under the cursor and qualifies all accesses in 
+// the current file. E.g.,
+//   using namespace std;
+//   vector foo(std::map);
+// Would become:
+//   std::vector foo(std::map);
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_TWEAKS_REMOVEUSINGNAMESPACE_H
+
+#include "refactor/Tweak.h"
+
+namespace clang {
+namespace clangd {
+
+class RemoveUsingNamespace : public Tweak {
+public:
+  TweakID id() override {
+return llvm::StringLiteral("remove-using-namespace");
+  }
+
+  bool prepare(const Selection ) override;
+  Expected apply(const Selection ) override;
+  std::string title() const override;
+
+private:
+  UsingDirectiveDecl *TargetDirective = nullptr;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -0,0 +1,188 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "RemoveUsingNamespace.h"
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
+#include "llvm/ADT/ScopeExit.h"
+
+namespace clang {
+namespace clangd {
+
+REGISTER_TWEAK(RemoveUsingNamespace);
+
+namespace {
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+  

[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-11 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov planned changes to this revision.
ilya-biryukov added a comment.

The most complicated of the sample actions, requires considerable work and 
thorough testing before it can be landed.
Serves the purpose of illustrating how to write the two-stage actions.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56612/new/

https://reviews.llvm.org/D56612



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56612: [clangd] A code action to remove 'using namespace'

2019-01-11 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov created this revision.
ilya-biryukov added a reviewer: sammccall.
Herald added subscribers: kadircet, jfb, arphaman, mgrang, jkorous, MaskRay, 
ioeric, mgorny.

Only available in the source files to fit into the model of single-file
actions. Doing the same in headers would require more complicated
machinery, which is out of scope of code actions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D56612

Files:
  clangd/AST.cpp
  clangd/AST.h
  clangd/CMakeLists.txt
  clangd/CodeActions.cpp
  clangd/refactor/actions/RemoveUsingNamespace.cpp
  clangd/refactor/actions/RemoveUsingNamespace.h

Index: clangd/refactor/actions/RemoveUsingNamespace.h
===
--- /dev/null
+++ clangd/refactor/actions/RemoveUsingNamespace.h
@@ -0,0 +1,32 @@
+//===--- RemoveUsingNamespace.h --*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+// A code action that removes the 'using namespace' under the cursor and
+// qualifies all accesses in the current file. E.g.,
+//   using namespace std;
+//   vector foo(std::map);
+// Would become:
+//   std::vector foo(std::map);
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_REMOVEUSINGNAMESPACE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_REMOVEUSINGNAMESPACE_H
+
+#include "refactor/ActionProvider.h"
+
+namespace clang {
+namespace clangd {
+
+class RemoveUsingNamespace : public ActionProvider {
+  llvm::Optional prepare(const ActionInputs ) override;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clangd/refactor/actions/RemoveUsingNamespace.cpp
===
--- /dev/null
+++ clangd/refactor/actions/RemoveUsingNamespace.cpp
@@ -0,0 +1,189 @@
+//===--- RemoveUsingNamespace.cpp *- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+#include "RemoveUsingNamespace.h"
+#include "AST.h"
+#include "ClangdUnit.h"
+#include "SourceCode.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
+#include "llvm/ADT/ScopeExit.h"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+class FindNodeUnderCursor : public RecursiveASTVisitor {
+public:
+  FindNodeUnderCursor(SourceLocation SearchedLoc, UsingDirectiveDecl *)
+  : SearchedLoc(SearchedLoc), Result(Result) {}
+
+  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+if (D->getUsingLoc() != SearchedLoc)
+  return true;
+
+Result = D;
+return false;
+  }
+
+private:
+  SourceLocation SearchedLoc;
+  UsingDirectiveDecl *
+};
+
+class FindSameUsings : public RecursiveASTVisitor {
+public:
+  FindSameUsings(UsingDirectiveDecl ,
+ std::vector )
+  : 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:
+  NamespaceDecl *TargetNS;
+  DeclContext *TargetCtx;
+  std::vector 
+};
+
+class FindIdentsToQualify
+: public tooling::RecursiveSymbolVisitor {
+public:
+  FindIdentsToQualify(ASTContext , NamespaceDecl ,
+  std::vector )
+  : RecursiveSymbolVisitor(Ctx.getSourceManager(), Ctx.getLangOpts()),
+Ctx(Ctx), TargetNS(TargetNS), ResultIdents(ResultIdents) {}
+
+  bool visitSymbolOccurrence(const NamedDecl *D,
+ llvm::ArrayRef NameRanges) {
+if (!D || D->getCanonicalDecl() == TargetNS.getCanonicalDecl())
+  return true;
+if (!D->getDeclName().isIdentifier() ||
+D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+  return true; // do not add qualifiers for non-idents, e.g. 'operator+'.
+// Check the symbol is unqualified and references something inside our
+// namespace.
+// FIXME: add a check it's unqualified.
+if (!TargetNS.InEnclosingNamespaceSetOf(D->getDeclContext()))
+  return true;
+// FIXME: handle more tricky cases, e.g. we don't need the qualifier if we
+//have the using decls for some entities, we might have qualified
+//references that need updating too.
+for (auto R : NameRanges) {
+