annotate clang-tools-extra/clang-change-namespace/ChangeNamespace.h @ 227:21e6aa2e49ef

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 19 Jul 2021 06:57:16 +0900
parents 2e18cbf3894f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===-- ChangeNamespace.h -- Change namespace ------------------*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
anatofuz
parents:
diff changeset
10 #define LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
anatofuz
parents:
diff changeset
11
anatofuz
parents:
diff changeset
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
anatofuz
parents:
diff changeset
13 #include "clang/Format/Format.h"
anatofuz
parents:
diff changeset
14 #include "clang/Tooling/Core/Replacement.h"
anatofuz
parents:
diff changeset
15 #include "llvm/Support/Regex.h"
anatofuz
parents:
diff changeset
16 #include <string>
anatofuz
parents:
diff changeset
17
anatofuz
parents:
diff changeset
18 namespace clang {
anatofuz
parents:
diff changeset
19 namespace change_namespace {
anatofuz
parents:
diff changeset
20
anatofuz
parents:
diff changeset
21 // This tool can be used to change the surrounding namespaces of class/function
anatofuz
parents:
diff changeset
22 // definitions. Classes/functions in the moved namespace will have new
anatofuz
parents:
diff changeset
23 // namespaces while references to symbols (e.g. types, functions) which are not
anatofuz
parents:
diff changeset
24 // defined in the changed namespace will be correctly qualified by prepending
anatofuz
parents:
diff changeset
25 // namespace specifiers before them.
anatofuz
parents:
diff changeset
26 // This will try to add shortest namespace specifiers possible. When a symbol
anatofuz
parents:
diff changeset
27 // reference needs to be fully-qualified, this adds a "::" prefix to the
anatofuz
parents:
diff changeset
28 // namespace specifiers unless the new namespace is the global namespace.
anatofuz
parents:
diff changeset
29 // For classes, only classes that are declared/defined in the given namespace in
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
30 // specified files will be moved: forward declarations will remain in the old
150
anatofuz
parents:
diff changeset
31 // namespace.
anatofuz
parents:
diff changeset
32 // For example, changing "a" to "x":
anatofuz
parents:
diff changeset
33 // Old code:
anatofuz
parents:
diff changeset
34 // namespace a {
anatofuz
parents:
diff changeset
35 // class FWD;
anatofuz
parents:
diff changeset
36 // class A { FWD *fwd; }
anatofuz
parents:
diff changeset
37 // } // a
anatofuz
parents:
diff changeset
38 // New code:
anatofuz
parents:
diff changeset
39 // namespace a {
anatofuz
parents:
diff changeset
40 // class FWD;
anatofuz
parents:
diff changeset
41 // } // a
anatofuz
parents:
diff changeset
42 // namespace x {
anatofuz
parents:
diff changeset
43 // class A { ::a::FWD *fwd; }
anatofuz
parents:
diff changeset
44 // } // x
anatofuz
parents:
diff changeset
45 // FIXME: support moving typedef, enums across namespaces.
anatofuz
parents:
diff changeset
46 class ChangeNamespaceTool : public ast_matchers::MatchFinder::MatchCallback {
anatofuz
parents:
diff changeset
47 public:
anatofuz
parents:
diff changeset
48 // Moves code in the old namespace `OldNs` to the new namespace `NewNs` in
anatofuz
parents:
diff changeset
49 // files matching `FilePattern`.
anatofuz
parents:
diff changeset
50 ChangeNamespaceTool(
anatofuz
parents:
diff changeset
51 llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
52 llvm::ArrayRef<std::string> AllowedSymbolPatterns,
150
anatofuz
parents:
diff changeset
53 std::map<std::string, tooling::Replacements> *FileToReplacements,
anatofuz
parents:
diff changeset
54 llvm::StringRef FallbackStyle = "LLVM");
anatofuz
parents:
diff changeset
55
anatofuz
parents:
diff changeset
56 void registerMatchers(ast_matchers::MatchFinder *Finder);
anatofuz
parents:
diff changeset
57
anatofuz
parents:
diff changeset
58 void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
anatofuz
parents:
diff changeset
59
anatofuz
parents:
diff changeset
60 // Moves the changed code in old namespaces but leaves class forward
anatofuz
parents:
diff changeset
61 // declarations behind.
anatofuz
parents:
diff changeset
62 void onEndOfTranslationUnit() override;
anatofuz
parents:
diff changeset
63
anatofuz
parents:
diff changeset
64 private:
anatofuz
parents:
diff changeset
65 void moveOldNamespace(const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
66 const NamespaceDecl *NsDecl);
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 void moveClassForwardDeclaration(
anatofuz
parents:
diff changeset
69 const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
70 const NamedDecl *FwdDecl);
anatofuz
parents:
diff changeset
71
anatofuz
parents:
diff changeset
72 void replaceQualifiedSymbolInDeclContext(
anatofuz
parents:
diff changeset
73 const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
74 const DeclContext *DeclContext, SourceLocation Start, SourceLocation End,
anatofuz
parents:
diff changeset
75 const NamedDecl *FromDecl);
anatofuz
parents:
diff changeset
76
anatofuz
parents:
diff changeset
77 void fixTypeLoc(const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
78 SourceLocation Start, SourceLocation End, TypeLoc Type);
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 void fixUsingShadowDecl(const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
81 const UsingDecl *UsingDeclaration);
anatofuz
parents:
diff changeset
82
anatofuz
parents:
diff changeset
83 void fixDeclRefExpr(const ast_matchers::MatchFinder::MatchResult &Result,
anatofuz
parents:
diff changeset
84 const DeclContext *UseContext, const NamedDecl *From,
anatofuz
parents:
diff changeset
85 const DeclRefExpr *Ref);
anatofuz
parents:
diff changeset
86
anatofuz
parents:
diff changeset
87 // Information about moving an old namespace.
anatofuz
parents:
diff changeset
88 struct MoveNamespace {
anatofuz
parents:
diff changeset
89 // The start offset of the namespace block being moved in the original
anatofuz
parents:
diff changeset
90 // code.
anatofuz
parents:
diff changeset
91 unsigned Offset;
anatofuz
parents:
diff changeset
92 // The length of the namespace block in the original code.
anatofuz
parents:
diff changeset
93 unsigned Length;
anatofuz
parents:
diff changeset
94 // The offset at which the new namespace block will be inserted in the
anatofuz
parents:
diff changeset
95 // original code.
anatofuz
parents:
diff changeset
96 unsigned InsertionOffset;
anatofuz
parents:
diff changeset
97 // The file in which the namespace is declared.
anatofuz
parents:
diff changeset
98 FileID FID;
anatofuz
parents:
diff changeset
99 SourceManager *SourceMgr;
anatofuz
parents:
diff changeset
100 };
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 // Information about inserting a class forward declaration.
anatofuz
parents:
diff changeset
103 struct InsertForwardDeclaration {
anatofuz
parents:
diff changeset
104 // The offset at while the forward declaration will be inserted in the
anatofuz
parents:
diff changeset
105 // original code.
anatofuz
parents:
diff changeset
106 unsigned InsertionOffset;
anatofuz
parents:
diff changeset
107 // The code to be inserted.
anatofuz
parents:
diff changeset
108 std::string ForwardDeclText;
anatofuz
parents:
diff changeset
109 };
anatofuz
parents:
diff changeset
110
anatofuz
parents:
diff changeset
111 std::string FallbackStyle;
anatofuz
parents:
diff changeset
112 // In match callbacks, this contains replacements for replacing `typeLoc`s in
anatofuz
parents:
diff changeset
113 // and deleting forward declarations in the moved namespace blocks.
anatofuz
parents:
diff changeset
114 // In `onEndOfTranslationUnit` callback, the previous added replacements are
anatofuz
parents:
diff changeset
115 // applied (on the moved namespace blocks), and then changed code in old
anatofuz
parents:
diff changeset
116 // namespaces re moved to new namespaces, and previously deleted forward
anatofuz
parents:
diff changeset
117 // declarations are inserted back to old namespaces, from which they are
anatofuz
parents:
diff changeset
118 // deleted.
anatofuz
parents:
diff changeset
119 std::map<std::string, tooling::Replacements> &FileToReplacements;
anatofuz
parents:
diff changeset
120 // A fully qualified name of the old namespace without "::" prefix, e.g.
anatofuz
parents:
diff changeset
121 // "a::b::c".
anatofuz
parents:
diff changeset
122 std::string OldNamespace;
anatofuz
parents:
diff changeset
123 // A fully qualified name of the new namespace without "::" prefix, e.g.
anatofuz
parents:
diff changeset
124 // "x::y::z".
anatofuz
parents:
diff changeset
125 std::string NewNamespace;
anatofuz
parents:
diff changeset
126 // The longest suffix in the old namespace that does not overlap the new
anatofuz
parents:
diff changeset
127 // namespace.
anatofuz
parents:
diff changeset
128 // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
anatofuz
parents:
diff changeset
129 // "a::x::y", then `DiffOldNamespace` will be "b::c".
anatofuz
parents:
diff changeset
130 std::string DiffOldNamespace;
anatofuz
parents:
diff changeset
131 // The longest suffix in the new namespace that does not overlap the old
anatofuz
parents:
diff changeset
132 // namespace.
anatofuz
parents:
diff changeset
133 // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
anatofuz
parents:
diff changeset
134 // "a::x::y", then `DiffNewNamespace` will be "x::y".
anatofuz
parents:
diff changeset
135 std::string DiffNewNamespace;
anatofuz
parents:
diff changeset
136 // A regex pattern that matches files to be processed.
anatofuz
parents:
diff changeset
137 std::string FilePattern;
anatofuz
parents:
diff changeset
138 llvm::Regex FilePatternRE;
anatofuz
parents:
diff changeset
139 // Information about moved namespaces grouped by file.
anatofuz
parents:
diff changeset
140 // Since we are modifying code in old namespaces (e.g. add namespace
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
141 // specifiers) as well as moving them, we store information about namespaces
150
anatofuz
parents:
diff changeset
142 // to be moved and only move them after all modifications are finished (i.e.
anatofuz
parents:
diff changeset
143 // in `onEndOfTranslationUnit`).
anatofuz
parents:
diff changeset
144 std::map<std::string, std::vector<MoveNamespace>> MoveNamespaces;
anatofuz
parents:
diff changeset
145 // Information about forward declaration insertions grouped by files.
anatofuz
parents:
diff changeset
146 // A class forward declaration is not moved, so it will be deleted from the
anatofuz
parents:
diff changeset
147 // moved code block and inserted back into the old namespace. The insertion
anatofuz
parents:
diff changeset
148 // will be done after removing the code from the old namespace and before
anatofuz
parents:
diff changeset
149 // inserting it to the new namespace.
anatofuz
parents:
diff changeset
150 std::map<std::string, std::vector<InsertForwardDeclaration>> InsertFwdDecls;
anatofuz
parents:
diff changeset
151 // Records all using declarations, which can be used to shorten namespace
anatofuz
parents:
diff changeset
152 // specifiers.
anatofuz
parents:
diff changeset
153 llvm::SmallPtrSet<const UsingDecl *, 8> UsingDecls;
anatofuz
parents:
diff changeset
154 // Records all using namespace declarations, which can be used to shorten
anatofuz
parents:
diff changeset
155 // namespace specifiers.
anatofuz
parents:
diff changeset
156 llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
anatofuz
parents:
diff changeset
157 // Records all namespace alias declarations, which can be used to shorten
anatofuz
parents:
diff changeset
158 // namespace specifiers.
anatofuz
parents:
diff changeset
159 llvm::SmallPtrSet<const NamespaceAliasDecl *, 8> NamespaceAliasDecls;
anatofuz
parents:
diff changeset
160 // TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
anatofuz
parents:
diff changeset
161 // be fixed.
anatofuz
parents:
diff changeset
162 llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
anatofuz
parents:
diff changeset
163 // Since a DeclRefExpr for a function call can be matched twice (one as
anatofuz
parents:
diff changeset
164 // CallExpr and one as DeclRefExpr), we record all DeclRefExpr's that have
anatofuz
parents:
diff changeset
165 // been processed so that we don't handle them twice.
anatofuz
parents:
diff changeset
166 llvm::SmallPtrSet<const clang::DeclRefExpr*, 16> ProcessedFuncRefs;
anatofuz
parents:
diff changeset
167 // Patterns of symbol names whose references are not expected to be updated
anatofuz
parents:
diff changeset
168 // when changing namespaces around them.
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
169 std::vector<llvm::Regex> AllowedSymbolRegexes;
150
anatofuz
parents:
diff changeset
170 };
anatofuz
parents:
diff changeset
171
anatofuz
parents:
diff changeset
172 } // namespace change_namespace
anatofuz
parents:
diff changeset
173 } // namespace clang
anatofuz
parents:
diff changeset
174
anatofuz
parents:
diff changeset
175 #endif // LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H