[clang-tools-extra] r287863 - [clang-move] Enable dump all declarations in old header.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 24 02:17:17 PST 2016


Author: hokein
Date: Thu Nov 24 04:17:17 2016
New Revision: 287863

URL: http://llvm.org/viewvc/llvm-project?rev=287863&view=rev
Log:
[clang-move] Enable dump all declarations in old header.

Summary:
* Add -dump_dels option to dump all declarations from old header. It
  will allow clang-move used as a frontend to get declarations from
  header. Further more, this will make debugging stuff easier. Currently only
  class/function types are supported.
* Refactoring code a little bit by creating a ClangMoveContext which
  holds all options for ClangMoveTool, which can simplify the code in
  some degree.

Reviewers: ioeric

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D27059

Modified:
    clang-tools-extra/trunk/clang-move/ClangMove.cpp
    clang-tools-extra/trunk/clang-move/ClangMove.h
    clang-tools-extra/trunk/clang-move/tool/ClangMoveMain.cpp
    clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp

Modified: clang-tools-extra/trunk/clang-move/ClangMove.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-move/ClangMove.cpp?rev=287863&r1=287862&r2=287863&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp (original)
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp Thu Nov 24 04:17:17 2016
@@ -401,15 +401,11 @@ ClangMoveAction::CreateASTConsumer(clang
   return MatchFinder.newASTConsumer();
 }
 
-ClangMoveTool::ClangMoveTool(
-    const MoveDefinitionSpec &MoveSpec,
-    std::map<std::string, tooling::Replacements> &FileToReplacements,
-    llvm::StringRef OriginalRunningDirectory, llvm::StringRef FallbackStyle)
-    : Spec(MoveSpec), FileToReplacements(FileToReplacements),
-      OriginalRunningDirectory(OriginalRunningDirectory),
-      FallbackStyle(FallbackStyle) {
-  if (!Spec.NewHeader.empty())
-    CCIncludes.push_back("#include \"" + Spec.NewHeader + "\"\n");
+ClangMoveTool::ClangMoveTool(ClangMoveContext *const Context,
+                             DeclarationReporter *const Reporter)
+    : Context(Context), Reporter(Reporter) {
+  if (!Context->Spec.NewHeader.empty())
+    CCIncludes.push_back("#include \"" + Context->Spec.NewHeader + "\"\n");
 }
 
 void ClangMoveTool::addRemovedDecl(const MovedDecl &Decl) {
@@ -421,24 +417,10 @@ void ClangMoveTool::addRemovedDecl(const
 }
 
 void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
-  Optional<ast_matchers::internal::Matcher<NamedDecl>> HasAnySymbolNames;
-  for (StringRef SymbolName: Spec.Names) {
-    llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':');
-    const auto HasName = hasName(("::" + GlobalSymbolName).str());
-    HasAnySymbolNames =
-        HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName;
-  }
-  if (!HasAnySymbolNames) {
-    llvm::errs() << "No symbols being moved.\n";
-    return;
-  }
-
-  auto InOldHeader = isExpansionInFile(makeAbsolutePath(Spec.OldHeader));
-  auto InOldCC = isExpansionInFile(makeAbsolutePath(Spec.OldCC));
+  auto InOldHeader =
+      isExpansionInFile(makeAbsolutePath(Context->Spec.OldHeader));
+  auto InOldCC = isExpansionInFile(makeAbsolutePath(Context->Spec.OldCC));
   auto InOldFiles = anyOf(InOldHeader, InOldCC);
-  auto InMovedClass =
-      hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));
-
   auto ForwardDecls =
       cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition())));
 
