This revision was automatically updated to reflect the committed changes.
Closed by commit rG69e5abb57b70: [libclang] Add CXRewriter to libclang API 
(authored by jkorous).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D86992?vs=289837&id=290027#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86992

Files:
  clang/include/clang-c/Rewrite.h
  clang/tools/libclang/CMakeLists.txt
  clang/tools/libclang/Rewrite.cpp
  clang/tools/libclang/libclang.exports
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===================================================================
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang-c/Index.h"
+#include "clang-c/Rewrite.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileSystem.h"
@@ -842,3 +843,90 @@
       },
       nullptr);
 }
+class LibclangRewriteTest : public LibclangParseTest {
+public:
+  CXRewriter Rew = nullptr;
+  std::string Filename;
+  CXFile File = nullptr;
+
+  void SetUp() override {
+    LibclangParseTest::SetUp();
+    Filename = "file.cpp";
+    WriteFile(Filename, "int main() { return 0; }");
+    ClangTU = clang_parseTranslationUnit(Index, Filename.c_str(), nullptr, 0,
+                                         nullptr, 0, TUFlags);
+    Rew = clang_CXRewriter_create(ClangTU);
+    File = clang_getFile(ClangTU, Filename.c_str());
+  }
+  void TearDown() override {
+    clang_CXRewriter_dispose(Rew);
+    LibclangParseTest::TearDown();
+  }
+};
+
+static std::string getFileContent(const std::string& Filename) {
+  std::ifstream RewrittenFile(Filename);
+  std::string RewrittenFileContent;
+  std::string Line;
+  while (std::getline(RewrittenFile, Line)) {
+    if (RewrittenFileContent.empty())
+      RewrittenFileContent = Line;
+    else {
+      RewrittenFileContent += "\n" + Line;
+    }
+  }
+  return RewrittenFileContent;
+}
+
+TEST_F(LibclangRewriteTest, RewriteReplace) {
+  CXSourceLocation B = clang_getLocation(ClangTU, File, 1, 5);
+  CXSourceLocation E = clang_getLocation(ClangTU, File, 1, 9);
+  CXSourceRange Rng	= clang_getRange(B, E);
+
+  clang_CXRewriter_replaceText(Rew, Rng, "MAIN");
+
+  ASSERT_EQ(clang_CXRewriter_overwriteChangedFiles(Rew), 0);
+  EXPECT_EQ(getFileContent(Filename), "int MAIN() { return 0; }");
+}
+
+TEST_F(LibclangRewriteTest, RewriteReplaceShorter) {
+  CXSourceLocation B = clang_getLocation(ClangTU, File, 1, 5);
+  CXSourceLocation E = clang_getLocation(ClangTU, File, 1, 9);
+  CXSourceRange Rng	= clang_getRange(B, E);
+
+  clang_CXRewriter_replaceText(Rew, Rng, "foo");
+
+  ASSERT_EQ(clang_CXRewriter_overwriteChangedFiles(Rew), 0);
+  EXPECT_EQ(getFileContent(Filename), "int foo() { return 0; }");
+}
+
+TEST_F(LibclangRewriteTest, RewriteReplaceLonger) {
+  CXSourceLocation B = clang_getLocation(ClangTU, File, 1, 5);
+  CXSourceLocation E = clang_getLocation(ClangTU, File, 1, 9);
+  CXSourceRange Rng	= clang_getRange(B, E);
+
+  clang_CXRewriter_replaceText(Rew, Rng, "patatino");
+
+  ASSERT_EQ(clang_CXRewriter_overwriteChangedFiles(Rew), 0);
+  EXPECT_EQ(getFileContent(Filename), "int patatino() { return 0; }");
+}
+
+TEST_F(LibclangRewriteTest, RewriteInsert) {
+  CXSourceLocation Loc = clang_getLocation(ClangTU, File, 1, 5);
+
+  clang_CXRewriter_insertTextBefore(Rew, Loc, "ro");
+
+  ASSERT_EQ(clang_CXRewriter_overwriteChangedFiles(Rew), 0);
+  EXPECT_EQ(getFileContent(Filename), "int romain() { return 0; }");
+}
+
+TEST_F(LibclangRewriteTest, RewriteRemove) {
+  CXSourceLocation B = clang_getLocation(ClangTU, File, 1, 5);
+  CXSourceLocation E = clang_getLocation(ClangTU, File, 1, 9);
+  CXSourceRange Rng	= clang_getRange(B, E);
+
+  clang_CXRewriter_removeText(Rew, Rng);
+
+  ASSERT_EQ(clang_CXRewriter_overwriteChangedFiles(Rew), 0);
+  EXPECT_EQ(getFileContent(Filename), "int () { return 0; }");
+}
Index: clang/tools/libclang/libclang.exports
===================================================================
--- clang/tools/libclang/libclang.exports
+++ clang/tools/libclang/libclang.exports
@@ -385,3 +385,10 @@
 clang_Cursor_getVarDeclInitializer
 clang_Cursor_hasVarDeclGlobalStorage
 clang_Cursor_hasVarDeclExternalStorage
