10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
20 SourceLocation Loc1, SourceLocation Loc2) {
21 return Loc1.isFileID() && Loc2.isFileID() &&
22 Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
26 return ND.isAnonymousNamespace() || ND.isInlineNamespace();
30 NamespaceDecl::decl_range Decls = ND.decls();
31 if (std::distance(Decls.begin(), Decls.end()) != 1)
34 const auto *ChildNamespace = dyn_cast<const NamespaceDecl>(*Decls.begin());
39 const SourceRange &ReplacementRange,
40 const SourceManager &Sources,
43 CharSourceRange TextRange =
44 Lexer::getAsCharRange(ReplacementRange, Sources,
LangOpts);
45 StringRef CurrentNamespacesText =
47 return CurrentNamespacesText.count(
':') == (NumCandidates - 1) * 2;
50 ConcatNestedNamespacesCheck::NamespaceString
51 ConcatNestedNamespacesCheck::concatNamespaces() {
52 NamespaceString Result(
"namespace ");
53 Result.append(Namespaces.front()->getName());
55 std::for_each(std::next(Namespaces.begin()), Namespaces.end(),
56 [&Result](
const NamespaceDecl *ND) {
58 Result.append(ND->getName());
65 ast_matchers::MatchFinder *Finder) {
66 Finder->addMatcher(ast_matchers::namespaceDecl().bind(
"namespace"),
this);
69 void ConcatNestedNamespacesCheck::reportDiagnostic(
70 const SourceRange &FrontReplacement,
const SourceRange &BackReplacement) {
71 diag(Namespaces.front()->getBeginLoc(),
73 << FixItHint::CreateReplacement(FrontReplacement, concatNamespaces())
74 << FixItHint::CreateReplacement(BackReplacement,
"}");
78 const ast_matchers::MatchFinder::MatchResult &Result) {
79 const NamespaceDecl &ND = *Result.Nodes.getNodeAs<NamespaceDecl>(
"namespace");
80 const SourceManager &Sources = *Result.SourceManager;
88 Namespaces.push_back(&ND);
93 SourceRange FrontReplacement(Namespaces.front()->getBeginLoc(),
94 Namespaces.back()->getLocation());
95 SourceRange BackReplacement(Namespaces.back()->getRBraceLoc(),
96 Namespaces.front()->getRBraceLoc());
100 reportDiagnostic(FrontReplacement, BackReplacement);