1 | //===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_CLANG_UNITTESTS_RENAME_CLANGRENAMETEST_H |
10 | #define LLVM_CLANG_UNITTESTS_RENAME_CLANGRENAMETEST_H |
11 | |
12 | #include "unittests/Tooling/RewriterTestContext.h" |
13 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
14 | #include "clang/Basic/FileManager.h" |
15 | #include "clang/Basic/FileSystemOptions.h" |
16 | #include "clang/Format/Format.h" |
17 | #include "clang/Frontend/CompilerInstance.h" |
18 | #include "clang/Frontend/PCHContainerOperations.h" |
19 | #include "clang/Tooling/Refactoring.h" |
20 | #include "clang/Tooling/Refactoring/Rename/RenamingAction.h" |
21 | #include "clang/Tooling/Refactoring/Rename/USRFindingAction.h" |
22 | #include "clang/Tooling/Tooling.h" |
23 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
24 | #include "llvm/ADT/StringRef.h" |
25 | #include "llvm/Support/Format.h" |
26 | #include "llvm/Support/MemoryBuffer.h" |
27 | #include "llvm/Support/VirtualFileSystem.h" |
28 | #include "gtest/gtest.h" |
29 | #include <memory> |
30 | #include <string> |
31 | #include <vector> |
32 | |
33 | namespace clang { |
34 | namespace clang_rename { |
35 | namespace test { |
36 | |
37 | struct Case { |
38 | std::string Before; |
39 | std::string After; |
40 | std::string OldName; |
41 | std::string NewName; |
42 | }; |
43 | |
44 | class ClangRenameTest : public testing::Test, |
45 | public testing::WithParamInterface<Case> { |
46 | protected: |
47 | void (StringRef Code) { HeaderContent += Code.str(); } |
48 | |
49 | std::string runClangRenameOnCode(llvm::StringRef Code, |
50 | llvm::StringRef OldName, |
51 | llvm::StringRef NewName) { |
52 | std::string NewCode; |
53 | llvm::raw_string_ostream(NewCode) << llvm::format( |
54 | Fmt: "#include \"%s\"\n%s" , Vals: HeaderName.c_str(), Vals: Code.str().c_str()); |
55 | tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent}, |
56 | {CCName, NewCode}}; |
57 | clang::RewriterTestContext Context; |
58 | Context.createInMemoryFile(Name: HeaderName, Content: HeaderContent); |
59 | clang::FileID InputFileID = Context.createInMemoryFile(Name: CCName, Content: NewCode); |
60 | |
61 | tooling::USRFindingAction FindingAction({}, {std::string(OldName)}, false); |
62 | std::unique_ptr<tooling::FrontendActionFactory> USRFindingActionFactory = |
63 | tooling::newFrontendActionFactory(ConsumerFactory: &FindingAction); |
64 | |
65 | if (!tooling::runToolOnCodeWithArgs( |
66 | ToolAction: USRFindingActionFactory->create(), Code: NewCode, Args: {"-std=c++11" }, FileName: CCName, |
67 | ToolName: "clang-rename" , PCHContainerOps: std::make_shared<PCHContainerOperations>(), |
68 | VirtualMappedFiles: FileContents)) |
69 | return "" ; |
70 | |
71 | const std::vector<std::vector<std::string>> &USRList = |
72 | FindingAction.getUSRList(); |
73 | std::vector<std::string> NewNames = {std::string(NewName)}; |
74 | std::map<std::string, tooling::Replacements> FileToReplacements; |
75 | tooling::QualifiedRenamingAction RenameAction(NewNames, USRList, |
76 | FileToReplacements); |
77 | auto RenameActionFactory = tooling::newFrontendActionFactory(ConsumerFactory: &RenameAction); |
78 | if (!tooling::runToolOnCodeWithArgs( |
79 | ToolAction: RenameActionFactory->create(), Code: NewCode, Args: {"-std=c++11" }, FileName: CCName, |
80 | ToolName: "clang-rename" , PCHContainerOps: std::make_shared<PCHContainerOperations>(), |
81 | VirtualMappedFiles: FileContents)) |
82 | return "" ; |
83 | |
84 | formatAndApplyAllReplacements(FileToReplaces: FileToReplacements, Rewrite&: Context.Rewrite, Style: "llvm" ); |
85 | return Context.getRewrittenText(ID: InputFileID); |
86 | } |
87 | |
88 | void CompareSnippets(StringRef Expected, StringRef Actual) { |
89 | std::string ExpectedCode; |
90 | llvm::raw_string_ostream(ExpectedCode) << llvm::format( |
91 | Fmt: "#include \"%s\"\n%s" , Vals: HeaderName.c_str(), Vals: Expected.str().c_str()); |
92 | EXPECT_EQ(format(ExpectedCode), format(Actual)); |
93 | } |
94 | |
95 | std::string format(llvm::StringRef Code) { |
96 | tooling::Replacements Replaces = format::reformat( |
97 | Style: format::getLLVMStyle(), Code, Ranges: {tooling::Range(0, Code.size())}); |
98 | auto ChangedCode = tooling::applyAllReplacements(Code, Replaces); |
99 | EXPECT_TRUE(static_cast<bool>(ChangedCode)); |
100 | if (!ChangedCode) { |
101 | llvm::errs() << llvm::toString(E: ChangedCode.takeError()); |
102 | return "" ; |
103 | } |
104 | return *ChangedCode; |
105 | } |
106 | |
107 | std::string ; |
108 | std::string = "header.h" ; |
109 | std::string CCName = "input.cc" ; |
110 | }; |
111 | |
112 | } // namespace test |
113 | } // namespace clang_rename |
114 | } // namesdpace clang |
115 | |
116 | #endif |
117 | |