+clang_CXRewriter_create
+clang_CXRewriter_insertTextBefore
+clang_CXRewriter_replaceText
+clang_CXRewriter_removeText
+clang_CXRewriter_overwriteChangedFiles
+clang_CXRewriter_writeMainFileToStdOut
+clang_CXRewriter_dispose
Index: clang/tools/libclang/Rewrite.cpp
===================================================================
--- /dev/null
+++ clang/tools/libclang/Rewrite.cpp
@@ -0,0 +1,63 @@
+//===- Rewrite.cpp --------------------------------------------------------===//
+//
+// 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 "clang-c/Rewrite.h"
+#include "CXSourceLocation.h"
+#include "CXTranslationUnit.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+
+CXRewriter clang_CXRewriter_create(CXTranslationUnit TU) {
+  if (clang::cxtu::isNotUsableTU(TU)) {
+    LOG_BAD_TU(TU);
+    return {};
+  }
+  clang::ASTUnit *AU = clang::cxtu::getASTUnit(TU);
+  assert(AU);
+  return reinterpret_cast<CXRewriter>(
+      new clang::Rewriter(AU->getSourceManager(), AU->getLangOpts()));
+}
+
+void clang_CXRewriter_insertTextBefore(CXRewriter Rew, CXSourceLocation Loc,
+                            const char *Insert) {
+  assert(Rew);
+  clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+  R.InsertTextBefore(clang::cxloc::translateSourceLocation(Loc), Insert);
+}
+
+void clang_CXRewriter_replaceText(CXRewriter Rew, CXSourceRange ToBeReplaced,
+                       const char *Replacement) {
+  assert(Rew);
+  clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+  R.ReplaceText(clang::cxloc::translateCXRangeToCharRange(ToBeReplaced),
+                Replacement);
+}
+
+void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved) {
+  assert(Rew);
+  clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+  R.RemoveText(clang::cxloc::translateCXRangeToCharRange(ToBeRemoved));
+}
+
+int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew) {
+  assert(Rew);
+  clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+  return R.overwriteChangedFiles();
+}
+
+void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew) {
+  assert(Rew);
+  clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+  R.getEditBuffer(R.getSourceMgr().getMainFileID()).write(llvm::outs());
+}
+
+void clang_CXRewriter_dispose(CXRewriter Rew) {
+  if (Rew)
+    delete reinterpret_cast<clang::Rewriter *>(Rew);
+}
Index: clang/tools/libclang/CMakeLists.txt
===================================================================
--- clang/tools/libclang/CMakeLists.txt
+++ clang/tools/libclang/CMakeLists.txt
@@ -20,6 +20,7 @@
   CXType.cpp
   Indexing.cpp
   FatalErrorHandler.cpp
+  Rewrite.cpp
 
   ADDITIONAL_HEADERS
   CIndexDiagnostic.h
Index: clang/include/clang-c/Rewrite.h
===================================================================
--- /dev/null
+++ clang/include/clang-c/Rewrite.h
@@ -0,0 +1,63 @@
+/*===-- clang-c/Rewrite.h - C CXRewriter   --------------------------*- 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                    *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_REWRITE_H
+#define LLVM_CLANG_C_REWRITE_H
+
+#include "clang-c/CXString.h"
+#include "clang-c/ExternC.h"
+#include "clang-c/Index.h"
+#include "clang-c/Platform.h"
+
+LLVM_CLANG_C_EXTERN_C_BEGIN
+
+typedef void *CXRewriter;
+
+/**
+ * Create CXRewriter.
+ */
+CINDEX_LINKAGE CXRewriter clang_CXRewriter_create(CXTranslationUnit TU);
+
+/**
+ * Insert the specified string at the specified location in the original buffer.
+ */
+CINDEX_LINKAGE void clang_CXRewriter_insertTextBefore(CXRewriter Rew, CXSourceLocation Loc,
+                                           const char *Insert);
+
+/**
+ * Replace the specified range of characters in the input with the specified
+ * replacement.
+ */
+CINDEX_LINKAGE void clang_CXRewriter_replaceText(CXRewriter Rew, CXSourceRange ToBeReplaced,
+                                      const char *Replacement);
+
+/**
+ * Remove the specified range.
+ */
+CINDEX_LINKAGE void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved);
+
+/**
+ * Save all changed files to disk.
+ * Returns 1 if any files were not saved successfully, returns 0 otherwise.
+ */
+CINDEX_LINKAGE int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew);
+
+/**
+ * Write out rewritten version of the main file to stdout.
+ */
+CINDEX_LINKAGE void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew);
+
+/**
+ * Free the given CXRewriter.
+ */
+CINDEX_LINKAGE void clang_CXRewriter_dispose(CXRewriter Rew);
+
+LLVM_CLANG_C_EXTERN_C_END
+
+#endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to