[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