blob: 55a8b85cfdadeae5c345ab27515df5e5d598d70d [file] [log] [blame]
Alexander Kornienkob959f4c2015-12-30 10:24:40 +00001//===--- LexerUtils.h - clang-tidy-------------------------------*- C++ -*-===//
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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
12
13#include "clang/AST/ASTContext.h"
14#include "clang/Lex/Lexer.h"
15
16namespace clang {
17namespace tidy {
Etienne Bergeron2a4c00f2016-05-03 02:54:05 +000018namespace utils {
19namespace lexer {
Alexander Kornienkob959f4c2015-12-30 10:24:40 +000020
Alexander Kornienko2d730222017-02-06 15:46:33 +000021/// Returns previous token or ``tok::unknown`` if not found.
Jonas Totha78c2492018-10-05 14:15:19 +000022Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
23 const LangOptions &LangOpts, bool SkipComments = true);
Alexander Kornienkob959f4c2015-12-30 10:24:40 +000024
Jonas Toth0ea5af72018-10-31 16:50:44 +000025SourceLocation findPreviousTokenStart(SourceLocation Start,
26 const SourceManager &SM,
27 const LangOptions &LangOpts);
28
29SourceLocation findPreviousTokenKind(SourceLocation Start,
30 const SourceManager &SM,
31 const LangOptions &LangOpts,
32 tok::TokenKind TK);
33
34SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
35 const LangOptions &LangOpts);
36
37template <typename TokenKind, typename... TokenKinds>
38SourceLocation findPreviousAnyTokenKind(SourceLocation Start,
39 const SourceManager &SM,
40 const LangOptions &LangOpts,
41 TokenKind TK, TokenKinds... TKs) {
42 while (true) {
43 SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
44 if (L.isInvalid() || L.isMacroID())
45 return SourceLocation();
46
47 Token T;
48 // Returning 'true' is used to signal failure to retrieve the token.
49 if (Lexer::getRawToken(L, T, SM, LangOpts))
50 return SourceLocation();
51
52 if (T.isOneOf(TK, TKs...))
53 return T.getLocation();
54
55 Start = L;
56 }
57}
58
59template <typename TokenKind, typename... TokenKinds>
60SourceLocation findNextAnyTokenKind(SourceLocation Start,
61 const SourceManager &SM,
62 const LangOptions &LangOpts, TokenKind TK,
63 TokenKinds... TKs) {
64 while (true) {
65 Optional<Token> CurrentToken = Lexer::findNextToken(Start, SM, LangOpts);
66
67 if (!CurrentToken)
68 return SourceLocation();
69
70 Token PotentialMatch = *CurrentToken;
71 if (PotentialMatch.isOneOf(TK, TKs...))
72 return PotentialMatch.getLocation();
73
74 Start = PotentialMatch.getLastLoc();
75 }
76}
77
78/// Re-lex the provide \p Range and return \c false if either a macro spans
79/// multiple tokens, a pre-processor directive or failure to retrieve the
80/// next token is found, otherwise \c true.
81bool rangeContainsExpansionsOrDirectives(SourceRange Range,
82 const SourceManager &SM,
83 const LangOptions &LangOpts);
84
Aaron Ballman3a027222018-10-31 19:11:38 +000085/// Assuming that ``Range`` spans a const-qualified type, returns the ``const``
86/// token in ``Range`` that is responsible for const qualification. ``Range``
87/// must be valid with respect to ``SM``. Returns ``None`` if no ``const``
88/// tokens are found.
89llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
90 const ASTContext &Context,
91 const SourceManager &SM);
92
Etienne Bergeron2a4c00f2016-05-03 02:54:05 +000093} // namespace lexer
94} // namespace utils
Alexander Kornienkob959f4c2015-12-30 10:24:40 +000095} // namespace tidy
96} // namespace clang
97
98#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H