clang-tools 6.0.0

UsingInserter.cpp
Go to the documentation of this file.
1 //===---------- UsingInserter.cpp - clang-tidy ----------------------------===//
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 #include "UsingInserter.h"
11
12 #include "ASTUtils.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
15 #include "clang/Lex/Lexer.h"
16
17 namespace clang {
18 namespace tidy {
19 namespace utils {
20
21 using namespace ast_matchers;
22
23 static StringRef getUnqualifiedName(StringRef QualifiedName) {
24 size_t LastSeparatorPos = QualifiedName.rfind("::");
25 if (LastSeparatorPos == StringRef::npos)
26 return QualifiedName;
27 return QualifiedName.drop_front(LastSeparatorPos + 2);
28 }
29
30 UsingInserter::UsingInserter(const SourceManager &SourceMgr)
31 : SourceMgr(SourceMgr) {}
32
33 Optional<FixItHint> UsingInserter::createUsingDeclaration(
34 ASTContext &Context, const Stmt &Statement, StringRef QualifiedName) {
35 StringRef UnqualifiedName = getUnqualifiedName(QualifiedName);
36 const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
37 if (!Function)
38 return None;
39
40 if (AddedUsing.count(std::make_pair(Function, QualifiedName.str())) != 0)
41 return None;
42
43 SourceLocation InsertLoc = Lexer::getLocForEndOfToken(
44 Function->getBody()->getLocStart(), 0, SourceMgr, Context.getLangOpts());
45
46 // Only use using declarations in the main file, not in includes.
47 if (SourceMgr.getFileID(InsertLoc) != SourceMgr.getMainFileID())
48 return None;
49
50 // FIXME: This declaration could be masked. Investigate if
51 // there is a way to avoid using Sema.
52 bool AlreadyHasUsingDecl =
53 !match(stmt(hasAncestor(decl(has(usingDecl(hasAnyUsingShadowDecl(
54 hasTargetDecl(hasName(QualifiedName.str())))))))),
55 Statement, Context)
56 .empty();
57 if (AlreadyHasUsingDecl) {
58 AddedUsing.emplace(NameInFunction(Function, QualifiedName.str()));
59 return None;
60 }
61 // Find conflicting declarations and references.
62 auto ConflictingDecl = namedDecl(hasName(UnqualifiedName));
63 bool HasConflictingDeclaration =
64 !match(findAll(ConflictingDecl), *Function, Context).empty();
65 bool HasConflictingDeclRef =
66 !match(findAll(declRefExpr(to(ConflictingDecl))), *Function, Context)
67 .empty();
68 if (HasConflictingDeclaration || HasConflictingDeclRef)
69 return None;
70
71 std::string Declaration =
72 (llvm::Twine("\nusing ") + QualifiedName + ";").str();
73
74 AddedUsing.emplace(std::make_pair(Function, QualifiedName.str()));
75 return FixItHint::CreateInsertion(InsertLoc, Declaration);
76 }
77
78 StringRef UsingInserter::getShortName(ASTContext &Context,
79 const Stmt &Statement,
80 StringRef QualifiedName) {
81 const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
82 if (AddedUsing.count(NameInFunction(Function, QualifiedName.str())) != 0)
83 return getUnqualifiedName(QualifiedName);
84 return QualifiedName;
85 }
86
87 } // namespace utils
88 } // namespace tidy
89 } // namespace clang
clang::tidy::utils::UsingInserter::UsingInserter
UsingInserter(const SourceManager &SourceMgr)
Definition: UsingInserter.cpp:30
clang::tidy::utils::getUnqualifiedName
static StringRef getUnqualifiedName(StringRef QualifiedName)
Definition: UsingInserter.cpp:23
UsingInserter.h
clang::tidy::utils::getSurroundingFunction
const FunctionDecl * getSurroundingFunction(ASTContext &Context, const Stmt &Statement)
Definition: ASTUtils.cpp:21
clang::tidy::utils::UsingInserter::createUsingDeclaration
llvm::Optional< FixItHint > createUsingDeclaration(ASTContext &Context, const Stmt &Statement, llvm::StringRef QualifiedName)
Definition: UsingInserter.cpp:33
clang
Definition: AndroidTidyModule.cpp:28
ASTUtils.h
clang::tidy::utils::UsingInserter::getShortName
llvm::StringRef getShortName(ASTContext &Context, const Stmt &Statement, llvm::StringRef QualifiedName)
Definition: UsingInserter.cpp:78