Line data Source code
1 : //===-- ClangMove.h - Clang move -----------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_CLANGMOVE_H
11 : #define LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_CLANGMOVE_H
12 :
13 : #include "HelperDeclRefGraph.h"
14 : #include "clang/ASTMatchers/ASTMatchFinder.h"
15 : #include "clang/Frontend/FrontendAction.h"
16 : #include "clang/Tooling/Core/Replacement.h"
17 : #include "clang/Tooling/Tooling.h"
18 : #include "llvm/ADT/SmallPtrSet.h"
19 : #include "llvm/ADT/StringMap.h"
20 : #include "llvm/ADT/StringRef.h"
21 : #include <map>
22 : #include <memory>
23 : #include <string>
24 : #include <vector>
25 :
26 : namespace clang {
27 : namespace move {
28 :
29 : // A reporter which collects and reports declarations in old header.
30 : class DeclarationReporter {
31 : public:
32 : DeclarationReporter() = default;
33 1 : ~DeclarationReporter() = default;
34 :
35 : void reportDeclaration(llvm::StringRef DeclarationName, llvm::StringRef Type,
36 : bool Templated) {
37 : DeclarationList.emplace_back(DeclarationName, Type, Templated);
38 : };
39 :
40 30 : struct Declaration {
41 15 : Declaration(llvm::StringRef QName, llvm::StringRef Kind, bool Templated)
42 15 : : QualifiedName(QName), Kind(Kind), Templated(Templated) {}
43 :
44 : friend bool operator==(const Declaration &LHS, const Declaration &RHS) {
45 450 : return std::tie(LHS.QualifiedName, LHS.Kind, LHS.Templated) ==
46 450 : std::tie(RHS.QualifiedName, RHS.Kind, RHS.Templated);
47 : }
48 : std::string QualifiedName; // E.g. A::B::Foo.
49 : std::string Kind; // E.g. Function, Class
50 : bool Templated = false; // Whether the declaration is templated.
51 : };
52 :
53 : const std::vector<Declaration> getDeclarationList() const {
54 1 : return DeclarationList;
55 : }
56 :
57 : private:
58 : std::vector<Declaration> DeclarationList;
59 : };
60 :
61 : // Specify declarations being moved. It contains all information of the moved
62 : // declarations.
63 15 : struct MoveDefinitionSpec {
64 : // The list of fully qualified names, e.g. Foo, a::Foo, b::Foo.
65 : SmallVector<std::string, 4> Names;
66 : // The file path of old header, can be relative path and absolute path.
67 : std::string OldHeader;
68 : // The file path of old cc, can be relative path and absolute path.
69 : std::string OldCC;
70 : // The file path of new header, can be relative path and absolute path.
71 : std::string NewHeader;
72 : // The file path of new cc, can be relative path and absolute path.
73 : std::string NewCC;
74 : // Whether old.h depends on new.h. If true, #include "new.h" will be added
75 : // in old.h.
76 : bool OldDependOnNew = false;
77 : // Whether new.h depends on old.h. If true, #include "old.h" will be added
78 : // in new.h.
79 : bool NewDependOnOld = false;
80 : };
81 :
82 : // A Context which contains extra options which are used in ClangMoveTool.
83 : struct ClangMoveContext {
84 : MoveDefinitionSpec Spec;
85 : // The Key is file path, value is the replacements being applied to the file.
86 : std::map<std::string, tooling::Replacements> &FileToReplacements;
87 : // The original working directory where the local clang-move binary runs.
88 : //
89 : // clang-move will change its current working directory to the build
90 : // directory when analyzing the source file. We save the original working
91 : // directory in order to get the absolute file path for the fields in Spec.
92 : std::string OriginalRunningDirectory;
93 : // The name of a predefined code style.
94 : std::string FallbackStyle;
95 : // Whether dump all declarations in old header.
96 : bool DumpDeclarations;
97 : };
98 :
99 : // This tool is used to move class/function definitions from the given source
100 : // files (old.h/cc) to new files (new.h/cc).
101 : // The goal of this tool is to make the new/old files as compilable as possible.
102 : //
103 : // When moving a symbol,all used helper declarations (e.g. static
104 : // functions/variables definitions in global/named namespace,
105 : // functions/variables/classes definitions in anonymous namespace) used by the
106 : // moved symbol in old.cc are moved to the new.cc. In addition, all
107 : // using-declarations in old.cc are also moved to new.cc; forward class
108 : // declarations in old.h are also moved to new.h.
109 : //
110 : // The remaining helper declarations which are unused by non-moved symbols in
111 : // old.cc will be removed.
112 : //
113 : // Note: When all declarations in old header are being moved, all code in
114 : // old.h/cc will be moved, which means old.h/cc are empty. This ignores symbols
115 : // that are not supported (e.g. typedef and enum) so that we always move old
116 : // files to new files when all symbols produced from dump_decls are moved.
117 : class ClangMoveTool : public ast_matchers::MatchFinder::MatchCallback {
118 : public:
119 : ClangMoveTool(ClangMoveContext *const Context,
120 : DeclarationReporter *const Reporter);
121 :
122 : void registerMatchers(ast_matchers::MatchFinder *Finder);
123 :
124 : void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
125 :
126 : void onEndOfTranslationUnit() override;
127 :
128 : /// Add #includes from old.h/cc files.
129 : ///
130 : /// \param IncludeHeader The name of the file being included, as written in
131 : /// the source code.
132 : /// \param IsAngled Whether the file name was enclosed in angle brackets.
133 : /// \param SearchPath The search path which was used to find the IncludeHeader
134 : /// in the file system. It can be a relative path or an absolute path.
135 : /// \param FileName The name of file where the IncludeHeader comes from.
136 : /// \param IncludeFilenameRange The source range for the written file name in
137 : /// #include (i.e. "old.h" for #include "old.h") in old.cc.
138 : /// \param SM The SourceManager.
139 : void addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
140 : llvm::StringRef SearchPath, llvm::StringRef FileName,
141 : clang::CharSourceRange IncludeFilenameRange,
142 : const SourceManager &SM);
143 :
144 : std::vector<const NamedDecl *> &getMovedDecls() { return MovedDecls; }
145 :
146 : /// Add declarations being removed from old.h/cc. For each declarations, the
147 : /// method also records the mapping relationship between the corresponding
148 : /// FilePath and its FileID.
149 : void addRemovedDecl(const NamedDecl *Decl);
150 :
151 : llvm::SmallPtrSet<const NamedDecl *, 8> &getUnremovedDeclsInOldHeader() {
152 : return UnremovedDeclsInOldHeader;
153 : }
154 :
155 : private:
156 : // Make the Path absolute using the OrignalRunningDirectory if the Path is not
157 : // an absolute path. An empty Path will result in an empty string.
158 : std::string makeAbsolutePath(StringRef Path);
159 :
160 : void removeDeclsInOldFiles();
161 : void moveDeclsToNewFiles();
162 : void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
163 :
164 : // Stores all MatchCallbacks created by this tool.
165 : std::vector<std::unique_ptr<ast_matchers::MatchFinder::MatchCallback>>
166 : MatchCallbacks;
167 : // Store all potential declarations (decls being moved, forward decls) that
168 : // might need to move to new.h/cc. It includes all helper declarations
169 : // (include unused ones) by default. The unused ones will be filtered out in
170 : // the last stage. Saving in an AST-visited order.
171 : std::vector<const NamedDecl *> MovedDecls;
172 : // The declarations that needs to be removed in old.cc/h.
173 : std::vector<const NamedDecl *> RemovedDecls;
174 : // The #includes in old_header.h.
175 : std::vector<std::string> HeaderIncludes;
176 : // The #includes in old_cc.cc.
177 : std::vector<std::string> CCIncludes;
178 : // Records all helper declarations (function/variable/class definitions in
179 : // anonymous namespaces, static function/variable definitions in global/named
180 : // namespaces) in old.cc. saving in an AST-visited order.
181 : std::vector<const NamedDecl *> HelperDeclarations;
182 : // The unmoved named declarations in old header.
183 : llvm::SmallPtrSet<const NamedDecl*, 8> UnremovedDeclsInOldHeader;
184 : /// The source range for the written file name in #include (i.e. "old.h" for
185 : /// #include "old.h") in old.cc, including the enclosing quotes or angle
186 : /// brackets.
187 : clang::CharSourceRange OldHeaderIncludeRangeInCC;
188 : /// The source range for the written file name in #include (i.e. "old.h" for
189 : /// #include "old.h") in old.h, including the enclosing quotes or angle
190 : /// brackets.
191 : clang::CharSourceRange OldHeaderIncludeRangeInHeader;
192 : /// Mapping from FilePath to FileID, which can be used in post processes like
193 : /// cleanup around replacements.
194 : llvm::StringMap<FileID> FilePathToFileID;
195 : /// A context contains all running options. It is not owned.
196 : ClangMoveContext *const Context;
197 : /// A reporter to report all declarations from old header. It is not owned.
198 : DeclarationReporter *const Reporter;
199 : /// Builder for helper declarations reference graph.
200 : HelperDeclRGBuilder RGBuilder;
201 : };
202 :
203 : class ClangMoveAction : public clang::ASTFrontendAction {
204 : public:
205 22 : ClangMoveAction(ClangMoveContext *const Context,
206 : DeclarationReporter *const Reporter)
207 22 : : MoveTool(Context, Reporter) {
208 22 : MoveTool.registerMatchers(&MatchFinder);
209 22 : }
210 :
211 : ~ClangMoveAction() override = default;
212 :
213 : std::unique_ptr<clang::ASTConsumer>
214 : CreateASTConsumer(clang::CompilerInstance &Compiler,
215 : llvm::StringRef InFile) override;
216 :
217 : private:
218 : ast_matchers::MatchFinder MatchFinder;
219 : ClangMoveTool MoveTool;
220 : };
221 :
222 : class ClangMoveActionFactory : public tooling::FrontendActionFactory {
223 : public:
224 : ClangMoveActionFactory(ClangMoveContext *const Context,
225 : DeclarationReporter *const Reporter = nullptr)
226 22 : : Context(Context), Reporter(Reporter) {}
227 :
228 22 : clang::FrontendAction *create() override {
229 22 : return new ClangMoveAction(Context, Reporter);
230 : }
231 :
232 : private:
233 : // Not owned.
234 : ClangMoveContext *const Context;
235 : DeclarationReporter *const Reporter;
236 : };
237 :
238 : } // namespace move
239 : } // namespace clang
240 :
241 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_MOVE_CLANGMOVE_H
|