43 if (!language || !ts_parser_set_language(
m_ts_state->parser, language)) {
44 LLDB_LOG(log,
"Creating tree-sitter language failed for {0}",
GetName());
49 uint32_t error_offset = 0;
50 TSQueryError error_type = TSQueryErrorNone;
51 m_ts_state->query = ts_query_new(language, query_source.data(),
52 static_cast<uint32_t
>(query_source.size()),
53 &error_offset, &error_type);
54 if (!
m_ts_state->query || error_type != TSQueryErrorNone) {
56 "Creating tree-sitter query failed for {0} with error {1}: {2}",
57 GetName(), error_type, query_source.substr(error_offset, 64));
91 const HighlightStyle &options, llvm::StringRef text, uint32_t start_byte,
93 std::optional<size_t> cursor_pos,
bool &highlighted_cursor,
96 if (start_byte >= end_byte || start_byte >= text.size())
99 end_byte = std::min(end_byte,
static_cast<uint32_t
>(text.size()));
101 llvm::StringRef range = text.substr(start_byte, end_byte - start_byte);
103 auto print = [&](llvm::StringRef str) {
111 if (cursor_pos && *cursor_pos >= start_byte && *cursor_pos < end_byte &&
112 !highlighted_cursor) {
113 highlighted_cursor =
true;
116 const size_t cursor_in_range = *cursor_pos - start_byte;
119 if (cursor_in_range > 0) {
120 llvm::StringRef before = range.substr(0, cursor_in_range);
125 if (cursor_in_range < range.size()) {
127 llvm::StringRef cursor_char = range.substr(cursor_in_range, 1);
129 style.
Apply(cursor_str, cursor_char);
131 cursor_str << cursor_char;
136 if (cursor_in_range + 1 < range.size()) {
137 llvm::StringRef after = range.substr(cursor_in_range + 1);
147 llvm::StringRef line,
148 std::optional<size_t> cursor_pos,
149 llvm::StringRef previous_lines,
151 auto unformatted = [&]() ->
void { s << line; };
155 return unformatted();
157 std::string source = previous_lines.str() + line.str();
159 ts_parser_parse_string(ts_state.
parser,
nullptr, source.c_str(),
160 static_cast<uint32_t
>(source.size()));
162 return unformatted();
164 TSQueryCursor *cursor = ts_query_cursor_new();
167 llvm::scope_exit delete_cusor([&] { ts_query_cursor_delete(cursor); });
169 TSNode root_node = ts_tree_root_node(tree);
170 ts_query_cursor_exec(cursor, ts_state.
query, root_node);
173 std::vector<HLRange> highlights;
175 uint32_t capture_index;
176 while (ts_query_cursor_next_capture(cursor, &match, &capture_index)) {
177 TSQueryCapture capture = match.captures[capture_index];
179 uint32_t capture_name_len = 0;
180 const char *capture_name = ts_query_capture_name_for_id(
181 ts_state.
query, capture.index, &capture_name_len);
184 llvm::StringRef(capture_name, capture_name_len), options);
186 TSNode node = capture.node;
187 uint32_t start = ts_node_start_byte(node);
188 uint32_t end = ts_node_end_byte(node);
190 if (style && start < end)
191 highlights.push_back({start, end, style});
194 std::sort(highlights.begin(), highlights.end(),
196 if (a.start_byte != b.start_byte)
197 return a.start_byte < b.start_byte;
201 return (b.end_byte - b.start_byte) > (a.end_byte - a.start_byte);
204 uint32_t current_pos = 0;
205 bool highlighted_cursor =
false;
207 for (
const auto &h : highlights) {
210 if (h.start_byte < current_pos)
214 if (current_pos < h.start_byte) {
215 HighlightRange(options, line, current_pos, h.start_byte, {}, cursor_pos,
216 highlighted_cursor, s);
217 current_pos = h.start_byte;
221 HighlightRange(options, line, h.start_byte, h.end_byte, h.style, cursor_pos,
222 highlighted_cursor, s);
223 current_pos = h.end_byte;
227 if (current_pos < line.size()) {
229 static_cast<uint32_t
>(line.size()), {}, cursor_pos,
230 highlighted_cursor, s);
void Highlight(const HighlightStyle &options, llvm::StringRef line, std::optional< size_t > cursor_pos, llvm::StringRef previous_lines, Stream &s) const override
Highlights a single line of code using tree-sitter parsing.
void HighlightRange(const HighlightStyle &options, llvm::StringRef text, uint32_t start_byte, uint32_t end_byte, const HighlightStyle::ColorStyle &style, std::optional< size_t > cursor_pos, bool &highlighted_cursor, Stream &s) const
Applies syntax highlighting to a range of text.