clang-tools 23.0.0git
LexerUtils.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
11
12#include "clang/AST/ASTContext.h"
13#include "clang/Basic/TokenKinds.h"
14#include "clang/Lex/Lexer.h"
15#include "llvm/ADT/STLFunctionalExtras.h"
16#include <optional>
17#include <utility>
18#include <vector>
19
20namespace clang {
21
22class Stmt;
23
24namespace tidy::utils::lexer {
25
26/// Returns previous token or ``std::nullopt`` if not found.
27std::optional<Token> getPreviousToken(SourceLocation Location,
28 const SourceManager &SM,
29 const LangOptions &LangOpts,
30 bool SkipComments = true);
31
32std::pair<std::optional<Token>, SourceLocation>
33getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
34 const LangOptions &LangOpts, bool SkipComments = true);
35
36SourceLocation findPreviousTokenStart(SourceLocation Start,
37 const SourceManager &SM,
38 const LangOptions &LangOpts);
39
40SourceLocation findPreviousTokenKind(SourceLocation Start,
41 const SourceManager &SM,
42 const LangOptions &LangOpts,
43 tok::TokenKind TK);
44
45SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
46 const LangOptions &LangOpts);
47
48template <typename TokenKind, typename... TokenKinds>
49SourceLocation findPreviousAnyTokenKind(SourceLocation Start,
50 const SourceManager &SM,
51 const LangOptions &LangOpts,
52 TokenKind TK, TokenKinds... TKs) {
53 if (Start.isInvalid() || Start.isMacroID())
54 return {};
55 while (true) {
56 const SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
57 if (L.isInvalid() || L.isMacroID())
58 return {};
59
60 Token T;
61 // Returning 'true' is used to signal failure to retrieve the token.
62 if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
63 return {};
64
65 if (T.isOneOf(TK, TKs...))
66 return T.getLocation();
67
68 Start = L;
69 }
70}
71
72template <typename TokenKind, typename... TokenKinds>
73SourceLocation findNextAnyTokenKind(SourceLocation Start,
74 const SourceManager &SM,
75 const LangOptions &LangOpts, TokenKind TK,
76 TokenKinds... TKs) {
77 while (true) {
78 std::optional<Token> CurrentToken =
79 Lexer::findNextToken(Start, SM, LangOpts);
80
81 if (!CurrentToken)
82 return {};
83
84 const Token PotentialMatch = *CurrentToken;
85 if (PotentialMatch.isOneOf(TK, TKs...))
86 return PotentialMatch.getLocation();
87
88 // If we reach the end of the file, and eof is not the target token, we stop
89 // the loop, otherwise we will get infinite loop (findNextToken will return
90 // eof on eof).
91 if (PotentialMatch.is(tok::eof))
92 return {};
93 Start = PotentialMatch.getLastLoc();
94 }
95}
96
97// Finds next token, possibly a comment.
98inline std::optional<Token>
99findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM,
100 const LangOptions &LangOpts) {
101 return Lexer::findNextToken(Start, SM, LangOpts, true);
102}
103
104// Finds next token that's not a comment.
105inline std::optional<Token>
106findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM,
107 const LangOptions &LangOpts) {
108 return Lexer::findNextToken(Start, SM, LangOpts, false);
109}
110
111/// Re-lex the provide \p Range and return \c false if either a macro spans
112/// multiple tokens, a pre-processor directive or failure to retrieve the
113/// next token is found, otherwise \c true.
114bool rangeContainsExpansionsOrDirectives(SourceRange Range,
115 const SourceManager &SM,
116 const LangOptions &LangOpts);
117
118// Represents a comment token and its source location in the original file.
120 SourceLocation Loc;
121 StringRef Text;
122};
123
124/// Returns all comment tokens found in the given range.
125std::vector<CommentToken> getCommentsInRange(CharSourceRange Range,
126 const SourceManager &SM,
127 const LangOptions &LangOpts);
128
129/// Returns comment tokens found in the given range. If a non-comment token is
130/// encountered, clears previously collected comments and continues.
131std::vector<CommentToken>
132getTrailingCommentsInRange(CharSourceRange Range, const SourceManager &SM,
133 const LangOptions &LangOpts);
134
135/// Returns source range of the first token in \p Range matching \p Pred.
136/// The returned char range starts at the matched token and ends at the start
137/// of the next token. Returns invalid range if no token matches.
138CharSourceRange
139findTokenTextInRange(CharSourceRange Range, const SourceManager &SM,
140 const LangOptions &LangOpts,
141 llvm::function_ref<bool(const Token &)> Pred);
142
143/// Assuming that ``Range`` spans a CVR-qualified type, returns the
144/// token in ``Range`` that is responsible for the qualification. ``Range``
145/// must be valid with respect to ``SM``. Returns ``std::nullopt`` if no
146/// qualifying tokens are found.
147/// \note: doesn't support member function qualifiers.
148std::optional<Token> getQualifyingToken(tok::TokenKind TK,
149 CharSourceRange Range,
150 const ASTContext &Context,
151 const SourceManager &SM);
152
153/// Stmt->getEndLoc does not always behave the same way depending on Token type.
154/// See implementation for exceptions.
155SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM,
156 const LangOptions &LangOpts);
157
158/// For a given FunctionDecl returns the location where you would need to place
159/// the noexcept specifier.
160SourceLocation getLocationForNoexceptSpecifier(const FunctionDecl *FuncDecl,
161 const SourceManager &SM);
162
163} // namespace tidy::utils::lexer
164} // namespace clang
165
166#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
std::pair< std::optional< Token >, SourceLocation > getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
SourceLocation getLocationForNoexceptSpecifier(const FunctionDecl *FuncDecl, const SourceManager &SM)
For a given FunctionDecl returns the location where you would need to place the noexcept specifier.
SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM, const LangOptions &LangOpts)
Stmt->getEndLoc does not always behave the same way depending on Token type.
bool rangeContainsExpansionsOrDirectives(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Re-lex the provide Range and return false if either a macro spans multiple tokens,...
SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
std::optional< Token > getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
Returns previous token or std::nullopt if not found.
std::vector< CommentToken > getTrailingCommentsInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Returns comment tokens found in the given range. If a non-comment token is encountered,...
SourceLocation findNextAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition LexerUtils.h:73
std::optional< Token > findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition LexerUtils.h:106
SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
CharSourceRange findTokenTextInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, llvm::function_ref< bool(const Token &)> Pred)
Returns source range of the first token in Range matching Pred. The returned char range starts at the...
std::vector< CommentToken > getCommentsInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Returns all comment tokens found in the given range.
SourceLocation findPreviousTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, tok::TokenKind TK)
std::optional< Token > getQualifyingToken(tok::TokenKind TK, CharSourceRange Range, const ASTContext &Context, const SourceManager &SM)
Assuming that Range spans a CVR-qualified type, returns the token in Range that is responsible for th...
std::optional< Token > findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition LexerUtils.h:99
SourceLocation findPreviousAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition LexerUtils.h:49
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static constexpr const char FuncDecl[]