[cfe-commits] r172219 - in /cfe/trunk: include/clang/Rewrite/Core/Rewriter.h include/clang/Tooling/Refactoring.h include/clang/Tooling/Tooling.h lib/Tooling/Refactoring.cpp

Edwin Vane edwin.vane at intel.com
Fri Jan 11 09:04:55 PST 2013


Author: revane
Date: Fri Jan 11 11:04:55 2013
New Revision: 172219

URL: http://llvm.org/viewvc/llvm-project?rev=172219&view=rev
Log:
Allow RefactoringTool to write to memory instead of always to disk
    
RefactoringTool::run() always writes the result of rewrites to disk.
Instead, make this optional and provide a method for getting the
refactoring results in a memory buffer instead.

Also made ClangTool polymorphic so RefactoringTool could inherit from it
to properly express the IS-A relationship. This change also provides
access to ClangTool's public interface, e.g. mapVirtualFile() which is
important once refactored buffers start living in memory instead of on
disk.

Reviewers: klimek


Modified:
    cfe/trunk/include/clang/Rewrite/Core/Rewriter.h
    cfe/trunk/include/clang/Tooling/Refactoring.h
    cfe/trunk/include/clang/Tooling/Tooling.h
    cfe/trunk/lib/Tooling/Refactoring.cpp

Modified: cfe/trunk/include/clang/Rewrite/Core/Rewriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Rewrite/Core/Rewriter.h?rev=172219&r1=172218&r2=172219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Rewrite/Core/Rewriter.h (original)
+++ cfe/trunk/include/clang/Rewrite/Core/Rewriter.h Fri Jan 11 11:04:55 2013
@@ -52,7 +52,11 @@
   iterator end() const { return Buffer.end(); }
   unsigned size() const { return Buffer.size(); }
 
-  raw_ostream &write(raw_ostream &) const;
+  /// \brief Write to \p Stream the result of applying all changes to the
+  /// original buffer.
+  ///
+  /// The original buffer is not actually changed.
+  raw_ostream &write(raw_ostream &Stream) const;
 
   /// RemoveText - Remove the specified text.
   void RemoveText(unsigned OrigOffset, unsigned Size,

Modified: cfe/trunk/include/clang/Tooling/Refactoring.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring.h?rev=172219&r1=172218&r2=172219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring.h Fri Jan 11 11:04:55 2013
@@ -105,35 +105,48 @@
 /// FIXME: Change to a vector and deduplicate in the RefactoringTool.
 typedef std::set<Replacement, Replacement::Less> Replacements;
 
-/// \brief Apply all replacements on the Rewriter.
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
 ///
-/// If at least one Apply returns false, ApplyAll returns false. Every
-/// Apply will be executed independently of the result of other
-/// Apply operations.
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
 bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite);
 
 /// \brief A tool to run refactorings.
 ///
-/// This is a refactoring specific version of \see ClangTool.
-/// All text replacements added to getReplacements() during the run of the
-/// tool will be applied and saved after all translation units have been
-/// processed.
-class RefactoringTool {
+/// This is a refactoring specific version of \see ClangTool. FrontendActions
+/// passed to run() and runAndSave() should add replacements to
+/// getReplacements().
+class RefactoringTool : public ClangTool {
 public:
   /// \see ClangTool::ClangTool.
   RefactoringTool(const CompilationDatabase &Compilations,
                   ArrayRef<std::string> SourcePaths);
 
-  /// \brief Returns a set of replacements. All replacements added during the
-  /// run of the tool will be applied after all translation units have been
-  /// processed.
+  /// \brief Returns the set of replacements to which replacements should
+  /// be added during the run of the tool.
   Replacements &getReplacements();
 
-  /// \see ClangTool::run.
-  int run(FrontendActionFactory *ActionFactory);
+  /// \brief Call run(), apply all generated replacements, and immediately save
+  /// the results to disk.
+  ///
+  /// \returns 0 upon success. Non-zero upon failure.
+  int runAndSave(FrontendActionFactory *ActionFactory);
+
+  /// \brief Apply all stored replacements to the given Rewriter.
+  ///
+  /// Replacement applications happen independently of the success of other
+  /// applications.
+  ///
+  /// \returns true if all replacements apply. false otherwise.
+  bool applyAllReplacements(Rewriter &Rewrite);
+
+private:
+  /// \brief Write all refactored files to disk.
+  int saveRewrittenFiles(Rewriter &Rewrite);
 
 private:
-  ClangTool Tool;
   Replacements Replace;
 };
 
@@ -149,4 +162,3 @@
 } // end namespace clang
 
 #endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H
