Pull tree_sitter_code_index_update_single_buffer out as it's own routine, and use it in tree_sitter_parse_asyn__inner to avoid setting the buffer_modified flag

This commit is contained in:
Peter Slattery 2025-07-13 12:05:16 -07:00
parent 5ccd6dd2ab
commit 18428ec90d
2 changed files with 129 additions and 132 deletions

View File

@ -269,14 +269,7 @@ tree_sitter_parse_async__inner(Async_Context* actx, Buffer_ID buffer_id)
tree_data->tree = new_tree;
system_mutex_acquire(tree_data->tree_mutex);
// TODO(PS): Just put the code index update call here
// NOTE(jack): This feels kinda hacky, this is here to trigger
// the code index update tick. The buffer is also makred by the
// async lexer so we will update the index too frequently. We
// should probably change the lexer to not mark as modified.
// TODO(jack): Should we instead trigger another async task here to
// update the code index once this is done?
buffer_mark_as_modified(buffer_id);
tree_sitter_code_index_update_single_buffer(app, buffer_id);
// Force a frame refresh by requesting another frame
animate_in_n_milliseconds(app, 0);
@ -329,137 +322,140 @@ code_index_new_note(Code_Index_File* index, Arena* arena, Code_Index_Note_Kind k
}
function void
tree_sitter_code_index_update_tick(Application_Links* app)
tree_sitter_code_index_update_single_buffer(Application_Links* app, Buffer_ID buffer_id)
{
Scratch_Block scratch(app);
Arena arena = make_arena_system(KB(16));
Code_Index_File* index = push_array_zero(&arena, Code_Index_File, 1);
index->buffer = buffer_id;
String_Const_u8 buffer_contents = push_whole_buffer(app, scratch, buffer_id);
Tree_Sitter_Language_Definition* lang = tree_sitter_language_for_buffer(app, buffer_id);
if (!lang) return;
TSQuery* ts_query = lang->queries.ptr[Tree_Sitter_Language_Query_Tags];
Tree_Sitter_Query_Cursor query = tree_sitter_query_init(
app, buffer_id, ts_query
);
Code_Index_Nest_Stack* nest_stack_first = 0;
Code_Index_Nest_Stack* nest_stack_last = 0;
Code_Index_Note* last_note = 0;
u32 last_note_match_id = max_u32;
TSQueryMatch query_match;
u32 capture_index;
while (tree_sitter_query_continue(&query, &query_match, &capture_index))
{
TSQueryCapture type_capture = query_match.captures[capture_index];
TSNode type_node = type_capture.node;
Range_i64 type_range = tree_sitter_node_to_range(type_node);
u32 length;
const char* tmp = ts_query_capture_name_for_id(query.query, type_capture.index, &length);
String_Const_u8 capture_name = SCu8((char*)tmp, length);
if (string_match(capture_name, SCu8("scope_begin")))
{
Code_Index_Nest* nest = push_array_zero(&arena, Code_Index_Nest, 1);
nest->kind = CodeIndexNest_Scope;
nest->open = type_range;
nest->close = Ii64(max_i64);
nest->file = index;
if (nest_stack_last != 0)
{
nest->parent = nest_stack_last->nest;
code_index_push_nest(&nest->parent->nest_list, nest);
}
Code_Index_Nest_Stack* stack = push_array_zero(scratch, Code_Index_Nest_Stack, 1);
stack->nest = nest;
stack->prev = nest_stack_last;
stack->match_id = query_match.id;
if (nest_stack_last != 0) nest_stack_last->next = stack;
else nest_stack_first = stack;
nest_stack_last = stack;
}
else if (string_match(capture_name, SCu8("scope_end")))
{
Assert(nest_stack_last != 0);
Assert(nest_stack_last->match_id == query_match.id);
Code_Index_Nest* nest = nest_stack_last->nest;
nest->close = type_range;
nest->is_closed = true;
nest->nest_array = code_index_nest_ptr_array_from_list(&arena, &nest->nest_list);
if (nest->parent == 0) code_index_push_nest(&index->nest_list, nest);
nest_stack_last = nest_stack_last->prev;
if (nest_stack_last != 0) nest_stack_last->next = 0;
}
else if (string_match(capture_name, SCu8("definition.class")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Type, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.function")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Function, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.method")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Function, type_range, nest_stack_last);;
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.type")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Type, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("name")))
{
if (last_note != 0 && last_note_match_id == query_match.id)
{
last_note->pos = Ii64_size(type_range.start, type_range.end - type_range.start);
}
}
}
while (nest_stack_last != 0)
{
Code_Index_Nest* nest = nest_stack_last->nest;
if (nest->parent != 0) code_index_push_nest(&nest->parent->nest_list, nest);
else code_index_push_nest(&index->nest_list, nest);
nest->nest_array = code_index_nest_ptr_array_from_list(&arena, &nest->nest_list);
nest_stack_last = nest_stack_last->prev;
}
for (Code_Index_Note* note = index->note_list.first; note != 0 && note->next != note; note = note->next)
{
note->text = push_string_copy(&arena, string_substring(buffer_contents, note->pos));
}
// Finish the Index
index->nest_array = code_index_nest_ptr_array_from_list(&arena, &index->nest_list);
index->note_array = code_index_note_ptr_array_from_list(&arena, &index->note_list);
code_index_lock();
code_index_set_file(buffer_id, arena, index);
code_index_unlock();
buffer_clear_layout_cache(app, buffer_id);
tree_sitter_query_end(&query);
}
function void
tree_sitter_code_index_update_tick(Application_Links* app)
{
for (Buffer_Modified_Node* modified_node = global_buffer_modified_set.first;
modified_node != 0;
modified_node = modified_node->next
){
Temp_Memory_Block temp(scratch);
Buffer_ID buffer_id = modified_node->buffer;
Arena arena = make_arena_system(KB(16));
Code_Index_File* index = push_array_zero(&arena, Code_Index_File, 1);
index->buffer = buffer_id;
String_Const_u8 buffer_contents = push_whole_buffer(app, scratch, buffer_id);
Tree_Sitter_Language_Definition* lang = tree_sitter_language_for_buffer(app, buffer_id);
if (!lang) continue;
TSQuery* ts_query = lang->queries.ptr[Tree_Sitter_Language_Query_Tags];
Tree_Sitter_Query_Cursor query = tree_sitter_query_init(
app, buffer_id, ts_query
);
Code_Index_Nest_Stack* nest_stack_first = 0;
Code_Index_Nest_Stack* nest_stack_last = 0;
Code_Index_Note* last_note = 0;
u32 last_note_match_id = max_u32;
TSQueryMatch query_match;
u32 capture_index;
while (tree_sitter_query_continue(&query, &query_match, &capture_index))
{
TSQueryCapture type_capture = query_match.captures[capture_index];
TSNode type_node = type_capture.node;
Range_i64 type_range = tree_sitter_node_to_range(type_node);
u32 length;
const char* tmp = ts_query_capture_name_for_id(query.query, type_capture.index, &length);
String_Const_u8 capture_name = SCu8((char*)tmp, length);
if (string_match(capture_name, SCu8("scope_begin")))
{
Code_Index_Nest* nest = push_array_zero(&arena, Code_Index_Nest, 1);
nest->kind = CodeIndexNest_Scope;
nest->open = type_range;
nest->close = Ii64(max_i64);
nest->file = index;
if (nest_stack_last != 0)
{
nest->parent = nest_stack_last->nest;
code_index_push_nest(&nest->parent->nest_list, nest);
}
Code_Index_Nest_Stack* stack = push_array_zero(scratch, Code_Index_Nest_Stack, 1);
stack->nest = nest;
stack->prev = nest_stack_last;
stack->match_id = query_match.id;
if (nest_stack_last != 0) nest_stack_last->next = stack;
else nest_stack_first = stack;
nest_stack_last = stack;
}
else if (string_match(capture_name, SCu8("scope_end")))
{
Assert(nest_stack_last != 0);
Assert(nest_stack_last->match_id == query_match.id);
Code_Index_Nest* nest = nest_stack_last->nest;
nest->close = type_range;
nest->is_closed = true;
nest->nest_array = code_index_nest_ptr_array_from_list(&arena, &nest->nest_list);
if (nest->parent == 0) code_index_push_nest(&index->nest_list, nest);
nest_stack_last = nest_stack_last->prev;
if (nest_stack_last != 0) nest_stack_last->next = 0;
}
else if (string_match(capture_name, SCu8("definition.class")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Type, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.function")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Function, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.method")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Function, type_range, nest_stack_last);;
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("definition.type")))
{
last_note = code_index_new_note(index, &arena, CodeIndexNote_Type, type_range, nest_stack_last);
last_note_match_id = query_match.id;
}
else if (string_match(capture_name, SCu8("name")))
{
if (last_note != 0 && last_note_match_id == query_match.id)
{
last_note->pos = Ii64_size(type_range.start, type_range.end - type_range.start);
}
}
}
while (nest_stack_last != 0)
{
Code_Index_Nest* nest = nest_stack_last->nest;
if (nest->parent != 0) code_index_push_nest(&nest->parent->nest_list, nest);
else code_index_push_nest(&index->nest_list, nest);
nest->nest_array = code_index_nest_ptr_array_from_list(&arena, &nest->nest_list);
nest_stack_last = nest_stack_last->prev;
}
for (Code_Index_Note* note = index->note_list.first; note != 0 && note->next != note; note = note->next)
{
note->text = push_string_copy(&arena, string_substring(buffer_contents, note->pos));
}
// Finish the Index
index->nest_array = code_index_nest_ptr_array_from_list(&arena, &index->nest_list);
index->note_array = code_index_note_ptr_array_from_list(&arena, &index->note_list);
code_index_lock();
code_index_set_file(buffer_id, arena, index);
code_index_unlock();
buffer_clear_layout_cache(app, buffer_id);
tree_sitter_query_end(&query);
tree_sitter_code_index_update_single_buffer(app, modified_node->buffer);
}
buffer_modified_set_clear();

View File

@ -68,6 +68,7 @@ function void tree_sitter_register_language(String_Const_u8 ext, TSLanguage* lan
b8 use_tree_sitter_code_indexing = true;
b8 use_tree_sitter_token_coloring = true;
function void tree_sitter_code_index_update_single_buffer(Application_Links *app, Buffer_ID buffer_id);
function void tree_sitter_code_index_update_tick(Application_Links *app);
#endif //FCODER_TREE_SITTER_H