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?");
static HighlightStyle::ColorStyle determineClangStyle(const ClangHighlighter &highlighter, const clang::Token &token, llvm::StringRef tok_str, const HighlightStyle &options, bool &in_pp_directive)
Determines which style should be applied to the given token.
void Highlight(const HighlightStyle &options, llvm::StringRef line, std::optional< size_t > cursor_pos, llvm::StringRef previous_lines, Stream &s) const override
Highlights the given line.
bool isKeyword(llvm::StringRef token) const
Returns true if the given string represents a keywords in any Clang supported language.
static FileSystem & Instance()
A pair of strings that should be placed around a certain token.
void Apply(Stream &s, llvm::StringRef value) const
Applies this style to the given value.
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
A class that represents a running process on the host machine.
Represents style that the highlighter should apply to the given source code.
ColorStyle square_brackets
Matches '[' or ']'.
ColorStyle comment
Matches any comments in the language.
ColorStyle braces
Matches '{' or '}'.
ColorStyle scalar_literal
Matches scalar value literals like '42' or '0.1'.
ColorStyle comma
Matches commas: ','.
ColorStyle pp_directive
Matches directives to a preprocessor (if the language has any).
ColorStyle operators
Matches operators like '+', '-', '', '&', '='.
ColorStyle string_literal
Matches any string or character literals in the language: "foo" or 'f'.
ColorStyle keyword
Matches all reserved keywords in the language.
ColorStyle parentheses
Matches '(' or ')'.
ColorStyle selected
The style for the token which is below the cursor of the user.
ColorStyle identifier
Matches identifiers to variable or functions.
ColorStyle colon
Matches one colon: ':'.