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