forked from include-what-you-use/include-what-you-use
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iwyu_lexer_utils.cc
115 lines (101 loc) · 3.75 KB
/
iwyu_lexer_utils.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//===--- iwyu_lexer_utils.cc - clang-lexer utilities for iwyu -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "iwyu_lexer_utils.h"
#include <cstring>
#include <string>
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Token.h"
#include "iwyu_globals.h"
#include "iwyu_port.h" // for CHECK_
using clang::MacroInfo;
using clang::SourceLocation;
using clang::SourceManager;
using clang::Token;
using llvm::StringRef;
using std::string;
namespace include_what_you_use {
bool LineHasText(SourceLocation source_location, StringRef text) {
const StringRef data =
GetSourceTextUntilEndOfLine(source_location, DefaultDataGetter());
return data.find(text) != StringRef::npos;
}
// SourceManagerCharacterDataGetter method implementations.
SourceManagerCharacterDataGetter::SourceManagerCharacterDataGetter(
const SourceManager& source_manager)
: source_manager_(source_manager) {
}
const char* SourceManagerCharacterDataGetter::GetCharacterData(
SourceLocation loc) const {
bool invalid;
const char* data = source_manager_.getCharacterData(loc, &invalid);
CHECK_(!invalid);
CHECK_(data);
return data;
}
StringRef GetSourceTextUntilEndOfLine(
SourceLocation start_loc, const CharacterDataGetterInterface& data_getter) {
const char* data = data_getter.GetCharacterData(start_loc);
const char* line_end = strpbrk(data, "\r\n");
if (!line_end)
return data;
return StringRef(data, line_end - data);
}
SourceLocation GetLocationAfter(
SourceLocation start_loc, const string& needle,
const CharacterDataGetterInterface& data_getter) {
CHECK_(start_loc.isValid() && "GetLocationAfter takes only valid locations");
const char* data = data_getter.GetCharacterData(start_loc);
const char* needle_loc = strstr(data, needle.c_str());
if (!needle_loc)
return SourceLocation(); // invalid source location
return start_loc.getLocWithOffset(needle_loc - data + needle.length());
}
string GetIncludeNameAsWritten(
SourceLocation include_loc,
const CharacterDataGetterInterface& data_getter) {
const string data = GetSourceTextUntilEndOfLine(include_loc, data_getter).str();
if (data.empty())
return data;
string::size_type endpos = string::npos;
if (data[0] == '<') {
endpos = data.find('>', 1);
} else if (data[0] == '"') {
endpos = data.find('"', 1);
} else {
CHECK_UNREACHABLE_("Unexpected token being #included");
}
CHECK_(endpos != string::npos && "No end-character found for #include");
return data.substr(0, endpos+1);
}
// Get the text of a given token.
string GetTokenText(const Token& token,
const CharacterDataGetterInterface& data_getter) {
const char* text = data_getter.GetCharacterData(token.getLocation());
return string(text, token.getLength());
}
// Given a token iterator inside a macro, returns the kind of the token after
// current, ignoring comment tokens. If there is no token after, returns
// clang::tok::unknown.
clang::tok::TokenKind GetNextMacroTokenKind(
const MacroInfo* macro, MacroInfo::const_tokens_iterator current) {
MacroInfo::const_tokens_iterator token = current;
if (token == macro->tokens_end()) {
return clang::tok::unknown;
}
// Return the first non-comment token after current.
for (++token; token != macro->tokens_end(); ++token) {
// Skip over comment tokens (which may be there in in -E -C[C] mode).
if (token->is(clang::tok::comment))
continue;
return token->getKind();
}
return clang::tok::unknown;
}
} // namespace include_what_you_use