annotate clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp @ 173:0572611fdcc8 llvm10 llvm12

reorgnization done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 11:55:54 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- ConcatNestedNamespacesCheck.cpp - clang-tidy----------------------===//
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 #include "ConcatNestedNamespacesCheck.h"
anatofuz
parents:
diff changeset
10 #include "clang/AST/ASTContext.h"
anatofuz
parents:
diff changeset
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
anatofuz
parents:
diff changeset
12 #include <algorithm>
anatofuz
parents:
diff changeset
13 #include <iterator>
anatofuz
parents:
diff changeset
14
anatofuz
parents:
diff changeset
15 namespace clang {
anatofuz
parents:
diff changeset
16 namespace tidy {
anatofuz
parents:
diff changeset
17 namespace modernize {
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 static bool locationsInSameFile(const SourceManager &Sources,
anatofuz
parents:
diff changeset
20 SourceLocation Loc1, SourceLocation Loc2) {
anatofuz
parents:
diff changeset
21 return Loc1.isFileID() && Loc2.isFileID() &&
anatofuz
parents:
diff changeset
22 Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
anatofuz
parents:
diff changeset
23 }
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 static bool anonymousOrInlineNamespace(const NamespaceDecl &ND) {
anatofuz
parents:
diff changeset
26 return ND.isAnonymousNamespace() || ND.isInlineNamespace();
anatofuz
parents:
diff changeset
27 }
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 static bool singleNamedNamespaceChild(const NamespaceDecl &ND) {
anatofuz
parents:
diff changeset
30 NamespaceDecl::decl_range Decls = ND.decls();
anatofuz
parents:
diff changeset
31 if (std::distance(Decls.begin(), Decls.end()) != 1)
anatofuz
parents:
diff changeset
32 return false;
anatofuz
parents:
diff changeset
33
anatofuz
parents:
diff changeset
34 const auto *ChildNamespace = dyn_cast<const NamespaceDecl>(*Decls.begin());
anatofuz
parents:
diff changeset
35 return ChildNamespace && !anonymousOrInlineNamespace(*ChildNamespace);
anatofuz
parents:
diff changeset
36 }
anatofuz
parents:
diff changeset
37
anatofuz
parents:
diff changeset
38 static bool alreadyConcatenated(std::size_t NumCandidates,
anatofuz
parents:
diff changeset
39 const SourceRange &ReplacementRange,
anatofuz
parents:
diff changeset
40 const SourceManager &Sources,
anatofuz
parents:
diff changeset
41 const LangOptions &LangOpts) {
anatofuz
parents:
diff changeset
42 // FIXME: This logic breaks when there is a comment with ':'s in the middle.
anatofuz
parents:
diff changeset
43 CharSourceRange TextRange =
anatofuz
parents:
diff changeset
44 Lexer::getAsCharRange(ReplacementRange, Sources, LangOpts);
anatofuz
parents:
diff changeset
45 StringRef CurrentNamespacesText =
anatofuz
parents:
diff changeset
46 Lexer::getSourceText(TextRange, Sources, LangOpts);
anatofuz
parents:
diff changeset
47 return CurrentNamespacesText.count(':') == (NumCandidates - 1) * 2;
anatofuz
parents:
diff changeset
48 }
anatofuz
parents:
diff changeset
49
anatofuz
parents:
diff changeset
50 ConcatNestedNamespacesCheck::NamespaceString
anatofuz
parents:
diff changeset
51 ConcatNestedNamespacesCheck::concatNamespaces() {
anatofuz
parents:
diff changeset
52 NamespaceString Result("namespace ");
anatofuz
parents:
diff changeset
53 Result.append(Namespaces.front()->getName());
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 std::for_each(std::next(Namespaces.begin()), Namespaces.end(),
anatofuz
parents:
diff changeset
56 [&Result](const NamespaceDecl *ND) {
anatofuz
parents:
diff changeset
57 Result.append("::");
anatofuz
parents:
diff changeset
58 Result.append(ND->getName());
anatofuz
parents:
diff changeset
59 });
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 return Result;
anatofuz
parents:
diff changeset
62 }
anatofuz
parents:
diff changeset
63
anatofuz
parents:
diff changeset
64 void ConcatNestedNamespacesCheck::registerMatchers(
anatofuz
parents:
diff changeset
65 ast_matchers::MatchFinder *Finder) {
anatofuz
parents:
diff changeset
66 Finder->addMatcher(ast_matchers::namespaceDecl().bind("namespace"), this);
anatofuz
parents:
diff changeset
67 }
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 void ConcatNestedNamespacesCheck::reportDiagnostic(
anatofuz
parents:
diff changeset
70 const SourceRange &FrontReplacement, const SourceRange &BackReplacement) {
anatofuz
parents:
diff changeset
71 diag(Namespaces.front()->getBeginLoc(),
anatofuz
parents:
diff changeset
72 "nested namespaces can be concatenated", DiagnosticIDs::Warning)
anatofuz
parents:
diff changeset
73 << FixItHint::CreateReplacement(FrontReplacement, concatNamespaces())
anatofuz
parents:
diff changeset
74 << FixItHint::CreateReplacement(BackReplacement, "}");
anatofuz
parents:
diff changeset
75 }
anatofuz
parents:
diff changeset
76
anatofuz
parents:
diff changeset
77 void ConcatNestedNamespacesCheck::check(
anatofuz
parents:
diff changeset
78 const ast_matchers::MatchFinder::MatchResult &Result) {
anatofuz
parents:
diff changeset
79 const NamespaceDecl &ND = *Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
anatofuz
parents:
diff changeset
80 const SourceManager &Sources = *Result.SourceManager;
anatofuz
parents:
diff changeset
81
anatofuz
parents:
diff changeset
82 if (!locationsInSameFile(Sources, ND.getBeginLoc(), ND.getRBraceLoc()))
anatofuz
parents:
diff changeset
83 return;
anatofuz
parents:
diff changeset
84
anatofuz
parents:
diff changeset
85 if (!Sources.isInMainFile(ND.getBeginLoc()))
anatofuz
parents:
diff changeset
86 return;
anatofuz
parents:
diff changeset
87
anatofuz
parents:
diff changeset
88 if (anonymousOrInlineNamespace(ND))
anatofuz
parents:
diff changeset
89 return;
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 Namespaces.push_back(&ND);
anatofuz
parents:
diff changeset
92
anatofuz
parents:
diff changeset
93 if (singleNamedNamespaceChild(ND))
anatofuz
parents:
diff changeset
94 return;
anatofuz
parents:
diff changeset
95
anatofuz
parents:
diff changeset
96 SourceRange FrontReplacement(Namespaces.front()->getBeginLoc(),
anatofuz
parents:
diff changeset
97 Namespaces.back()->getLocation());
anatofuz
parents:
diff changeset
98 SourceRange BackReplacement(Namespaces.back()->getRBraceLoc(),
anatofuz
parents:
diff changeset
99 Namespaces.front()->getRBraceLoc());
anatofuz
parents:
diff changeset
100
anatofuz
parents:
diff changeset
101 if (!alreadyConcatenated(Namespaces.size(), FrontReplacement, Sources,
anatofuz
parents:
diff changeset
102 getLangOpts()))
anatofuz
parents:
diff changeset
103 reportDiagnostic(FrontReplacement, BackReplacement);
anatofuz
parents:
diff changeset
104
anatofuz
parents:
diff changeset
105 Namespaces.clear();
anatofuz
parents:
diff changeset
106 }
anatofuz
parents:
diff changeset
107
anatofuz
parents:
diff changeset
108 } // namespace modernize
anatofuz
parents:
diff changeset
109 } // namespace tidy
anatofuz
parents:
diff changeset
110 } // namespace clang