16 #include "clang/Basic/FileManager.h"
17 #include "clang/Basic/SourceManager.h"
18 #include "clang/Lex/Lexer.h"
19 #include "llvm/ADT/StringSet.h"
20 #include "llvm/Support/MemoryBuffer.h"
30 #define KEYWORD(X, N) keywords.insert(#X);
31 #include "clang/Basic/TokenKinds.def"
51 const clang::Token &token, llvm::StringRef tok_str,
53 using namespace clang;
55 if (token.is(tok::comment)) {
57 in_pp_directive =
false;
59 }
else if (in_pp_directive || token.getKind() == tok::hash) {
61 in_pp_directive =
true;
64 }
else if (tok::isStringLiteral(token.getKind()))
66 else if (tok::isLiteral(token.getKind()))
71 switch (token.getKind()) {
72 case tok::raw_identifier:
100 case tok::minusminus:
101 case tok::minusequal:
104 case tok::exclaimequal:
106 case tok::slashequal:
108 case tok::percentequal:
112 case tok::lesslessequal:
115 case tok::greatergreater:
116 case tok::greaterequal:
117 case tok::greatergreaterequal:
119 case tok::caretequal:
125 case tok::equalequal:
134 llvm::StringRef line,
135 std::optional<size_t> cursor_pos,
136 llvm::StringRef previous_lines,
138 using namespace clang;
140 FileSystemOptions file_opts;
141 FileManager file_mgr(file_opts,
150 llvm::StringRef line_ending =
"";
153 if (line.consume_back(
"\r\n"))
154 line_ending =
"\r\n";
155 else if (line.consume_back(
"\n"))
157 else if (line.consume_back(
"\r"))
160 unsigned line_number = previous_lines.count(
'\n') + 1U;
164 std::string full_source = previous_lines.str() + line.str();
165 llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(
new DiagnosticIDs());
166 llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts(
167 new DiagnosticOptions());
168 DiagnosticsEngine diags(diag_ids, diags_opts);
169 clang::SourceManager SM(diags, file_mgr);
170 auto buf = llvm::MemoryBuffer::getMemBuffer(full_source);
172 FileID FID = SM.createFileID(buf->getMemBufferRef());
179 Opts.CPlusPlus17 =
true;
180 Opts.LineComment =
true;
182 Lexer lex(FID, buf->getMemBufferRef(), SM, Opts);
184 lex.SetKeepWhitespaceMode(
true);
187 bool in_pp_directive =
false;
190 bool found_user_line =
false;
193 bool highlighted_cursor =
false;
198 exit = lex.LexFromRawLexer(token);
200 bool invalid =
false;
201 unsigned current_line_number =
202 SM.getSpellingLineNumber(token.getLocation(), &invalid);
203 if (current_line_number != line_number)
205 found_user_line =
true;
213 unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
220 if (token.isAnnotation())
224 llvm::StringRef tok_str = line.substr(start, token.getLength());
232 llvm::StringRef to_print = tok_str;
234 auto end = start + token.getLength();
235 if (cursor_pos && end > *cursor_pos && !highlighted_cursor) {
236 highlighted_cursor =
true;
245 color.
Apply(result, to_print);
249 result << line_ending;
255 if (!found_user_line) {
257 assert(
false &&
"We couldn't find the user line in the input file?");