-

Modified: cfe/trunk/include/clang/Tooling/Tooling.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Tooling.h?rev=172219&r1=172218&r2=172219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Tooling.h (original)
+++ cfe/trunk/include/clang/Tooling/Tooling.h Fri Jan 11 11:04:55 2013
@@ -179,6 +179,8 @@
   ClangTool(const CompilationDatabase &Compilations,
             ArrayRef<std::string> SourcePaths);
 
+  virtual ~ClangTool() {}
+
   /// \brief Map a virtual file to be used while running the tool.
   ///
   /// \param FilePath The path at which the content will be mapped.
@@ -195,7 +197,7 @@
   /// \param ActionFactory Factory generating the frontend actions. The function
   /// takes ownership of this parameter. A new action is generated for every
   /// processed translation unit.
-  int run(FrontendActionFactory *ActionFactory);
+  virtual int run(FrontendActionFactory *ActionFactory);
 
   /// \brief Returns the file manager used in the tool.
   ///

Modified: cfe/trunk/lib/Tooling/Refactoring.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring.cpp?rev=172219&r1=172218&r2=172219&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring.cpp Fri Jan 11 11:04:55 2013
@@ -135,50 +135,55 @@
   return Result;
 }
 
-bool saveRewrittenFiles(Rewriter &Rewrite) {
-  for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(),
-                                 E = Rewrite.buffer_end();
-       I != E; ++I) {
-    // FIXME: This code is copied from the FixItRewriter.cpp - I think it should
-    // go into directly into Rewriter (there we also have the Diagnostics to
-    // handle the error cases better).
-    const FileEntry *Entry =
-        Rewrite.getSourceMgr().getFileEntryForID(I->first);
-    std::string ErrorInfo;
-    llvm::raw_fd_ostream FileStream(
-        Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary);
-    if (!ErrorInfo.empty())
-      return false;
-    I->second.write(FileStream);
-    FileStream.flush();
-  }
-  return true;
-}
-
 RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations,
                                  ArrayRef<std::string> SourcePaths)
-  : Tool(Compilations, SourcePaths) {}
+  : ClangTool(Compilations, SourcePaths) {}
 
 Replacements &RefactoringTool::getReplacements() { return Replace; }
 
-int RefactoringTool::run(FrontendActionFactory *ActionFactory) {
-  int Result = Tool.run(ActionFactory);
+int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
+  if (int Result = run(ActionFactory)) {
+    return Result;
+  }
+
   LangOptions DefaultLangOptions;
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
   TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
   DiagnosticsEngine Diagnostics(
       llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
       &*DiagOpts, &DiagnosticPrinter, false);
-  SourceManager Sources(Diagnostics, Tool.getFiles());
+  SourceManager Sources(Diagnostics, getFiles());
   Rewriter Rewrite(Sources, DefaultLangOptions);
-  if (!applyAllReplacements(Replace, Rewrite)) {
+
+  if (!applyAllReplacements(Rewrite)) {
     llvm::errs() << "Skipped some replacements.\n";
   }
-  if (!saveRewrittenFiles(Rewrite)) {
-    llvm::errs() << "Could not save rewritten files.\n";
-    return 1;
+
+  return saveRewrittenFiles(Rewrite);
+}
+
+bool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) {
+  return tooling::applyAllReplacements(Replace, Rewrite);
+}
+
+int RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) {
+  for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(),
+                                 E = Rewrite.buffer_end();
+       I != E; ++I) {
+    // FIXME: This code is copied from the FixItRewriter.cpp - I think it should
+    // go into directly into Rewriter (there we also have the Diagnostics to
+    // handle the error cases better).
+    const FileEntry *Entry =
+        Rewrite.getSourceMgr().getFileEntryForID(I->first);
+    std::string ErrorInfo;
+    llvm::raw_fd_ostream FileStream(
+        Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary);
+    if (!ErrorInfo.empty())
+      return 1;
+    I->second.write(FileStream);
+    FileStream.flush();
   }
-  return Result;
+  return 0;
 }
 
 } // end namespace tooling





More information about the cfe-commits mailing list