@@ -448,15 +430,21 @@ void ClangMoveTool::registerMatchers(ast
   // Match all top-level named declarations (e.g. function, variable, enum) in
   // old header, exclude forward class declarations and namespace declarations.
   //
-  // The old header which contains only one declaration being moved and forward
-  // declarations is considered to be moved totally.
+  // We consider declarations inside a class belongs to the class. So these
+  // declarations will be ignored.
   auto AllDeclsInHeader = namedDecl(
       unless(ForwardDecls), unless(namespaceDecl()),
-      unless(usingDirectiveDecl()), // using namespace decl.
+      unless(usingDirectiveDecl()),                 // using namespace decl.
       unless(classTemplateDecl(has(ForwardDecls))), // template forward decl.
       InOldHeader,
-      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
+      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
+      hasDeclContext(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
   Finder->addMatcher(AllDeclsInHeader.bind("decls_in_header"), this);
+
+  // Don't register other matchers when dumping all declarations in header.
+  if (Context->DumpDeclarations)
+    return;
+
   // Match forward declarations in old header.
   Finder->addMatcher(namedDecl(ForwardDecls, InOldHeader).bind("fwd_decl"),
                      this);
@@ -484,6 +472,20 @@ void ClangMoveTool::registerMatchers(ast
 
   // Match static functions/variable definitions which are defined in named
   // namespaces.
+  Optional<ast_matchers::internal::Matcher<NamedDecl>> HasAnySymbolNames;
+  for (StringRef SymbolName : Context->Spec.Names) {
+    llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':');
+    const auto HasName = hasName(("::" + GlobalSymbolName).str());
+    HasAnySymbolNames =
+        HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName;
+  }
+
+  if (!HasAnySymbolNames) {
+    llvm::errs() << "No symbols being moved.\n";
+    return;
+  }
+  auto InMovedClass =
+      hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));
   auto IsOldCCStaticDefinition =
       allOf(isDefinition(), unless(InMovedClass), InOldCCNamedOrGlobalNamespace,
             isStaticStorageClass());
@@ -531,7 +533,7 @@ void ClangMoveTool::run(const ast_matche
     UnremovedDeclsInOldHeader.insert(D);
   } else if (const auto *FWD =
                  Result.Nodes.getNodeAs<clang::CXXRecordDecl>("fwd_decl")) {
-    // Skip all forwad declarations which appear after moved class declaration.
+    // Skip all forward declarations which appear after moved class declaration.
     if (RemovedDecls.empty()) {
       if (const auto *DCT = FWD->getDescribedClassTemplate())
         MovedDecls.emplace_back(DCT, &Result.Context->getSourceManager());
@@ -551,7 +553,7 @@ void ClangMoveTool::run(const ast_matche
 }
 
 std::string ClangMoveTool::makeAbsolutePath(StringRef Path) {
-  return MakeAbsolutePath(OriginalRunningDirectory, Path);
+  return MakeAbsolutePath(Context->OriginalRunningDirectory, Path);
 }
 
 void ClangMoveTool::addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
@@ -561,7 +563,7 @@ void ClangMoveTool::addIncludes(llvm::St
                                 const SourceManager &SM) {
   SmallVector<char, 128> HeaderWithSearchPath;
   llvm::sys::path::append(HeaderWithSearchPath, SearchPath, IncludeHeader);
-  std::string AbsoluteOldHeader = makeAbsolutePath(Spec.OldHeader);
+  std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader);
   // FIXME: Add old.h to the new.cc/h when the new target has dependencies on
   // old.h/c. For instance, when moved class uses another class defined in
   // old.h, the old.h should be added in new.h.
@@ -579,7 +581,7 @@ void ClangMoveTool::addIncludes(llvm::St
   std::string AbsoluteCurrentFile = MakeAbsolutePath(SM, FileName);
   if (AbsoluteOldHeader == AbsoluteCurrentFile) {
     HeaderIncludes.push_back(IncludeLine);
-  } else if (makeAbsolutePath(Spec.OldCC) == AbsoluteCurrentFile) {
+  } else if (makeAbsolutePath(Context->Spec.OldCC) == AbsoluteCurrentFile) {
     CCIncludes.push_back(IncludeLine);
   }
 }
@@ -594,20 +596,22 @@ void ClangMoveTool::removeClassDefinitio
         clang::CharSourceRange::getCharRange(Range.getBegin(), Range.getEnd()),
         "");
     std::string FilePath = RemoveReplacement.getFilePath().str();
-    auto Err = FileToReplacements[FilePath].add(RemoveReplacement);
+    auto Err = Context->FileToReplacements[FilePath].add(RemoveReplacement);
     if (Err)
       llvm::errs() << llvm::toString(std::move(Err)) << "\n";
   }
   const SourceManager* SM = RemovedDecls[0].SM;
 
   // Post process of cleanup around all the replacements.
-  for (auto& FileAndReplacements: FileToReplacements) {
+  for (auto &FileAndReplacements : Context->FileToReplacements) {
     StringRef FilePath = FileAndReplacements.first;
     // Add #include of new header to old header.
-    if (Spec.OldDependOnNew &&
-        MakeAbsolutePath(*SM, FilePath) == makeAbsolutePath(Spec.OldHeader)) {
+    if (Context->Spec.OldDependOnNew &&
+        MakeAbsolutePath(*SM, FilePath) ==
+            makeAbsolutePath(Context->Spec.OldHeader)) {
       // FIXME: Minimize the include path like include-fixer.
-      std::string IncludeNewH = "#include \""  + Spec.NewHeader + "\"\n";
+      std::string IncludeNewH =
+          "#include \"" + Context->Spec.NewHeader + "\"\n";
       // This replacment for inserting header will be cleaned up at the end.
       auto Err = FileAndReplacements.second.add(
           tooling::Replacement(FilePath, UINT_MAX, 0, IncludeNewH));
@@ -620,15 +624,15 @@ void ClangMoveTool::removeClassDefinitio
     if (SI == FilePathToFileID.end()) continue;
     llvm::StringRef Code = SM->getBufferData(SI->second);
     format::FormatStyle Style =
-        format::getStyle("file", FilePath, FallbackStyle);
+        format::getStyle("file", FilePath, Context->FallbackStyle);
     auto CleanReplacements = format::cleanupAroundReplacements(
-        Code, FileToReplacements[FilePath], Style);
+        Code, Context->FileToReplacements[FilePath], Style);
 
     if (!CleanReplacements) {
       llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
       continue;
     }
-    FileToReplacements[FilePath] = *CleanReplacements;
+    Context->FileToReplacements[FilePath] = *CleanReplacements;
   }
 }
 
@@ -636,23 +640,27 @@ void ClangMoveTool::moveClassDefinitionT
   std::vector<MovedDecl> NewHeaderDecls;
   std::vector<MovedDecl> NewCCDecls;
   for (const auto &MovedDecl : MovedDecls) {
-    if (isInHeaderFile(*MovedDecl.SM, MovedDecl.Decl, OriginalRunningDirectory,
-                       Spec.OldHeader))
+    if (isInHeaderFile(*MovedDecl.SM, MovedDecl.Decl,
+                       Context->OriginalRunningDirectory,
+                       Context->Spec.OldHeader))
       NewHeaderDecls.push_back(MovedDecl);
     else
       NewCCDecls.push_back(MovedDecl);
   }
 
-  if (!Spec.NewHeader.empty()) {
+  if (!Context->Spec.NewHeader.empty()) {
     std::string OldHeaderInclude =
-        Spec.NewDependOnOld ? "#include \"" + Spec.OldHeader + "\"\n" : "";
-    FileToReplacements[Spec.NewHeader] = createInsertedReplacements(
-        HeaderIncludes, NewHeaderDecls, Spec.NewHeader, /*IsHeader=*/true,
-        OldHeaderInclude);
-  }
-  if (!Spec.NewCC.empty())
-    FileToReplacements[Spec.NewCC] =
-        createInsertedReplacements(CCIncludes, NewCCDecls, Spec.NewCC);
+        Context->Spec.NewDependOnOld
+            ? "#include \"" + Context->Spec.OldHeader + "\"\n"
+            : "";
+    Context->FileToReplacements[Context->Spec.NewHeader] =
+        createInsertedReplacements(HeaderIncludes, NewHeaderDecls,
+                                   Context->Spec.NewHeader, /*IsHeader=*/true,
+                                   OldHeaderInclude);
+  }
+  if (!Context->Spec.NewCC.empty())
+    Context->FileToReplacements[Context->Spec.NewCC] =
+        createInsertedReplacements(CCIncludes, NewCCDecls, Context->Spec.NewCC);
 }
 
 // Move all contents from OldFile to NewFile.
@@ -669,7 +677,8 @@ void ClangMoveTool::moveAll(SourceManage
   clang::tooling::Replacement RemoveAll (
       SM, clang::CharSourceRange::getCharRange(Begin, End), "");
   std::string FilePath = RemoveAll.getFilePath().str();
-  FileToReplacements[FilePath] = clang::tooling::Replacements(RemoveAll);
+  Context->FileToReplacements[FilePath] =
+      clang::tooling::Replacements(RemoveAll);
 
   StringRef Code = SM.getBufferData(ID);
   if (!NewFile.empty()) {
@@ -677,22 +686,36 @@ void ClangMoveTool::moveAll(SourceManage
         clang::tooling::Replacement(NewFile, 0, 0, Code));
     // If we are moving from old.cc, an extra step is required: excluding
     // the #include of "old.h", instead, we replace it with #include of "new.h".
-    if (Spec.NewCC == NewFile && OldHeaderIncludeRange.isValid()) {
+    if (Context->Spec.NewCC == NewFile && OldHeaderIncludeRange.isValid()) {
       AllCode = AllCode.merge(
           clang::tooling::Replacements(clang::tooling::Replacement(
-              SM, OldHeaderIncludeRange, '"' + Spec.NewHeader + '"')));
+              SM, OldHeaderIncludeRange, '"' + Context->Spec.NewHeader + '"')));
     }
-    FileToReplacements[NewFile] = std::move(AllCode);
+    Context->FileToReplacements[NewFile] = std::move(AllCode);
   }
 }
 
 void ClangMoveTool::onEndOfTranslationUnit() {
+  if (Context->DumpDeclarations) {
+    assert(Reporter);
+    for (const auto *Decl : UnremovedDeclsInOldHeader) {
+      auto Kind = Decl->getKind();
+      const std::string QualifiedName = Decl->getQualifiedNameAsString();
+      if (Kind == Decl::Kind::Function || Kind == Decl::Kind::FunctionTemplate)
+        Reporter->reportDeclaration(QualifiedName, "Function");
+      else if (Kind == Decl::Kind::ClassTemplate ||
+               Kind == Decl::Kind::CXXRecord)
+        Reporter->reportDeclaration(QualifiedName, "Class");
+    }
+    return;
+  }
+
   if (RemovedDecls.empty())
     return;
-  if (UnremovedDeclsInOldHeader.empty() && !Spec.OldHeader.empty()) {
+  if (UnremovedDeclsInOldHeader.empty() && !Context->Spec.OldHeader.empty()) {
     auto &SM = *RemovedDecls[0].SM;
-    moveAll(SM, Spec.OldHeader, Spec.NewHeader);
-    moveAll(SM, Spec.OldCC, Spec.NewCC);
+    moveAll(SM, Context->Spec.OldHeader, Context->Spec.NewHeader);
+    moveAll(SM, Context->Spec.OldCC, Context->Spec.NewCC);
     return;
   }
   removeClassDefinitionInOldFiles();

Modified: clang-tools-extra/trunk/clang-move/ClangMove.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-move/ClangMove.h?rev=287863&r1=287862&r2=287863&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-move/ClangMove.h (original)
+++ clang-tools-extra/trunk/clang-move/ClangMove.h Thu Nov 24 04:17:17 2016
@@ -24,11 +24,78 @@
 namespace clang {
 namespace move {
 
-// FIXME: Make it support more types, e.g. function definitions.
-// Currently only support moving class definition.
+// A reporter which collects and reports declarations in old header.
+class DeclarationReporter {
+public:
+  DeclarationReporter() = default;
+  ~DeclarationReporter() = default;
+
+  void reportDeclaration(llvm::StringRef DeclarationName,
+                         llvm::StringRef Type) {
+    DeclarationList.emplace_back(DeclarationName, Type);
+  };
+
+  // A <DeclarationName, DeclarationKind> pair.
+  // The DeclarationName is a fully qualified name for the declaration, like
+  // A::B::Foo. The DeclarationKind is a string represents the kind of the
+  // declaration, currently only "Function" and "Class" are supported.
+  typedef std::pair<std::string, std::string> DeclarationPair;
+
+  const std::vector<DeclarationPair> getDeclarationList() const {
+    return DeclarationList;
+  }
+
+private:
+  std::vector<DeclarationPair> DeclarationList;
+};
+
+// Specify declarations being moved. It contains all information of the moved
+// declarations.
+struct MoveDefinitionSpec {
+  // The list of fully qualified names, e.g. Foo, a::Foo, b::Foo.
+  SmallVector<std::string, 4> Names;
+  // The file path of old header, can be relative path and absolute path.
+  std::string OldHeader;
+  // The file path of old cc, can be relative path and absolute path.
+  std::string OldCC;
+  // The file path of new header, can be relative path and absolute path.
+  std::string NewHeader;
+  // The file path of new cc, can be relative path and absolute path.
+  std::string NewCC;
+  // Whether old.h depends on new.h. If true, #include "new.h" will be added
+  // in old.h.
+  bool OldDependOnNew = false;
+  // Whether new.h depends on old.h. If true, #include "old.h" will be added
+  // in new.h.
+  bool NewDependOnOld = false;
+};
+
+// A Context which contains extra options which are used in ClangMoveTool.
+struct ClangMoveContext {
+  MoveDefinitionSpec Spec;
+  // The Key is file path, value is the replacements being applied to the file.
+  std::map<std::string, tooling::Replacements> &FileToReplacements;
+  // The original working directory where the local clang-move binary runs.
+  //
+  // clang-move will change its current working directory to the build
+  // directory when analyzing the source file. We save the original working
+  // directory in order to get the absolute file path for the fields in Spec.
+  std::string OriginalRunningDirectory;
+  // The name of a predefined code style.
+  std::string FallbackStyle;
+  // Whether dump all declarations in old header.
+  bool DumpDeclarations;
+};
+
+// This tool is used to move class/function definitions from the given source
+// files (old.h/cc) to new files (new.h/cc). When moving a class, all its
+// members are also moved. In addition, all helper functions (anonymous
+// namespace declarations, static declarations, using declarations) in old.cc
+// and forward class declarations in old.h are copied to the new files.
+// The goal of this tool is to make the new files as compliable as possible.
 //
-// When moving all class declarations in old header, all code in old.h/cc will
-// be moved.
+// Note: When all declarations in old header are being moved, all code in
+// old.h/cc will be moved, which means old.h/cc are empty.
 class ClangMoveTool : public ast_matchers::MatchFinder::MatchCallback {
 public:
   // Information about the declaration being moved.
@@ -42,29 +109,8 @@ public:
         : Decl(Decl), SM(SM) {}
   };
 
-  struct MoveDefinitionSpec {
-    // The list of fully qualified names, e.g. Foo, a::Foo, b::Foo.
-    SmallVector<std::string, 4> Names;
-    // The file path of old header, can be relative path and absolute path.
-    std::string OldHeader;
-    // The file path of old cc, can be relative path and absolute path.
-    std::string OldCC;
-    // The file path of new header, can be relative path and absolute path.
-    std::string NewHeader;
-    // The file path of new cc, can be relative path and absolute path.
-    std::string NewCC;
-    // Whether old.h depends on new.h. If true, #include "new.h" will be added
-    // in old.h.
-    bool OldDependOnNew = false;
-    // Whether new.h depends on old.h. If true, #include "old.h" will be added
-    // in new.h.
-    bool NewDependOnOld = false;
-  };
-
-  ClangMoveTool(
-      const MoveDefinitionSpec &MoveSpec,
-      std::map<std::string, tooling::Replacements> &FileToReplacements,
-      llvm::StringRef OriginalRunningDirectory, llvm::StringRef Style);
+  ClangMoveTool(ClangMoveContext *const Context,
+                DeclarationReporter *const Reporter);
 
   void registerMatchers(ast_matchers::MatchFinder *Finder);
 
@@ -80,8 +126,8 @@ public:
   /// \param SearchPath The search path which was used to find the IncludeHeader
   /// in the file system. It can be a relative path or an absolute path.
   /// \param FileName The name of file where the IncludeHeader comes from.
-  /// \param IncludeFilenameRange The source range for the written file name in #include
-  ///  (i.e. "old.h" for #include "old.h") in old.cc.
+  /// \param IncludeFilenameRange The source range for the written file name in
+  /// #include (i.e. "old.h" for #include "old.h") in old.cc.
   /// \param SM The SourceManager.
   void addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
                    llvm::StringRef SearchPath, llvm::StringRef FileName,
@@ -108,12 +154,9 @@ private:
   void moveClassDefinitionToNewFiles();
   void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
 
-  MoveDefinitionSpec Spec;
   // Stores all MatchCallbacks created by this tool.
   std::vector<std::unique_ptr<ast_matchers::MatchFinder::MatchCallback>>
       MatchCallbacks;
-  // The Key is file path, value is the replacements being applied to the file.
-  std::map<std::string, tooling::Replacements> &FileToReplacements;
   // All declarations (the class decl being moved, forward decls) that need to
   // be moved/copy to the new files, saving in an AST-visited order.
   std::vector<MovedDecl> MovedDecls;
@@ -123,14 +166,6 @@ private:
   std::vector<std::string> HeaderIncludes;
   // The #includes in old_cc.cc.
   std::vector<std::string> CCIncludes;
-  // The original working directory where the local clang-move binary runs.
-  //
-  // clang-move will change its current working directory to the build
-  // directory when analyzing the source file. We save the original working
-  // directory in order to get the absolute file path for the fields in Spec.
-  std::string OriginalRunningDirectory;
-  // The name of a predefined code style.
-  std::string FallbackStyle;
   // The unmoved named declarations in old header.
   llvm::SmallPtrSet<const NamedDecl*, 8> UnremovedDeclsInOldHeader;
   /// The source range for the written file name in #include (i.e. "old.h" for
@@ -140,16 +175,17 @@ private:
   /// Mapping from FilePath to FileID, which can be used in post processes like
   /// cleanup around replacements.
   llvm::StringMap<FileID> FilePathToFileID;
+  /// A context contains all running options. It is not owned.
+  ClangMoveContext *const Context;
+  /// A reporter to report all declarations from old header. It is not owned.
+  DeclarationReporter *const Reporter;
 };
 
 class ClangMoveAction : public clang::ASTFrontendAction {
 public:
-  ClangMoveAction(
-      const ClangMoveTool::MoveDefinitionSpec &spec,
-      std::map<std::string, tooling::Replacements> &FileToReplacements,
-      llvm::StringRef OriginalRunningDirectory, llvm::StringRef FallbackStyle)
-      : MoveTool(spec, FileToReplacements, OriginalRunningDirectory,
-                 FallbackStyle) {
+  ClangMoveAction(ClangMoveContext *const Context,
+                  DeclarationReporter *const Reporter)
+      : MoveTool(Context, Reporter) {
     MoveTool.registerMatchers(&MatchFinder);
   }
 
@@ -166,24 +202,18 @@ private:
 
 class ClangMoveActionFactory : public tooling::FrontendActionFactory {
 public:
-  ClangMoveActionFactory(
-      const ClangMoveTool::MoveDefinitionSpec &Spec,
-      std::map<std::string, tooling::Replacements> &FileToReplacements,
-      llvm::StringRef OriginalRunningDirectory, llvm::StringRef FallbackStyle)
-      : Spec(Spec), FileToReplacements(FileToReplacements),
-        OriginalRunningDirectory(OriginalRunningDirectory),
-        FallbackStyle(FallbackStyle) {}
+  ClangMoveActionFactory(ClangMoveContext *const Context,
+                         DeclarationReporter *const Reporter = nullptr)
+      : Context(Context), Reporter(Reporter) {}
 
   clang::FrontendAction *create() override {
-    return new ClangMoveAction(Spec, FileToReplacements,
-                               OriginalRunningDirectory, FallbackStyle);
+    return new ClangMoveAction(Context, Reporter);
   }
 
 private:
-  const ClangMoveTool::MoveDefinitionSpec &Spec;
-  std::map<std::string, tooling::Replacements> &FileToReplacements;
-  std::string OriginalRunningDirectory;
-  std::string FallbackStyle;
+  // Not owned.
+  ClangMoveContext *const Context;
+  DeclarationReporter *const Reporter;
 };
 
 } // namespace move

Modified: clang-tools-extra/trunk/clang-move/tool/ClangMoveMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-move/tool/ClangMoveMain.cpp?rev=287863&r1=287862&r2=287863&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-move/tool/ClangMoveMain.cpp (original)
+++ clang-tools-extra/trunk/clang-move/tool/ClangMoveMain.cpp Thu Nov 24 04:17:17 2016
@@ -38,7 +38,7 @@ std::error_code CreateNewFile(const llvm
 
 cl::OptionCategory ClangMoveCategory("clang-move options");
 
-cl::list<std::string> Names("names", cl::CommaSeparated, cl::OneOrMore,
+cl::list<std::string> Names("names", cl::CommaSeparated,
                             cl::desc("The list of the names of classes being "
                                      "moved, e.g. \"Foo,a::Foo,b::Foo\"."),
                             cl::cat(ClangMoveCategory));
@@ -84,6 +84,13 @@ cl::opt<bool> Dump("dump_result",
                    cl::desc("Dump results in JSON format to stdout."),
                    cl::cat(ClangMoveCategory));
 
+cl::opt<bool> DumpDecls(
+    "dump_decls",
+    cl::desc("Dump all declarations in old header (JSON format) to stdout. If "
+             "the option is specified, other command options will be ignored. "
+             "An empty JSON will be returned if old header isn't specified."),
+    cl::cat(ClangMoveCategory));
+
 } // namespace
 
 int main(int argc, const char **argv) {
@@ -110,7 +117,7 @@ int main(int argc, const char **argv) {
 
   tooling::RefactoringTool Tool(OptionsParser.getCompilations(),
                                 OptionsParser.getSourcePathList());
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names = {Names.begin(), Names.end()};
   Spec.OldHeader = OldHeader;
   Spec.NewHeader = NewHeader;
@@ -124,13 +131,34 @@ int main(int argc, const char **argv) {
     llvm::report_fatal_error("Cannot detect current path: " +
                              Twine(EC.message()));
 
+  move::ClangMoveContext Context{Spec, Tool.getReplacements(),
+                                 InitialDirectory.str(), Style, DumpDecls};
+  move::DeclarationReporter Reporter;
   auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
-      Spec, Tool.getReplacements(), InitialDirectory.str(), Style);
+      &Context, &Reporter);
 
   int CodeStatus = Tool.run(Factory.get());
   if (CodeStatus)
     return CodeStatus;
 
+  if (DumpDecls) {
+    llvm::outs() << "[\n";
+    const auto &Declarations = Reporter.getDeclarationList();
+    for (auto DeclPair : Declarations) {
+      llvm::outs() << "  {\n";
+      llvm::outs() << "    \"DeclarationName\": \"" << DeclPair.first
+                   << "\",\n";
+      llvm::outs() << "    \"DeclarationType\": \"" << DeclPair.second
+                   << "\"\n";
+      llvm::outs() << "  }";
+      // Don't print trailing "," at the end of last element.
+      if (DeclPair != *(--Declarations.end()))
+        llvm::outs() << ",\n";
+    }
+    llvm::outs() << "\n]\n";
+    return 0;
+  }
+
   if (!NewCC.empty()) {
     std::error_code EC = CreateNewFile(NewCC);
     if (EC) {

Modified: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp?rev=287863&r1=287862&r2=287863&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp Thu Nov 24 04:17:17 2016
@@ -180,9 +180,10 @@ const char ExpectedNewCC[] = "namespace
                              "} // namespace a\n";
 
 std::map<std::string, std::string>
-runClangMoveOnCode(const move::ClangMoveTool::MoveDefinitionSpec &Spec,
+runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,
                    const char *const Header = TestHeader,
-                   const char *const CC = TestCC) {
+                   const char *const CC = TestCC,
+                   DeclarationReporter *const Reporter = nullptr) {
   clang::RewriterTestContext Context;
 
   std::map<llvm::StringRef, clang::FileID> FileToFileID;
@@ -205,8 +206,12 @@ runClangMoveOnCode(const move::ClangMove
   std::error_code EC = llvm::sys::fs::current_path(InitialDirectory);
   assert(!EC);
   (void)EC;
+  ClangMoveContext MoveContext = {Spec, FileToReplacements,
+                                  InitialDirectory.str(), "LLVM",
+                                  Reporter != nullptr};
+
   auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
-      Spec, FileToReplacements, InitialDirectory.str(), "LLVM");
+      &MoveContext, Reporter);
 
   tooling::runToolOnCodeWithArgs(
       Factory->create(), CC, {"-std=c++11", "-fparse-all-comments"},
@@ -223,7 +228,7 @@ runClangMoveOnCode(const move::ClangMove
 }
 
 TEST(ClangMove, MoveHeaderAndCC) {
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names = {std::string("a::b::Foo")};
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -238,7 +243,7 @@ TEST(ClangMove, MoveHeaderAndCC) {
 }
 
 TEST(ClangMove, MoveHeaderOnly) {
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names = {std::string("a::b::Foo")};
   Spec.OldHeader = "foo.h";
   Spec.NewHeader = "new_foo.h";
@@ -249,7 +254,7 @@ TEST(ClangMove, MoveHeaderOnly) {
 }
 
 TEST(ClangMove, MoveCCOnly) {
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names = {std::string("a::b::Foo")};
   Spec.OldCC = "foo.cc";
   Spec.NewCC = "new_foo.cc";
@@ -261,7 +266,7 @@ TEST(ClangMove, MoveCCOnly) {
 }
 
 TEST(ClangMove, MoveNonExistClass) {
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names = {std::string("NonExistFoo")};
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -282,7 +287,7 @@ TEST(ClangMove, MoveAll) {
     "namespace a {}\nusing namespace a;\nclass A {\npublic:\n  int f();\n};",
   };
   const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -297,7 +302,7 @@ TEST(ClangMove, MoveAll) {
 }
 
 TEST(ClangMove, MoveAllMultipleClasses) {
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   std::vector<std::string> TestHeaders = {
     "class C;\nclass A {\npublic:\n  int f();\n};\nclass B {};",
     "class C;\nclass B;\nclass A {\npublic:\n  int f();\n};\nclass B {};",
@@ -331,7 +336,7 @@ TEST(ClangMove, DontMoveAll) {
     "void f() {};\nclass A {\npublic:\n  int f();\n};\n",
     "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -354,7 +359,7 @@ TEST(ClangMove, MacroInFunction) {
                           "INT A::f() { return 0; }\n";
   const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
                                  "INT A::f() { return 0; }\n";
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -407,7 +412,7 @@ TEST(ClangMove, WellFormattedCode) {
                                         "\n"
                                         "#endif // NEW_FOO_H\n";
   const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("a::b::c::A");
   Spec.Names.push_back("a::d::e::B");
   Spec.OldHeader = "foo.h";
@@ -430,7 +435,7 @@ TEST(ClangMove, AddDependentNewHeader) {
                                    "class A {};\n"
                                    "\n"
                                    "#endif // NEW_FOO_H\n";
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -455,7 +460,7 @@ TEST(ClangMove, AddDependentOldHeader) {
                                    "\n"
                                    "#endif // NEW_FOO_H\n";
   const char ExpectedOldHeader[] = "class A {};\n";
-  move::ClangMoveTool::MoveDefinitionSpec Spec;
+  move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("B");
   Spec.OldHeader = "foo.h";
   Spec.OldCC = "foo.cc";
@@ -467,6 +472,64 @@ TEST(ClangMove, AddDependentOldHeader) {
   EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
 }
 
+TEST(ClangMove, DumpDecls) {
+  const char TestHeader[] = "template <typename T>\n"
+                            "class A {\n"
+                            " public:\n"
+                            "  void f();\n"
+                            "  template <typename U> void h();\n"
+                            "  static int b;\n"
+                            "};\n"
+                            "\n"
+                            "template <typename T> void A<T>::f() {}\n"
+                            "\n"
+                            "template <typename T>\n"
+                            "template <typename U>\n"
+                            "void A<T>::h() {}\n"
+                            "\n"
+                            "template <typename T> int A<T>::b = 2;\n"
+                            "\n"
+                            "template <> class A<int> {};\n"
+                            "\n"
+                            "class B {};\n"
+                            "\n"
+                            "namespace a {\n"
+                            "class Move1 {};\n"
+                            "void f1() {}\n"
+                            "void f2();\n"
+                            "} // namespace a\n"
+                            "\n"
+                            "namespace a {\n"
+                            "namespace b {\n"
+                            "class Move1 { public : void f(); };\n"
+                            "void f() {}\n"
+                            "} // namespace b\n"
+                            "} // namespace a\n";
+  const char TestCode[] = "#include \"foo.h\"\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("B");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  DeclarationReporter Reporter;
+  std::vector<DeclarationReporter::DeclarationPair> ExpectedDeclarations = {
+      {"A", "Class"},         {"B", "Class"},        {"a::Move1", "Class"},
+      {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
+      {"a::b::f", "Function"}};
+  runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);
+  const auto& Results = Reporter.getDeclarationList();
+  auto ActualDeclIter = Results.begin();
+  auto ExpectedDeclIter = ExpectedDeclarations.begin();
+  while (ActualDeclIter != Results.end() && ExpectedDeclIter != Results.end()) {
+    EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
+    ++ActualDeclIter;
+    ++ExpectedDeclIter;
+  }
+  ASSERT_TRUE(ActualDeclIter == Results.end());
+  ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
+}
+
 } // namespace
 } // namespce move
 } // namespace clang




More information about the cfe-commits mailing list