blob: 85b6b136493cbf640f1be917a40298e99551f52b [file] [log] [blame]
Eric Liu495b2112016-09-19 17:40:32 +00001//===-- ChangeNamespace.cpp - Change namespace implementation -------------===//
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#include "ChangeNamespace.h"
10#include "clang/Format/Format.h"
11#include "clang/Lex/Lexer.h"
Eric Liuff51f012016-11-16 16:54:53 +000012#include "llvm/Support/ErrorHandling.h"
Eric Liu495b2112016-09-19 17:40:32 +000013
14using namespace clang::ast_matchers;
15
16namespace clang {
17namespace change_namespace {
18
19namespace {
20
21inline std::string
22joinNamespaces(const llvm::SmallVectorImpl<StringRef> &Namespaces) {
23 if (Namespaces.empty())
24 return "";
25 std::string Result = Namespaces.front();
26 for (auto I = Namespaces.begin() + 1, E = Namespaces.end(); I != E; ++I)
27 Result += ("::" + *I).str();
28 return Result;
29}
30
Eric Liu8bc24162017-03-21 12:41:59 +000031// Given "a::b::c", returns {"a", "b", "c"}.
32llvm::SmallVector<llvm::StringRef, 4> splitSymbolName(llvm::StringRef Name) {
33 llvm::SmallVector<llvm::StringRef, 4> Splitted;
34 Name.split(Splitted, "::", /*MaxSplit=*/-1,
35 /*KeepEmpty=*/false);
36 return Splitted;
37}
38
Eric Liu495b2112016-09-19 17:40:32 +000039SourceLocation startLocationForType(TypeLoc TLoc) {
40 // For elaborated types (e.g. `struct a::A`) we want the portion after the
41 // `struct` but including the namespace qualifier, `a::`.
42 if (TLoc.getTypeLocClass() == TypeLoc::Elaborated) {
43 NestedNameSpecifierLoc NestedNameSpecifier =
44 TLoc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
45 if (NestedNameSpecifier.getNestedNameSpecifier())
46 return NestedNameSpecifier.getBeginLoc();
47 TLoc = TLoc.getNextTypeLoc();
48 }
Stephen Kelly43465bf2018-08-09 22:42:26 +000049 return TLoc.getBeginLoc();
Eric Liu495b2112016-09-19 17:40:32 +000050}
51
Eric Liuc265b022016-12-01 17:25:55 +000052SourceLocation endLocationForType(TypeLoc TLoc) {
Eric Liu495b2112016-09-19 17:40:32 +000053 // Dig past any namespace or keyword qualifications.
54 while (TLoc.getTypeLocClass() == TypeLoc::Elaborated ||
55 TLoc.getTypeLocClass() == TypeLoc::Qualified)
56 TLoc = TLoc.getNextTypeLoc();
57
58 // The location for template specializations (e.g. Foo<int>) includes the
59 // templated types in its location range. We want to restrict this to just
60 // before the `<` character.
61 if (TLoc.getTypeLocClass() == TypeLoc::TemplateSpecialization)
62 return TLoc.castAs<TemplateSpecializationTypeLoc>()
63 .getLAngleLoc()
64 .getLocWithOffset(-1);
65 return TLoc.getEndLoc();
66}
67
68// Returns the containing namespace of `InnerNs` by skipping `PartialNsName`.
Eric Liu6aa94162016-11-10 18:29:01 +000069// If the `InnerNs` does not have `PartialNsName` as suffix, or `PartialNsName`
70// is empty, nullptr is returned.
Eric Liu495b2112016-09-19 17:40:32 +000071// For example, if `InnerNs` is "a::b::c" and `PartialNsName` is "b::c", then
72// the NamespaceDecl of namespace "a" will be returned.
73const NamespaceDecl *getOuterNamespace(const NamespaceDecl *InnerNs,
74 llvm::StringRef PartialNsName) {
Eric Liu6aa94162016-11-10 18:29:01 +000075 if (!InnerNs || PartialNsName.empty())
76 return nullptr;
Eric Liu495b2112016-09-19 17:40:32 +000077 const auto *CurrentContext = llvm::cast<DeclContext>(InnerNs);
78 const auto *CurrentNs = InnerNs;
Eric Liu8bc24162017-03-21 12:41:59 +000079 auto PartialNsNameSplitted = splitSymbolName(PartialNsName);
Eric Liu495b2112016-09-19 17:40:32 +000080 while (!PartialNsNameSplitted.empty()) {
81 // Get the inner-most namespace in CurrentContext.
82 while (CurrentContext && !llvm::isa<NamespaceDecl>(CurrentContext))
83 CurrentContext = CurrentContext->getParent();
84 if (!CurrentContext)
85 return nullptr;
86 CurrentNs = llvm::cast<NamespaceDecl>(CurrentContext);
87 if (PartialNsNameSplitted.back() != CurrentNs->getNameAsString())
88 return nullptr;
89 PartialNsNameSplitted.pop_back();
90 CurrentContext = CurrentContext->getParent();
91 }
92 return CurrentNs;
93}
94
Eric Liu73f49fd2016-10-12 12:34:18 +000095static std::unique_ptr<Lexer>
96getLexerStartingFromLoc(SourceLocation Loc, const SourceManager &SM,
97 const LangOptions &LangOpts) {
Eric Liu495b2112016-09-19 17:40:32 +000098 if (Loc.isMacroID() &&
99 !Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
Eric Liu73f49fd2016-10-12 12:34:18 +0000100 return nullptr;
Eric Liu495b2112016-09-19 17:40:32 +0000101 // Break down the source location.
102 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
103 // Try to load the file buffer.
104 bool InvalidTemp = false;
105 llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
106 if (InvalidTemp)
Eric Liu73f49fd2016-10-12 12:34:18 +0000107 return nullptr;
Eric Liu495b2112016-09-19 17:40:32 +0000108
109 const char *TokBegin = File.data() + LocInfo.second;
110 // Lex from the start of the given location.
Eric Liu73f49fd2016-10-12 12:34:18 +0000111 return llvm::make_unique<Lexer>(SM.getLocForStartOfFile(LocInfo.first),
112 LangOpts, File.begin(), TokBegin, File.end());
113}
Eric Liu495b2112016-09-19 17:40:32 +0000114
Eric Liu73f49fd2016-10-12 12:34:18 +0000115// FIXME: get rid of this helper function if this is supported in clang-refactor
116// library.
117static SourceLocation getStartOfNextLine(SourceLocation Loc,
118 const SourceManager &SM,
119 const LangOptions &LangOpts) {
120 std::unique_ptr<Lexer> Lex = getLexerStartingFromLoc(Loc, SM, LangOpts);
121 if (!Lex.get())
122 return SourceLocation();
Eric Liu495b2112016-09-19 17:40:32 +0000123 llvm::SmallVector<char, 16> Line;
124 // FIXME: this is a bit hacky to get ReadToEndOfLine work.
Eric Liu73f49fd2016-10-12 12:34:18 +0000125 Lex->setParsingPreprocessorDirective(true);
126 Lex->ReadToEndOfLine(&Line);
Haojian Wuef8a6dc2016-10-04 10:35:53 +0000127 auto End = Loc.getLocWithOffset(Line.size());
Eric Liu73f49fd2016-10-12 12:34:18 +0000128 return SM.getLocForEndOfFile(SM.getDecomposedLoc(Loc).first) == End
129 ? End
130 : End.getLocWithOffset(1);
Eric Liu495b2112016-09-19 17:40:32 +0000131}
132
133// Returns `R` with new range that refers to code after `Replaces` being
134// applied.
135tooling::Replacement
136getReplacementInChangedCode(const tooling::Replacements &Replaces,
137 const tooling::Replacement &R) {
138 unsigned NewStart = Replaces.getShiftedCodePosition(R.getOffset());
139 unsigned NewEnd =
140 Replaces.getShiftedCodePosition(R.getOffset() + R.getLength());
141 return tooling::Replacement(R.getFilePath(), NewStart, NewEnd - NewStart,
142 R.getReplacementText());
143}
144
145// Adds a replacement `R` into `Replaces` or merges it into `Replaces` by
146// applying all existing Replaces first if there is conflict.
147void addOrMergeReplacement(const tooling::Replacement &R,
148 tooling::Replacements *Replaces) {
149 auto Err = Replaces->add(R);
150 if (Err) {
151 llvm::consumeError(std::move(Err));
152 auto Replace = getReplacementInChangedCode(*Replaces, R);
153 *Replaces = Replaces->merge(tooling::Replacements(Replace));
154 }
155}
156
157tooling::Replacement createReplacement(SourceLocation Start, SourceLocation End,
158 llvm::StringRef ReplacementText,
159 const SourceManager &SM) {
160 if (!Start.isValid() || !End.isValid()) {
161 llvm::errs() << "start or end location were invalid\n";
162 return tooling::Replacement();
163 }
164 if (SM.getDecomposedLoc(Start).first != SM.getDecomposedLoc(End).first) {
165 llvm::errs()
166 << "start or end location were in different macro expansions\n";
167 return tooling::Replacement();
168 }
169 Start = SM.getSpellingLoc(Start);
170 End = SM.getSpellingLoc(End);
171 if (SM.getFileID(Start) != SM.getFileID(End)) {
172 llvm::errs() << "start or end location were in different files\n";
173 return tooling::Replacement();
174 }
175 return tooling::Replacement(
176 SM, CharSourceRange::getTokenRange(SM.getSpellingLoc(Start),
177 SM.getSpellingLoc(End)),
178 ReplacementText);
179}
180
Eric Liu4fe99e12016-12-14 17:01:52 +0000181void addReplacementOrDie(
182 SourceLocation Start, SourceLocation End, llvm::StringRef ReplacementText,
183 const SourceManager &SM,
184 std::map<std::string, tooling::Replacements> *FileToReplacements) {
185 const auto R = createReplacement(Start, End, ReplacementText, SM);
186 auto Err = (*FileToReplacements)[R.getFilePath()].add(R);
187 if (Err)
188 llvm_unreachable(llvm::toString(std::move(Err)).c_str());
189}
190
Eric Liu495b2112016-09-19 17:40:32 +0000191tooling::Replacement createInsertion(SourceLocation Loc,
192 llvm::StringRef InsertText,
193 const SourceManager &SM) {
194 if (Loc.isInvalid()) {
195 llvm::errs() << "insert Location is invalid.\n";
196 return tooling::Replacement();
197 }
198 Loc = SM.getSpellingLoc(Loc);
199 return tooling::Replacement(SM, Loc, 0, InsertText);
200}
201
202// Returns the shortest qualified name for declaration `DeclName` in the
203// namespace `NsName`. For example, if `DeclName` is "a::b::X" and `NsName`
204// is "a::c::d", then "b::X" will be returned.
Eric Liubc715502017-01-26 15:08:44 +0000205// Note that if `DeclName` is `::b::X` and `NsName` is `::a::b`, this returns
206// "::b::X" instead of "b::X" since there will be a name conflict otherwise.
Eric Liu447164d2016-10-05 15:52:39 +0000207// \param DeclName A fully qualified name, "::a::b::X" or "a::b::X".
208// \param NsName A fully qualified name, "::a::b" or "a::b". Global namespace
209// will have empty name.
Eric Liu495b2112016-09-19 17:40:32 +0000210std::string getShortestQualifiedNameInNamespace(llvm::StringRef DeclName,
211 llvm::StringRef NsName) {
Eric Liu447164d2016-10-05 15:52:39 +0000212 DeclName = DeclName.ltrim(':');
213 NsName = NsName.ltrim(':');
Eric Liu447164d2016-10-05 15:52:39 +0000214 if (DeclName.find(':') == llvm::StringRef::npos)
Eric Liub9bf1b52016-11-08 22:44:17 +0000215 return DeclName;
Eric Liu447164d2016-10-05 15:52:39 +0000216
Eric Liu8bc24162017-03-21 12:41:59 +0000217 auto NsNameSplitted = splitSymbolName(NsName);
218 auto DeclNsSplitted = splitSymbolName(DeclName);
Eric Liubc715502017-01-26 15:08:44 +0000219 llvm::StringRef UnqualifiedDeclName = DeclNsSplitted.pop_back_val();
220 // If the Decl is in global namespace, there is no need to shorten it.
221 if (DeclNsSplitted.empty())
222 return UnqualifiedDeclName;
223 // If NsName is the global namespace, we can simply use the DeclName sans
224 // leading "::".
225 if (NsNameSplitted.empty())
226 return DeclName;
227
228 if (NsNameSplitted.front() != DeclNsSplitted.front()) {
229 // The DeclName must be fully-qualified, but we still need to decide if a
230 // leading "::" is necessary. For example, if `NsName` is "a::b::c" and the
231 // `DeclName` is "b::X", then the reference must be qualified as "::b::X"
232 // to avoid conflict.
233 if (llvm::is_contained(NsNameSplitted, DeclNsSplitted.front()))
234 return ("::" + DeclName).str();
235 return DeclName;
Eric Liu495b2112016-09-19 17:40:32 +0000236 }
Eric Liubc715502017-01-26 15:08:44 +0000237 // Since there is already an overlap namespace, we know that `DeclName` can be
238 // shortened, so we reduce the longest common prefix.
239 auto DeclI = DeclNsSplitted.begin();
240 auto DeclE = DeclNsSplitted.end();
241 auto NsI = NsNameSplitted.begin();
242 auto NsE = NsNameSplitted.end();
243 for (; DeclI != DeclE && NsI != NsE && *DeclI == *NsI; ++DeclI, ++NsI) {
244 }
245 return (DeclI == DeclE)
246 ? UnqualifiedDeclName.str()
247 : (llvm::join(DeclI, DeclE, "::") + "::" + UnqualifiedDeclName)
248 .str();
Eric Liu495b2112016-09-19 17:40:32 +0000249}
250
251std::string wrapCodeInNamespace(StringRef NestedNs, std::string Code) {
252 if (Code.back() != '\n')
253 Code += "\n";
Eric Liu8bc24162017-03-21 12:41:59 +0000254 auto NsSplitted = splitSymbolName(NestedNs);
Eric Liu495b2112016-09-19 17:40:32 +0000255 while (!NsSplitted.empty()) {
256 // FIXME: consider code style for comments.
257 Code = ("namespace " + NsSplitted.back() + " {\n" + Code +
258 "} // namespace " + NsSplitted.back() + "\n")
259 .str();
260 NsSplitted.pop_back();
261 }
262 return Code;
263}
264
Eric Liub9bf1b52016-11-08 22:44:17 +0000265// Returns true if \p D is a nested DeclContext in \p Context
266bool isNestedDeclContext(const DeclContext *D, const DeclContext *Context) {
267 while (D) {
268 if (D == Context)
269 return true;
270 D = D->getParent();
271 }
272 return false;
273}
274
275// Returns true if \p D is visible at \p Loc with DeclContext \p DeclCtx.
276bool isDeclVisibleAtLocation(const SourceManager &SM, const Decl *D,
277 const DeclContext *DeclCtx, SourceLocation Loc) {
Stephen Kelly43465bf2018-08-09 22:42:26 +0000278 SourceLocation DeclLoc = SM.getSpellingLoc(D->getBeginLoc());
Eric Liub9bf1b52016-11-08 22:44:17 +0000279 Loc = SM.getSpellingLoc(Loc);
280 return SM.isBeforeInTranslationUnit(DeclLoc, Loc) &&
281 (SM.getFileID(DeclLoc) == SM.getFileID(Loc) &&
282 isNestedDeclContext(DeclCtx, D->getDeclContext()));
283}
284
Eric Liu8bc24162017-03-21 12:41:59 +0000285// Given a qualified symbol name, returns true if the symbol will be
286// incorrectly qualified without leading "::".
287bool conflictInNamespace(llvm::StringRef QualifiedSymbol,
288 llvm::StringRef Namespace) {
289 auto SymbolSplitted = splitSymbolName(QualifiedSymbol.trim(":"));
290 assert(!SymbolSplitted.empty());
291 SymbolSplitted.pop_back(); // We are only interested in namespaces.
292
293 if (SymbolSplitted.size() > 1 && !Namespace.empty()) {
294 auto NsSplitted = splitSymbolName(Namespace.trim(":"));
295 assert(!NsSplitted.empty());
296 // We do not check the outermost namespace since it would not be a conflict
297 // if it equals to the symbol's outermost namespace and the symbol name
298 // would have been shortened.
299 for (auto I = NsSplitted.begin() + 1, E = NsSplitted.end(); I != E; ++I) {
300 if (*I == SymbolSplitted.front())
301 return true;
302 }
303 }
304 return false;
305}
306
Eric Liu0325a772017-02-02 17:40:38 +0000307AST_MATCHER(EnumDecl, isScoped) {
308 return Node.isScoped();
309}
310
Eric Liu284b97c2017-03-17 14:05:39 +0000311bool isTemplateParameter(TypeLoc Type) {
312 while (!Type.isNull()) {
313 if (Type.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
314 return true;
315 Type = Type.getNextTypeLoc();
316 }
317 return false;
318}
319
Eric Liu495b2112016-09-19 17:40:32 +0000320} // anonymous namespace
321
322ChangeNamespaceTool::ChangeNamespaceTool(
323 llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
Eric Liu7fccc992017-02-24 11:54:45 +0000324 llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
Eric Liu495b2112016-09-19 17:40:32 +0000325 std::map<std::string, tooling::Replacements> *FileToReplacements,
326 llvm::StringRef FallbackStyle)
327 : FallbackStyle(FallbackStyle), FileToReplacements(*FileToReplacements),
328 OldNamespace(OldNs.ltrim(':')), NewNamespace(NewNs.ltrim(':')),
Eric Liuc265b022016-12-01 17:25:55 +0000329 FilePattern(FilePattern), FilePatternRE(FilePattern) {
Eric Liu495b2112016-09-19 17:40:32 +0000330 FileToReplacements->clear();
Eric Liu8bc24162017-03-21 12:41:59 +0000331 auto OldNsSplitted = splitSymbolName(OldNamespace);
332 auto NewNsSplitted = splitSymbolName(NewNamespace);
Eric Liu495b2112016-09-19 17:40:32 +0000333 // Calculates `DiffOldNamespace` and `DiffNewNamespace`.
334 while (!OldNsSplitted.empty() && !NewNsSplitted.empty() &&
335 OldNsSplitted.front() == NewNsSplitted.front()) {
336 OldNsSplitted.erase(OldNsSplitted.begin());
337 NewNsSplitted.erase(NewNsSplitted.begin());
338 }
339 DiffOldNamespace = joinNamespaces(OldNsSplitted);
340 DiffNewNamespace = joinNamespaces(NewNsSplitted);
Eric Liu7fccc992017-02-24 11:54:45 +0000341
342 for (const auto &Pattern : WhiteListedSymbolPatterns)
343 WhiteListedSymbolRegexes.emplace_back(Pattern);
Eric Liu495b2112016-09-19 17:40:32 +0000344}
345
Eric Liu495b2112016-09-19 17:40:32 +0000346void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
Eric Liu495b2112016-09-19 17:40:32 +0000347 std::string FullOldNs = "::" + OldNamespace;
Eric Liub9bf1b52016-11-08 22:44:17 +0000348 // Prefix is the outer-most namespace in DiffOldNamespace. For example, if the
349 // OldNamespace is "a::b::c" and DiffOldNamespace is "b::c", then Prefix will
350 // be "a::b". Declarations in this namespace will not be visible in the new
351 // namespace. If DiffOldNamespace is empty, Prefix will be a invalid name "-".
352 llvm::SmallVector<llvm::StringRef, 4> DiffOldNsSplitted;
Eric Liu2dd0e1b2016-12-05 11:17:04 +0000353 llvm::StringRef(DiffOldNamespace)
354 .split(DiffOldNsSplitted, "::", /*MaxSplit=*/-1,
355 /*KeepEmpty=*/false);
Eric Liub9bf1b52016-11-08 22:44:17 +0000356 std::string Prefix = "-";
357 if (!DiffOldNsSplitted.empty())
358 Prefix = (StringRef(FullOldNs).drop_back(DiffOldNamespace.size()) +
359 DiffOldNsSplitted.front())
360 .str();
361 auto IsInMovedNs =
362 allOf(hasAncestor(namespaceDecl(hasName(FullOldNs)).bind("ns_decl")),
363 isExpansionInFileMatching(FilePattern));
364 auto IsVisibleInNewNs = anyOf(
365 IsInMovedNs, unless(hasAncestor(namespaceDecl(hasName(Prefix)))));
366 // Match using declarations.
367 Finder->addMatcher(
368 usingDecl(isExpansionInFileMatching(FilePattern), IsVisibleInNewNs)
369 .bind("using"),
370 this);
371 // Match using namespace declarations.
372 Finder->addMatcher(usingDirectiveDecl(isExpansionInFileMatching(FilePattern),
373 IsVisibleInNewNs)
374 .bind("using_namespace"),
375 this);
Eric Liu180dac62016-12-23 10:47:09 +0000376 // Match namespace alias declarations.
377 Finder->addMatcher(namespaceAliasDecl(isExpansionInFileMatching(FilePattern),
378 IsVisibleInNewNs)
379 .bind("namespace_alias"),
380 this);
Eric Liub9bf1b52016-11-08 22:44:17 +0000381
382 // Match old namespace blocks.
Eric Liu495b2112016-09-19 17:40:32 +0000383 Finder->addMatcher(
384 namespaceDecl(hasName(FullOldNs), isExpansionInFileMatching(FilePattern))
385 .bind("old_ns"),
386 this);
387
Eric Liu41552d62016-12-07 14:20:52 +0000388 // Match class forward-declarations in the old namespace.
389 // Note that forward-declarations in classes are not matched.
390 Finder->addMatcher(cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition())),
391 IsInMovedNs, hasParent(namespaceDecl()))
392 .bind("class_fwd_decl"),
393 this);
394
395 // Match template class forward-declarations in the old namespace.
Eric Liu495b2112016-09-19 17:40:32 +0000396 Finder->addMatcher(
Eric Liu41552d62016-12-07 14:20:52 +0000397 classTemplateDecl(unless(hasDescendant(cxxRecordDecl(isDefinition()))),
398 IsInMovedNs, hasParent(namespaceDecl()))
399 .bind("template_class_fwd_decl"),
Eric Liu495b2112016-09-19 17:40:32 +0000400 this);
401
402 // Match references to types that are not defined in the old namespace.
403 // Forward-declarations in the old namespace are also matched since they will
404 // be moved back to the old namespace.
405 auto DeclMatcher = namedDecl(
406 hasAncestor(namespaceDecl()),
407 unless(anyOf(
Eric Liu912d0392016-09-27 12:54:48 +0000408 isImplicit(), hasAncestor(namespaceDecl(isAnonymous())),
Eric Liu495b2112016-09-19 17:40:32 +0000409 hasAncestor(cxxRecordDecl()),
410 allOf(IsInMovedNs, unless(cxxRecordDecl(unless(isDefinition())))))));
Eric Liu912d0392016-09-27 12:54:48 +0000411
Eric Liu8685c762016-12-07 17:04:07 +0000412 // Using shadow declarations in classes always refers to base class, which
413 // does not need to be qualified since it can be inferred from inheritance.
414 // Note that this does not match using alias declarations.
415 auto UsingShadowDeclInClass =
416 usingDecl(hasAnyUsingShadowDecl(decl()), hasParent(cxxRecordDecl()));
417
Eric Liu495b2112016-09-19 17:40:32 +0000418 // Match TypeLocs on the declaration. Carefully match only the outermost
Eric Liu8393cb02016-10-31 08:28:29 +0000419 // TypeLoc and template specialization arguments (which are not outermost)
420 // that are directly linked to types matching `DeclMatcher`. Nested name
421 // specifier locs are handled separately below.
Eric Liu495b2112016-09-19 17:40:32 +0000422 Finder->addMatcher(
423 typeLoc(IsInMovedNs,
424 loc(qualType(hasDeclaration(DeclMatcher.bind("from_decl")))),
Eric Liu8393cb02016-10-31 08:28:29 +0000425 unless(anyOf(hasParent(typeLoc(loc(qualType(
426 allOf(hasDeclaration(DeclMatcher),
427 unless(templateSpecializationType())))))),
Eric Liu8685c762016-12-07 17:04:07 +0000428 hasParent(nestedNameSpecifierLoc()),
429 hasAncestor(isImplicit()),
Eric Liub583a7e2017-10-16 08:20:10 +0000430 hasAncestor(UsingShadowDeclInClass),
431 hasAncestor(functionDecl(isDefaulted())))),
Eric Liu495b2112016-09-19 17:40:32 +0000432 hasAncestor(decl().bind("dc")))
433 .bind("type"),
434 this);
Eric Liu912d0392016-09-27 12:54:48 +0000435
Eric Liu68765a82016-09-21 15:06:12 +0000436 // Types in `UsingShadowDecl` is not matched by `typeLoc` above, so we need to
437 // special case it.
Eric Liu8685c762016-12-07 17:04:07 +0000438 // Since using declarations inside classes must have the base class in the
439 // nested name specifier, we leave it to the nested name specifier matcher.
440 Finder->addMatcher(usingDecl(IsInMovedNs, hasAnyUsingShadowDecl(decl()),
441 unless(UsingShadowDeclInClass))
Eric Liub9bf1b52016-11-08 22:44:17 +0000442 .bind("using_with_shadow"),
443 this);
Eric Liu912d0392016-09-27 12:54:48 +0000444
Eric Liuff51f012016-11-16 16:54:53 +0000445 // Handle types in nested name specifier. Specifiers that are in a TypeLoc
446 // matched above are not matched, e.g. "A::" in "A::A" is not matched since
447 // "A::A" would have already been fixed.
Eric Liu8685c762016-12-07 17:04:07 +0000448 Finder->addMatcher(
449 nestedNameSpecifierLoc(
450 hasAncestor(decl(IsInMovedNs).bind("dc")),
451 loc(nestedNameSpecifier(
452 specifiesType(hasDeclaration(DeclMatcher.bind("from_decl"))))),
453 unless(anyOf(hasAncestor(isImplicit()),
454 hasAncestor(UsingShadowDeclInClass),
Eric Liub583a7e2017-10-16 08:20:10 +0000455 hasAncestor(functionDecl(isDefaulted())),
Eric Liu8685c762016-12-07 17:04:07 +0000456 hasAncestor(typeLoc(loc(qualType(hasDeclaration(
457 decl(equalsBoundNode("from_decl"))))))))))
458 .bind("nested_specifier_loc"),
459 this);
Eric Liu12068d82016-09-22 11:54:00 +0000460
Eric Liuff51f012016-11-16 16:54:53 +0000461 // Matches base class initializers in constructors. TypeLocs of base class
462 // initializers do not need to be fixed. For example,
463 // class X : public a::b::Y {
464 // public:
465 // X() : Y::Y() {} // Y::Y do not need namespace specifier.
466 // };
467 Finder->addMatcher(
468 cxxCtorInitializer(isBaseInitializer()).bind("base_initializer"), this);
469
Eric Liu12068d82016-09-22 11:54:00 +0000470 // Handle function.
Eric Liu912d0392016-09-27 12:54:48 +0000471 // Only handle functions that are defined in a namespace excluding member
472 // function, static methods (qualified by nested specifier), and functions
473 // defined in the global namespace.
Eric Liu12068d82016-09-22 11:54:00 +0000474 // Note that the matcher does not exclude calls to out-of-line static method
475 // definitions, so we need to exclude them in the callback handler.
Eric Liu912d0392016-09-27 12:54:48 +0000476 auto FuncMatcher =
477 functionDecl(unless(anyOf(cxxMethodDecl(), IsInMovedNs,
478 hasAncestor(namespaceDecl(isAnonymous())),
479 hasAncestor(cxxRecordDecl()))),
480 hasParent(namespaceDecl()));
Eric Liu9a543972018-03-15 14:45:02 +0000481 Finder->addMatcher(
482 expr(allOf(hasAncestor(decl().bind("dc")), IsInMovedNs,
483 unless(hasAncestor(isImplicit())),
484 anyOf(callExpr(callee(FuncMatcher)).bind("call"),
485 declRefExpr(to(FuncMatcher.bind("func_decl")))
486 .bind("func_ref")))),
487 this);
Eric Liu159f0132016-09-30 04:32:39 +0000488
489 auto GlobalVarMatcher = varDecl(
490 hasGlobalStorage(), hasParent(namespaceDecl()),
491 unless(anyOf(IsInMovedNs, hasAncestor(namespaceDecl(isAnonymous())))));
492 Finder->addMatcher(declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
493 to(GlobalVarMatcher.bind("var_decl")))
494 .bind("var_ref"),
495 this);
Eric Liu0325a772017-02-02 17:40:38 +0000496
497 // Handle unscoped enum constant.
498 auto UnscopedEnumMatcher = enumConstantDecl(hasParent(enumDecl(
499 hasParent(namespaceDecl()),
500 unless(anyOf(isScoped(), IsInMovedNs, hasAncestor(cxxRecordDecl()),
501 hasAncestor(namespaceDecl(isAnonymous())))))));
502 Finder->addMatcher(
503 declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
504 to(UnscopedEnumMatcher.bind("enum_const_decl")))
505 .bind("enum_const_ref"),
506 this);
Eric Liu495b2112016-09-19 17:40:32 +0000507}
508
509void ChangeNamespaceTool::run(
510 const ast_matchers::MatchFinder::MatchResult &Result) {
Eric Liub9bf1b52016-11-08 22:44:17 +0000511 if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) {
512 UsingDecls.insert(Using);
513 } else if (const auto *UsingNamespace =
514 Result.Nodes.getNodeAs<UsingDirectiveDecl>(
515 "using_namespace")) {
516 UsingNamespaceDecls.insert(UsingNamespace);
Eric Liu180dac62016-12-23 10:47:09 +0000517 } else if (const auto *NamespaceAlias =
518 Result.Nodes.getNodeAs<NamespaceAliasDecl>(
519 "namespace_alias")) {
520 NamespaceAliasDecls.insert(NamespaceAlias);
Eric Liub9bf1b52016-11-08 22:44:17 +0000521 } else if (const auto *NsDecl =
522 Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
Eric Liu495b2112016-09-19 17:40:32 +0000523 moveOldNamespace(Result, NsDecl);
524 } else if (const auto *FwdDecl =
Eric Liu41552d62016-12-07 14:20:52 +0000525 Result.Nodes.getNodeAs<CXXRecordDecl>("class_fwd_decl")) {
526 moveClassForwardDeclaration(Result, cast<NamedDecl>(FwdDecl));
527 } else if (const auto *TemplateFwdDecl =
528 Result.Nodes.getNodeAs<ClassTemplateDecl>(
529 "template_class_fwd_decl")) {
530 moveClassForwardDeclaration(Result, cast<NamedDecl>(TemplateFwdDecl));
Eric Liub9bf1b52016-11-08 22:44:17 +0000531 } else if (const auto *UsingWithShadow =
532 Result.Nodes.getNodeAs<UsingDecl>("using_with_shadow")) {
533 fixUsingShadowDecl(Result, UsingWithShadow);
Eric Liu68765a82016-09-21 15:06:12 +0000534 } else if (const auto *Specifier =
535 Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
536 "nested_specifier_loc")) {
537 SourceLocation Start = Specifier->getBeginLoc();
Eric Liuc265b022016-12-01 17:25:55 +0000538 SourceLocation End = endLocationForType(Specifier->getTypeLoc());
Eric Liu68765a82016-09-21 15:06:12 +0000539 fixTypeLoc(Result, Start, End, Specifier->getTypeLoc());
Eric Liuff51f012016-11-16 16:54:53 +0000540 } else if (const auto *BaseInitializer =
541 Result.Nodes.getNodeAs<CXXCtorInitializer>(
542 "base_initializer")) {
543 BaseCtorInitializerTypeLocs.push_back(
544 BaseInitializer->getTypeSourceInfo()->getTypeLoc());
Eric Liu12068d82016-09-22 11:54:00 +0000545 } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) {
Eric Liu26cf68a2016-12-15 10:42:35 +0000546 // This avoids fixing types with record types as qualifier, which is not
547 // filtered by matchers in some cases, e.g. the type is templated. We should
548 // handle the record type qualifier instead.
Eric Liu0c0aea02016-12-15 13:02:41 +0000549 TypeLoc Loc = *TLoc;
550 while (Loc.getTypeLocClass() == TypeLoc::Qualified)
551 Loc = Loc.getNextTypeLoc();
552 if (Loc.getTypeLocClass() == TypeLoc::Elaborated) {
Eric Liu26cf68a2016-12-15 10:42:35 +0000553 NestedNameSpecifierLoc NestedNameSpecifier =
Eric Liu0c0aea02016-12-15 13:02:41 +0000554 Loc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
Eric Liu5a6d57c2017-12-08 10:06:16 +0000555 // This happens for friend declaration of a base class with injected class
556 // name.
557 if (!NestedNameSpecifier.getNestedNameSpecifier())
558 return;
Eric Liu26cf68a2016-12-15 10:42:35 +0000559 const Type *SpecifierType =
560 NestedNameSpecifier.getNestedNameSpecifier()->getAsType();
561 if (SpecifierType && SpecifierType->isRecordType())
562 return;
563 }
Eric Liu0c0aea02016-12-15 13:02:41 +0000564 fixTypeLoc(Result, startLocationForType(Loc), endLocationForType(Loc), Loc);
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +0000565 } else if (const auto *VarRef =
566 Result.Nodes.getNodeAs<DeclRefExpr>("var_ref")) {
Eric Liu159f0132016-09-30 04:32:39 +0000567 const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var_decl");
568 assert(Var);
569 if (Var->getCanonicalDecl()->isStaticDataMember())
570 return;
Eric Liuda22b3c2016-11-29 14:15:14 +0000571 const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
Eric Liu159f0132016-09-30 04:32:39 +0000572 assert(Context && "Empty decl context.");
Eric Liuda22b3c2016-11-29 14:15:14 +0000573 fixDeclRefExpr(Result, Context->getDeclContext(),
574 llvm::cast<NamedDecl>(Var), VarRef);
Eric Liu0325a772017-02-02 17:40:38 +0000575 } else if (const auto *EnumConstRef =
576 Result.Nodes.getNodeAs<DeclRefExpr>("enum_const_ref")) {
577 // Do not rename the reference if it is already scoped by the EnumDecl name.
578 if (EnumConstRef->hasQualifier() &&
Eric Liu28c30ce2017-02-02 19:46:12 +0000579 EnumConstRef->getQualifier()->getKind() ==
580 NestedNameSpecifier::SpecifierKind::TypeSpec &&
Eric Liu0325a772017-02-02 17:40:38 +0000581 EnumConstRef->getQualifier()->getAsType()->isEnumeralType())
582 return;
583 const auto *EnumConstDecl =
584 Result.Nodes.getNodeAs<EnumConstantDecl>("enum_const_decl");
585 assert(EnumConstDecl);
586 const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
587 assert(Context && "Empty decl context.");
588 // FIXME: this would qualify "ns::VALUE" as "ns::EnumValue::VALUE". Fix it
589 // if it turns out to be an issue.
590 fixDeclRefExpr(Result, Context->getDeclContext(),
591 llvm::cast<NamedDecl>(EnumConstDecl), EnumConstRef);
Eric Liuda22b3c2016-11-29 14:15:14 +0000592 } else if (const auto *FuncRef =
593 Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
Eric Liue3f35e42016-12-20 14:39:04 +0000594 // If this reference has been processed as a function call, we do not
595 // process it again.
596 if (ProcessedFuncRefs.count(FuncRef))
597 return;
598 ProcessedFuncRefs.insert(FuncRef);
Eric Liuda22b3c2016-11-29 14:15:14 +0000599 const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
600 assert(Func);
601 const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
602 assert(Context && "Empty decl context.");
603 fixDeclRefExpr(Result, Context->getDeclContext(),
604 llvm::cast<NamedDecl>(Func), FuncRef);
Eric Liu12068d82016-09-22 11:54:00 +0000605 } else {
Eric Liuda22b3c2016-11-29 14:15:14 +0000606 const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +0000607 assert(Call != nullptr && "Expecting callback for CallExpr.");
Eric Liue3f35e42016-12-20 14:39:04 +0000608 const auto *CalleeFuncRef =
609 llvm::cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit());
610 ProcessedFuncRefs.insert(CalleeFuncRef);
Eric Liuda22b3c2016-11-29 14:15:14 +0000611 const FunctionDecl *Func = Call->getDirectCallee();
Eric Liu12068d82016-09-22 11:54:00 +0000612 assert(Func != nullptr);
Eric Liue3f35e42016-12-20 14:39:04 +0000613 // FIXME: ignore overloaded operators. This would miss cases where operators
614 // are called by qualified names (i.e. "ns::operator <"). Ignore such
615 // cases for now.
616 if (Func->isOverloadedOperator())
617 return;
Eric Liu12068d82016-09-22 11:54:00 +0000618 // Ignore out-of-line static methods since they will be handled by nested
619 // name specifiers.
620 if (Func->getCanonicalDecl()->getStorageClass() ==
Eric Liuda22b3c2016-11-29 14:15:14 +0000621 StorageClass::SC_Static &&
Eric Liu12068d82016-09-22 11:54:00 +0000622 Func->isOutOfLine())
623 return;
Eric Liuda22b3c2016-11-29 14:15:14 +0000624 const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
Eric Liu12068d82016-09-22 11:54:00 +0000625 assert(Context && "Empty decl context.");
Eric Liuda22b3c2016-11-29 14:15:14 +0000626 SourceRange CalleeRange = Call->getCallee()->getSourceRange();
Eric Liub9bf1b52016-11-08 22:44:17 +0000627 replaceQualifiedSymbolInDeclContext(
628 Result, Context->getDeclContext(), CalleeRange.getBegin(),
Eric Liu231c6552016-11-10 18:15:34 +0000629 CalleeRange.getEnd(), llvm::cast<NamedDecl>(Func));
Eric Liu495b2112016-09-19 17:40:32 +0000630 }
631}
632
Eric Liu73f49fd2016-10-12 12:34:18 +0000633static SourceLocation getLocAfterNamespaceLBrace(const NamespaceDecl *NsDecl,
634 const SourceManager &SM,
635 const LangOptions &LangOpts) {
636 std::unique_ptr<Lexer> Lex =
Stephen Kelly43465bf2018-08-09 22:42:26 +0000637 getLexerStartingFromLoc(NsDecl->getBeginLoc(), SM, LangOpts);
Eric Liu73f49fd2016-10-12 12:34:18 +0000638 assert(Lex.get() &&
639 "Failed to create lexer from the beginning of namespace.");
640 if (!Lex.get())
641 return SourceLocation();
642 Token Tok;
643 while (!Lex->LexFromRawLexer(Tok) && Tok.isNot(tok::TokenKind::l_brace)) {
644 }
645 return Tok.isNot(tok::TokenKind::l_brace)
646 ? SourceLocation()
647 : Tok.getEndLoc().getLocWithOffset(1);
648}
649
Eric Liu495b2112016-09-19 17:40:32 +0000650// Stores information about a moved namespace in `MoveNamespaces` and leaves
651// the actual movement to `onEndOfTranslationUnit()`.
652void ChangeNamespaceTool::moveOldNamespace(
653 const ast_matchers::MatchFinder::MatchResult &Result,
654 const NamespaceDecl *NsDecl) {
655 // If the namespace is empty, do nothing.
656 if (Decl::castToDeclContext(NsDecl)->decls_empty())
657 return;
658
Eric Liuee5104b2017-01-04 14:49:08 +0000659 const SourceManager &SM = *Result.SourceManager;
Eric Liu495b2112016-09-19 17:40:32 +0000660 // Get the range of the code in the old namespace.
Eric Liuee5104b2017-01-04 14:49:08 +0000661 SourceLocation Start =
662 getLocAfterNamespaceLBrace(NsDecl, SM, Result.Context->getLangOpts());
Eric Liu73f49fd2016-10-12 12:34:18 +0000663 assert(Start.isValid() && "Can't find l_brace for namespace.");
Eric Liu495b2112016-09-19 17:40:32 +0000664 MoveNamespace MoveNs;
Eric Liuee5104b2017-01-04 14:49:08 +0000665 MoveNs.Offset = SM.getFileOffset(Start);
666 // The range of the moved namespace is from the location just past the left
667 // brace to the location right before the right brace.
668 MoveNs.Length = SM.getFileOffset(NsDecl->getRBraceLoc()) - MoveNs.Offset;
Eric Liu495b2112016-09-19 17:40:32 +0000669
670 // Insert the new namespace after `DiffOldNamespace`. For example, if
671 // `OldNamespace` is "a::b::c" and `NewNamespace` is `a::x::y`, then
672 // "x::y" will be inserted inside the existing namespace "a" and after "a::b".
673 // `OuterNs` is the first namespace in `DiffOldNamespace`, e.g. "namespace b"
674 // in the above example.
Eric Liu6aa94162016-11-10 18:29:01 +0000675 // If there is no outer namespace (i.e. DiffOldNamespace is empty), the new
676 // namespace will be a nested namespace in the old namespace.
Eric Liu495b2112016-09-19 17:40:32 +0000677 const NamespaceDecl *OuterNs = getOuterNamespace(NsDecl, DiffOldNamespace);
Eric Liu6aa94162016-11-10 18:29:01 +0000678 SourceLocation InsertionLoc = Start;
679 if (OuterNs) {
Eric Liuee5104b2017-01-04 14:49:08 +0000680 SourceLocation LocAfterNs = getStartOfNextLine(
681 OuterNs->getRBraceLoc(), SM, Result.Context->getLangOpts());
Eric Liu6aa94162016-11-10 18:29:01 +0000682 assert(LocAfterNs.isValid() &&
683 "Failed to get location after DiffOldNamespace");
684 InsertionLoc = LocAfterNs;
685 }
Eric Liuee5104b2017-01-04 14:49:08 +0000686 MoveNs.InsertionOffset = SM.getFileOffset(SM.getSpellingLoc(InsertionLoc));
687 MoveNs.FID = SM.getFileID(Start);
Eric Liucc83c662016-09-19 17:58:59 +0000688 MoveNs.SourceMgr = Result.SourceManager;
Eric Liuee5104b2017-01-04 14:49:08 +0000689 MoveNamespaces[SM.getFilename(Start)].push_back(MoveNs);
Eric Liu495b2112016-09-19 17:40:32 +0000690}
691
692// Removes a class forward declaration from the code in the moved namespace and
693// creates an `InsertForwardDeclaration` to insert the forward declaration back
694// into the old namespace after moving code from the old namespace to the new
695// namespace.
696// For example, changing "a" to "x":
697// Old code:
698// namespace a {
699// class FWD;
700// class A { FWD *fwd; }
701// } // a
702// New code:
703// namespace a {
704// class FWD;
705// } // a
706// namespace x {
707// class A { a::FWD *fwd; }
708// } // x
709void ChangeNamespaceTool::moveClassForwardDeclaration(
710 const ast_matchers::MatchFinder::MatchResult &Result,
Eric Liu41552d62016-12-07 14:20:52 +0000711 const NamedDecl *FwdDecl) {
Stephen Kelly43465bf2018-08-09 22:42:26 +0000712 SourceLocation Start = FwdDecl->getBeginLoc();
Eric Liu495b2112016-09-19 17:40:32 +0000713 SourceLocation End = FwdDecl->getLocEnd();
Eric Liu41367152017-03-01 10:29:39 +0000714 const SourceManager &SM = *Result.SourceManager;
Eric Liu495b2112016-09-19 17:40:32 +0000715 SourceLocation AfterSemi = Lexer::findLocationAfterToken(
Eric Liu41367152017-03-01 10:29:39 +0000716 End, tok::semi, SM, Result.Context->getLangOpts(),
Eric Liu495b2112016-09-19 17:40:32 +0000717 /*SkipTrailingWhitespaceAndNewLine=*/true);
718 if (AfterSemi.isValid())
719 End = AfterSemi.getLocWithOffset(-1);
720 // Delete the forward declaration from the code to be moved.
Eric Liu41367152017-03-01 10:29:39 +0000721 addReplacementOrDie(Start, End, "", SM, &FileToReplacements);
Eric Liu495b2112016-09-19 17:40:32 +0000722 llvm::StringRef Code = Lexer::getSourceText(
Eric Liu41367152017-03-01 10:29:39 +0000723 CharSourceRange::getTokenRange(SM.getSpellingLoc(Start),
724 SM.getSpellingLoc(End)),
725 SM, Result.Context->getLangOpts());
Eric Liu495b2112016-09-19 17:40:32 +0000726 // Insert the forward declaration back into the old namespace after moving the
727 // code from old namespace to new namespace.
728 // Insertion information is stored in `InsertFwdDecls` and actual
729 // insertion will be performed in `onEndOfTranslationUnit`.
730 // Get the (old) namespace that contains the forward declaration.
731 const auto *NsDecl = Result.Nodes.getNodeAs<NamespaceDecl>("ns_decl");
732 // The namespace contains the forward declaration, so it must not be empty.
733 assert(!NsDecl->decls_empty());
Eric Liu41367152017-03-01 10:29:39 +0000734 const auto Insertion = createInsertion(
735 getLocAfterNamespaceLBrace(NsDecl, SM, Result.Context->getLangOpts()),
736 Code, SM);
Eric Liu495b2112016-09-19 17:40:32 +0000737 InsertForwardDeclaration InsertFwd;
738 InsertFwd.InsertionOffset = Insertion.getOffset();
739 InsertFwd.ForwardDeclText = Insertion.getReplacementText().str();
740 InsertFwdDecls[Insertion.getFilePath()].push_back(InsertFwd);
741}
742
Eric Liub9bf1b52016-11-08 22:44:17 +0000743// Replaces a qualified symbol (in \p DeclCtx) that refers to a declaration \p
744// FromDecl with the shortest qualified name possible when the reference is in
745// `NewNamespace`.
Eric Liu495b2112016-09-19 17:40:32 +0000746void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
Eric Liub9bf1b52016-11-08 22:44:17 +0000747 const ast_matchers::MatchFinder::MatchResult &Result,
748 const DeclContext *DeclCtx, SourceLocation Start, SourceLocation End,
749 const NamedDecl *FromDecl) {
750 const auto *NsDeclContext = DeclCtx->getEnclosingNamespaceContext();
Eric Liu4fe99e12016-12-14 17:01:52 +0000751 if (llvm::isa<TranslationUnitDecl>(NsDeclContext)) {
752 // This should not happen in usual unless the TypeLoc is in function type
753 // parameters, e.g `std::function<void(T)>`. In this case, DeclContext of
754 // `T` will be the translation unit. We simply use fully-qualified name
755 // here.
756 // Note that `FromDecl` must not be defined in the old namespace (according
757 // to `DeclMatcher`), so its fully-qualified name will not change after
758 // changing the namespace.
759 addReplacementOrDie(Start, End, FromDecl->getQualifiedNameAsString(),
760 *Result.SourceManager, &FileToReplacements);
761 return;
762 }
Eric Liu231c6552016-11-10 18:15:34 +0000763 const auto *NsDecl = llvm::cast<NamespaceDecl>(NsDeclContext);
Eric Liu495b2112016-09-19 17:40:32 +0000764 // Calculate the name of the `NsDecl` after it is moved to new namespace.
765 std::string OldNs = NsDecl->getQualifiedNameAsString();
766 llvm::StringRef Postfix = OldNs;
767 bool Consumed = Postfix.consume_front(OldNamespace);
768 assert(Consumed && "Expect OldNS to start with OldNamespace.");
769 (void)Consumed;
770 const std::string NewNs = (NewNamespace + Postfix).str();
771
772 llvm::StringRef NestedName = Lexer::getSourceText(
773 CharSourceRange::getTokenRange(
774 Result.SourceManager->getSpellingLoc(Start),
775 Result.SourceManager->getSpellingLoc(End)),
776 *Result.SourceManager, Result.Context->getLangOpts());
Eric Liub9bf1b52016-11-08 22:44:17 +0000777 std::string FromDeclName = FromDecl->getQualifiedNameAsString();
Eric Liu7fccc992017-02-24 11:54:45 +0000778 for (llvm::Regex &RE : WhiteListedSymbolRegexes)
779 if (RE.match(FromDeclName))
780 return;
Eric Liu495b2112016-09-19 17:40:32 +0000781 std::string ReplaceName =
Eric Liub9bf1b52016-11-08 22:44:17 +0000782 getShortestQualifiedNameInNamespace(FromDeclName, NewNs);
783 // Checks if there is any using namespace declarations that can shorten the
784 // qualified name.
785 for (const auto *UsingNamespace : UsingNamespaceDecls) {
786 if (!isDeclVisibleAtLocation(*Result.SourceManager, UsingNamespace, DeclCtx,
787 Start))
788 continue;
789 StringRef FromDeclNameRef = FromDeclName;
790 if (FromDeclNameRef.consume_front(UsingNamespace->getNominatedNamespace()
791 ->getQualifiedNameAsString())) {
792 FromDeclNameRef = FromDeclNameRef.drop_front(2);
793 if (FromDeclNameRef.size() < ReplaceName.size())
794 ReplaceName = FromDeclNameRef;
795 }
796 }
Eric Liu180dac62016-12-23 10:47:09 +0000797 // Checks if there is any namespace alias declarations that can shorten the
798 // qualified name.
799 for (const auto *NamespaceAlias : NamespaceAliasDecls) {
800 if (!isDeclVisibleAtLocation(*Result.SourceManager, NamespaceAlias, DeclCtx,
801 Start))
802 continue;
803 StringRef FromDeclNameRef = FromDeclName;
804 if (FromDeclNameRef.consume_front(
805 NamespaceAlias->getNamespace()->getQualifiedNameAsString() +
806 "::")) {
807 std::string AliasName = NamespaceAlias->getNameAsString();
808 std::string AliasQualifiedName =
809 NamespaceAlias->getQualifiedNameAsString();
810 // We only consider namespace aliases define in the global namepspace or
811 // in namespaces that are directly visible from the reference, i.e.
812 // ancestor of the `OldNs`. Note that declarations in ancestor namespaces
813 // but not visible in the new namespace is filtered out by
814 // "IsVisibleInNewNs" matcher.
815 if (AliasQualifiedName != AliasName) {
816 // The alias is defined in some namespace.
817 assert(StringRef(AliasQualifiedName).endswith("::" + AliasName));
818 llvm::StringRef AliasNs =
819 StringRef(AliasQualifiedName).drop_back(AliasName.size() + 2);
820 if (!llvm::StringRef(OldNs).startswith(AliasNs))
821 continue;
822 }
823 std::string NameWithAliasNamespace =
824 (AliasName + "::" + FromDeclNameRef).str();
825 if (NameWithAliasNamespace.size() < ReplaceName.size())
826 ReplaceName = NameWithAliasNamespace;
827 }
828 }
Eric Liub9bf1b52016-11-08 22:44:17 +0000829 // Checks if there is any using shadow declarations that can shorten the
830 // qualified name.
831 bool Matched = false;
832 for (const UsingDecl *Using : UsingDecls) {
833 if (Matched)
834 break;
835 if (isDeclVisibleAtLocation(*Result.SourceManager, Using, DeclCtx, Start)) {
836 for (const auto *UsingShadow : Using->shadows()) {
837 const auto *TargetDecl = UsingShadow->getTargetDecl();
Eric Liuae7de712017-02-02 15:29:54 +0000838 if (TargetDecl->getQualifiedNameAsString() ==
839 FromDecl->getQualifiedNameAsString()) {
Eric Liub9bf1b52016-11-08 22:44:17 +0000840 ReplaceName = FromDecl->getNameAsString();
841 Matched = true;
842 break;
843 }
844 }
845 }
846 }
Eric Liu495b2112016-09-19 17:40:32 +0000847 // If the new nested name in the new namespace is the same as it was in the
848 // old namespace, we don't create replacement.
Eric Liu91229162017-01-26 16:31:32 +0000849 if (NestedName == ReplaceName ||
850 (NestedName.startswith("::") && NestedName.drop_front(2) == ReplaceName))
Eric Liu495b2112016-09-19 17:40:32 +0000851 return;
Eric Liu97f87ad2016-12-07 20:08:02 +0000852 // If the reference need to be fully-qualified, add a leading "::" unless
853 // NewNamespace is the global namespace.
Eric Liu8bc24162017-03-21 12:41:59 +0000854 if (ReplaceName == FromDeclName && !NewNamespace.empty() &&
855 conflictInNamespace(ReplaceName, NewNamespace))
Eric Liu97f87ad2016-12-07 20:08:02 +0000856 ReplaceName = "::" + ReplaceName;
Eric Liu4fe99e12016-12-14 17:01:52 +0000857 addReplacementOrDie(Start, End, ReplaceName, *Result.SourceManager,
858 &FileToReplacements);
Eric Liu495b2112016-09-19 17:40:32 +0000859}
860
861// Replace the [Start, End] of `Type` with the shortest qualified name when the
862// `Type` is in `NewNamespace`.
863void ChangeNamespaceTool::fixTypeLoc(
864 const ast_matchers::MatchFinder::MatchResult &Result, SourceLocation Start,
865 SourceLocation End, TypeLoc Type) {
866 // FIXME: do not rename template parameter.
867 if (Start.isInvalid() || End.isInvalid())
868 return;
Eric Liuff51f012016-11-16 16:54:53 +0000869 // Types of CXXCtorInitializers do not need to be fixed.
870 if (llvm::is_contained(BaseCtorInitializerTypeLocs, Type))
871 return;
Eric Liu284b97c2017-03-17 14:05:39 +0000872 if (isTemplateParameter(Type))
873 return;
Eric Liu495b2112016-09-19 17:40:32 +0000874 // The declaration which this TypeLoc refers to.
875 const auto *FromDecl = Result.Nodes.getNodeAs<NamedDecl>("from_decl");
876 // `hasDeclaration` gives underlying declaration, but if the type is
877 // a typedef type, we need to use the typedef type instead.
Eric Liu26cf68a2016-12-15 10:42:35 +0000878 auto IsInMovedNs = [&](const NamedDecl *D) {
879 if (!llvm::StringRef(D->getQualifiedNameAsString())
880 .startswith(OldNamespace + "::"))
881 return false;
Stephen Kelly43465bf2018-08-09 22:42:26 +0000882 auto ExpansionLoc = Result.SourceManager->getExpansionLoc(D->getBeginLoc());
Eric Liu26cf68a2016-12-15 10:42:35 +0000883 if (ExpansionLoc.isInvalid())
884 return false;
885 llvm::StringRef Filename = Result.SourceManager->getFilename(ExpansionLoc);
886 return FilePatternRE.match(Filename);
887 };
888 // Make `FromDecl` the immediate declaration that `Type` refers to, i.e. if
889 // `Type` is an alias type, we make `FromDecl` the type alias declaration.
890 // Also, don't fix the \p Type if it refers to a type alias decl in the moved
891 // namespace since the alias decl will be moved along with the type reference.
Eric Liu32158862016-11-14 19:37:55 +0000892 if (auto *Typedef = Type.getType()->getAs<TypedefType>()) {
Eric Liu495b2112016-09-19 17:40:32 +0000893 FromDecl = Typedef->getDecl();
Eric Liu32158862016-11-14 19:37:55 +0000894 if (IsInMovedNs(FromDecl))
895 return;
Eric Liu26cf68a2016-12-15 10:42:35 +0000896 } else if (auto *TemplateType =
897 Type.getType()->getAs<TemplateSpecializationType>()) {
898 if (TemplateType->isTypeAlias()) {
899 FromDecl = TemplateType->getTemplateName().getAsTemplateDecl();
900 if (IsInMovedNs(FromDecl))
901 return;
902 }
Eric Liu32158862016-11-14 19:37:55 +0000903 }
Piotr Padlewski08124b12016-12-14 15:29:23 +0000904 const auto *DeclCtx = Result.Nodes.getNodeAs<Decl>("dc");
Eric Liu495b2112016-09-19 17:40:32 +0000905 assert(DeclCtx && "Empty decl context.");
Eric Liub9bf1b52016-11-08 22:44:17 +0000906 replaceQualifiedSymbolInDeclContext(Result, DeclCtx->getDeclContext(), Start,
907 End, FromDecl);
Eric Liu495b2112016-09-19 17:40:32 +0000908}
909
Eric Liu68765a82016-09-21 15:06:12 +0000910void ChangeNamespaceTool::fixUsingShadowDecl(
911 const ast_matchers::MatchFinder::MatchResult &Result,
912 const UsingDecl *UsingDeclaration) {
Stephen Kelly43465bf2018-08-09 22:42:26 +0000913 SourceLocation Start = UsingDeclaration->getBeginLoc();
Eric Liu68765a82016-09-21 15:06:12 +0000914 SourceLocation End = UsingDeclaration->getLocEnd();
Mandeep Singh Grang7c7ea7d2016-11-08 07:50:19 +0000915 if (Start.isInvalid() || End.isInvalid())
916 return;
Eric Liu68765a82016-09-21 15:06:12 +0000917
918 assert(UsingDeclaration->shadow_size() > 0);
919 // FIXME: it might not be always accurate to use the first using-decl.
920 const NamedDecl *TargetDecl =
921 UsingDeclaration->shadow_begin()->getTargetDecl();
922 std::string TargetDeclName = TargetDecl->getQualifiedNameAsString();
923 // FIXME: check if target_decl_name is in moved ns, which doesn't make much
924 // sense. If this happens, we need to use name with the new namespace.
925 // Use fully qualified name in UsingDecl for now.
Eric Liu4fe99e12016-12-14 17:01:52 +0000926 addReplacementOrDie(Start, End, "using ::" + TargetDeclName,
927 *Result.SourceManager, &FileToReplacements);
Eric Liu68765a82016-09-21 15:06:12 +0000928}
929
Eric Liuda22b3c2016-11-29 14:15:14 +0000930void ChangeNamespaceTool::fixDeclRefExpr(
931 const ast_matchers::MatchFinder::MatchResult &Result,
932 const DeclContext *UseContext, const NamedDecl *From,
933 const DeclRefExpr *Ref) {
934 SourceRange RefRange = Ref->getSourceRange();
935 replaceQualifiedSymbolInDeclContext(Result, UseContext, RefRange.getBegin(),
936 RefRange.getEnd(), From);
937}
938
Eric Liu495b2112016-09-19 17:40:32 +0000939void ChangeNamespaceTool::onEndOfTranslationUnit() {
940 // Move namespace blocks and insert forward declaration to old namespace.
941 for (const auto &FileAndNsMoves : MoveNamespaces) {
942 auto &NsMoves = FileAndNsMoves.second;
943 if (NsMoves.empty())
944 continue;
945 const std::string &FilePath = FileAndNsMoves.first;
946 auto &Replaces = FileToReplacements[FilePath];
Eric Liucc83c662016-09-19 17:58:59 +0000947 auto &SM = *NsMoves.begin()->SourceMgr;
948 llvm::StringRef Code = SM.getBufferData(NsMoves.begin()->FID);
Eric Liu495b2112016-09-19 17:40:32 +0000949 auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
950 if (!ChangedCode) {
951 llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
952 continue;
953 }
954 // Replacements on the changed code for moving namespaces and inserting
955 // forward declarations to old namespaces.
956 tooling::Replacements NewReplacements;
957 // Cut the changed code from the old namespace and paste the code in the new
958 // namespace.
959 for (const auto &NsMove : NsMoves) {
960 // Calculate the range of the old namespace block in the changed
961 // code.
962 const unsigned NewOffset = Replaces.getShiftedCodePosition(NsMove.Offset);
963 const unsigned NewLength =
964 Replaces.getShiftedCodePosition(NsMove.Offset + NsMove.Length) -
965 NewOffset;
966 tooling::Replacement Deletion(FilePath, NewOffset, NewLength, "");
967 std::string MovedCode = ChangedCode->substr(NewOffset, NewLength);
968 std::string MovedCodeWrappedInNewNs =
969 wrapCodeInNamespace(DiffNewNamespace, MovedCode);
970 // Calculate the new offset at which the code will be inserted in the
971 // changed code.
972 unsigned NewInsertionOffset =
973 Replaces.getShiftedCodePosition(NsMove.InsertionOffset);
974 tooling::Replacement Insertion(FilePath, NewInsertionOffset, 0,
975 MovedCodeWrappedInNewNs);
976 addOrMergeReplacement(Deletion, &NewReplacements);
977 addOrMergeReplacement(Insertion, &NewReplacements);
978 }
979 // After moving namespaces, insert forward declarations back to old
980 // namespaces.
981 const auto &FwdDeclInsertions = InsertFwdDecls[FilePath];
982 for (const auto &FwdDeclInsertion : FwdDeclInsertions) {
983 unsigned NewInsertionOffset =
984 Replaces.getShiftedCodePosition(FwdDeclInsertion.InsertionOffset);
985 tooling::Replacement Insertion(FilePath, NewInsertionOffset, 0,
986 FwdDeclInsertion.ForwardDeclText);
987 addOrMergeReplacement(Insertion, &NewReplacements);
988 }
989 // Add replacements referring to the changed code to existing replacements,
990 // which refers to the original code.
991 Replaces = Replaces.merge(NewReplacements);
Eric Liufa63e982018-08-02 10:30:56 +0000992 auto Style =
993 format::getStyle(format::DefaultFormatStyle, FilePath, FallbackStyle);
Antonio Maiorano0d7d9c22017-01-17 00:13:32 +0000994 if (!Style) {
995 llvm::errs() << llvm::toString(Style.takeError()) << "\n";
996 continue;
997 }
Eric Liu495b2112016-09-19 17:40:32 +0000998 // Clean up old namespaces if there is nothing in it after moving.
999 auto CleanReplacements =
Antonio Maiorano0d7d9c22017-01-17 00:13:32 +00001000 format::cleanupAroundReplacements(Code, Replaces, *Style);
Eric Liu495b2112016-09-19 17:40:32 +00001001 if (!CleanReplacements) {
1002 llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
1003 continue;
1004 }
1005 FileToReplacements[FilePath] = *CleanReplacements;
1006 }
Eric Liuc265b022016-12-01 17:25:55 +00001007
1008 // Make sure we don't generate replacements for files that do not match
1009 // FilePattern.
1010 for (auto &Entry : FileToReplacements)
1011 if (!FilePatternRE.match(Entry.first))
1012 Entry.second.clear();
Eric Liu495b2112016-09-19 17:40:32 +00001013}
1014
1015} // namespace change_namespace
1016} // namespace clang