hokein updated this revision to Diff 185941.
hokein added a comment.

Update


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D57943

Files:
  clangd/refactor/tweaks/CMakeLists.txt
  clangd/refactor/tweaks/ClangTidy.cpp
  unittests/clangd/TweakTests.cpp

Index: unittests/clangd/TweakTests.cpp
===================================================================
--- unittests/clangd/TweakTests.cpp
+++ unittests/clangd/TweakTests.cpp
@@ -217,6 +217,23 @@
   )cpp");
 }
 
+TEST(TweakTest, ConvertTypedef) {
+  llvm::StringLiteral ID = "ConvertTypedef";
+  checkAvailable(ID, R"cpp(^t^y^p^e^d^e^f^ int ^F^o^o;)cpp");
+  llvm::StringLiteral Input = "^typedef int Foo;";
+  llvm::StringLiteral Output = "using Foo = int;";
+  checkTransform(ID, Input, Output);
+}
+
+TEST(TweakTest, UseAuto) {
+  llvm::StringLiteral ID = "UseAuto";
+  llvm::StringLiteral Input =
+      "void f() { [[unsigned c = static_cast<unsigned>(1);]] }";
+  llvm::StringLiteral Output =
+      "void f() { auto c = static_cast<unsigned>(1); }";
+  checkTransform(ID, Input, Output);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/refactor/tweaks/ClangTidy.cpp
===================================================================
--- /dev/null
+++ clangd/refactor/tweaks/ClangTidy.cpp
@@ -0,0 +1,149 @@
+//===--- ClangTidy.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 "ClangdUnit.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
+#include "../clang-tidy/modernize/UseUsingCheck.h"
+#include "../clang-tidy/modernize/UseAutoCheck.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+bool isInsideMainFile(const SourceLocation Loc, const SourceManager &M) {
+  return Loc.isValid() && M.isWrittenInMainFile(M.getFileLoc(Loc));
+}
+
+struct StoreClangTidyDiags : public DiagnosticConsumer {
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override {
+    assert(Info.hasSourceManager() && "Diagnostic must have SourceManager");
+    if (Info.getNumFixItHints() > 0)
+      DiagsWithFixIt.push_back(Info);
+  }
+  std::vector<clang::Diagnostic> DiagsWithFixIt;
+};
+
+/// An interface for clang-tidy-based Tweaks. The tweak will run a clang-tidy
+/// check over on an AST node under the cursor. It is designed for simple
+/// refactoring-like clang-tidy checks.
+/// Limitations:
+///    - checks only match single AST node would work
+///    - checks don't see any preprocessor events
+///    - no check options are supported yet
+class ClangTidyTweak : public Tweak {
+public:
+  ClangTidyTweak()
+      : DiagsEng(new clang::DiagnosticIDs(), new clang::DiagnosticOptions(),
+                 &ClangTidyDiags, /*ShouldOwnClient=*/false) {}
+
+  virtual std::unique_ptr<tidy::ClangTidyCheck>
+  createCheck(tidy::ClangTidyContext *) = 0;
+
+  bool prepare(const Selection &Inputs) override;
+
+protected:
+  Expected<tooling::Replacements> execute(const Selection &Inputs) override;
+
+  StoreClangTidyDiags ClangTidyDiags;
+  DiagnosticsEngine DiagsEng; // Extend the lifetime of Diagnostics.
+};
+
+bool ClangTidyTweak::prepare(const Selection &Inputs) {
+  if (!Inputs.ASTSelection.commonAncestor())
+    return false;
+  if (Inputs.AST.getASTContext().getDiagnostics().hasErrorOccurred())
+    return false;
+  DiagsEng.setSourceManager(&Inputs.AST.getASTContext().getSourceManager());
+  tidy::ClangTidyContext CTContext(
+      llvm::make_unique<tidy::DefaultOptionsProvider>(
+          tidy::ClangTidyGlobalOptions(),
+          tidy::ClangTidyOptions::getDefaults()));
+  CTContext.setDiagnosticsEngine(&DiagsEng);
+  CTContext.setASTContext(&Inputs.AST.getASTContext());
+
+  auto Check = createCheck(&CTContext);
+  ast_matchers::MatchFinder CTFinder;
+  Check->registerMatchers(&CTFinder);
+  // Run the check on the AST node under the cursor.
+  CTFinder.match(Inputs.ASTSelection.commonAncestor()->ASTNode,
+                 Inputs.AST.getASTContext());
+  return !ClangTidyDiags.DiagsWithFixIt.empty();
+}
+
+Expected<tooling::Replacements>
+ClangTidyTweak::execute(const Selection &Inputs) {
+  tooling::Replacements FixReplacements;
+  for (const auto &Diag : ClangTidyDiags.DiagsWithFixIt) {
+    for (auto &FixIt : Diag.getFixItHints()) {
+      if (!isInsideMainFile(FixIt.RemoveRange.getBegin(),
+                            Diag.getSourceManager()))
+        continue;
+      tooling::Replacement Fix(Diag.getSourceManager(), FixIt.RemoveRange,
+                               FixIt.CodeToInsert);
+
+      llvm::Error Err = FixReplacements.add(Fix);
+      if (Err)
+        return std::move(Err);
+    }
+  }
+  return FixReplacements;
+}
+
+/// Convert typedef to using.
+/// Before:
+///   typedef int Foo;
+///   ^^^^^^^     ^^^
+/// After:
+///   using Foo = int;
+class ConvertTypedef : public ClangTidyTweak {
+public:
+  const char *id() const override final;
+
+  std::unique_ptr<tidy::ClangTidyCheck>
+  createCheck(tidy::ClangTidyContext *Context) override {
+    return llvm::make_unique<tidy::modernize::UseUsingCheck>(
+        "modernize-use-using", Context);
+  }
+
+  std::string title() const override { return "Convert typedef to using"; }
+};
+
+/// Use auto.
+/// Before:
+///  [[std::vector<int>::iterator I = my_container.begin();]]
+/// After
+///  auto I = my_container.begin();
+class UseAuto : public ClangTidyTweak {
+public:
+  const char *id() const override final;
+
+  std::unique_ptr<tidy::ClangTidyCheck>
+  createCheck(tidy::ClangTidyContext *Context) override {
+    return llvm::make_unique<tidy::modernize::UseAutoCheck>(
+        "modernize-use-auto", Context);
+  }
+
+  std::string title() const override { return "Covert type to auto"; }
+};
+
+REGISTER_TWEAK(ConvertTypedef);
+REGISTER_TWEAK(UseAuto);
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clangd/refactor/tweaks/CMakeLists.txt
===================================================================
--- clangd/refactor/tweaks/CMakeLists.txt
+++ clangd/refactor/tweaks/CMakeLists.txt
@@ -13,6 +13,7 @@
 # clangd/tool/CMakeLists.txt for an example.
 add_clang_library(clangDaemonTweaks OBJECT
   SwapIfBranches.cpp
+  ClangTidy.cpp
 
   LINK_LIBS
   clangAST
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to