Incrementally re-parse notes and scope delimiters within the range of a single edit.
This commit is contained in:
parent
6d7f1281b2
commit
12322796c2
|
@ -230,11 +230,44 @@ code_index_shift_list(Code_Index_Nest_List *list, Range_i64 old_range, u64 new_s
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
code_index_shift(Code_Index_File *file, Range_i64 old_range, u64 new_size)
|
code_index_shift_list(Code_Index_Scope_Delim_List *list, Range_i64 old_range, u64 new_size)
|
||||||
{
|
{
|
||||||
code_index_shift_list(&file->nest_list, old_range, new_size);
|
i32 count = list->count;
|
||||||
|
Code_Index_Scope_Delim *delim = list->first;
|
||||||
|
for (i32 i = 0; i < count; i += 1, delim = delim->next)
|
||||||
|
{
|
||||||
|
if (old_range.min == old_range.max)
|
||||||
|
{
|
||||||
|
if (old_range.max <= delim->pos.min)
|
||||||
|
{
|
||||||
|
delim->pos.min = delim->pos.min + new_size - (old_range.max - old_range.min);
|
||||||
|
delim->pos.max = delim->pos.max + new_size - (old_range.max - old_range.min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (old_range.min <= delim->pos.min && delim->pos.min < old_range.max) {
|
||||||
|
delim->pos.min = old_range.first;
|
||||||
|
} else if (old_range.max <= delim->pos.min) {
|
||||||
|
delim->pos.min = delim->pos.min + new_size - (old_range.max - old_range.min);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_range.min < delim->pos.max && delim->pos.max <= old_range.max) {
|
||||||
|
delim->pos.max = old_range.first;
|
||||||
|
} else if (old_range.max <= delim->pos.max) {
|
||||||
|
delim->pos.max = delim->pos.max + new_size - (old_range.max - old_range.min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
code_index_shift(Code_Index_File *file, Range_i64 old_range, u64 new_size)
|
||||||
|
{
|
||||||
|
// TODO(PS): @DontShiftNestList - This is unnecessary now that nest_list just gets fully rebuilt each edit
|
||||||
|
code_index_shift_list(&file->nest_list, old_range, new_size);
|
||||||
|
code_index_shift_list(&file->scope_delim_list, old_range, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// NOTE(allen): Parser Helpers
|
// NOTE(allen): Parser Helpers
|
||||||
|
|
|
@ -144,7 +144,9 @@ BUFFER_EDIT_RANGE_SIG(custom_buffer_edit_range){
|
||||||
{
|
{
|
||||||
code_index_lock();
|
code_index_lock();
|
||||||
Code_Index_File *file = code_index_get_file(buffer_id);
|
Code_Index_File *file = code_index_get_file(buffer_id);
|
||||||
if (file != 0) code_index_shift(file, old_range, range_size(new_range));
|
if (file != 0) {
|
||||||
|
code_index_shift(file, old_range, range_size(new_range));
|
||||||
|
}
|
||||||
code_index_unlock();
|
code_index_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,6 +389,23 @@ function void custom_render_buffer(
|
||||||
// NOTE(allen): put the actual text on the actual screen
|
// NOTE(allen): put the actual text on the actual screen
|
||||||
draw_text_layout_default(app, text_layout_id);
|
draw_text_layout_default(app, text_layout_id);
|
||||||
|
|
||||||
|
// TEMP - highlight the node range of the last edit
|
||||||
|
if (use_tree_sitter_token_coloring) {
|
||||||
|
Managed_Scope scope = buffer_get_managed_scope(app, buffer);
|
||||||
|
Buffer_Tree_Sitter_Data* tree_data = scope_attachment(app, scope, buffer_tree_sitter_data_id, Buffer_Tree_Sitter_Data);
|
||||||
|
for (int i = 0; i < tree_data->last_update_node_range_count; i++)
|
||||||
|
{
|
||||||
|
Range_i64 last_update_range = tree_data->last_update_node_range[i];
|
||||||
|
Rect_f32 range_min = text_layout_character_on_screen(app, text_layout_id, last_update_range.min);
|
||||||
|
Rect_f32 range_max = text_layout_character_on_screen(app, text_layout_id, last_update_range.max);
|
||||||
|
Rect_f32 range;
|
||||||
|
range.x0 = Min(range_min.x0, range_max.x0);
|
||||||
|
range.y0 = Min(range_min.y0, range_max.y0);
|
||||||
|
range.x1 = Max(range_min.x1, range_max.x1);
|
||||||
|
range.y1 = Max(range_min.y1, range_max.y1);
|
||||||
|
draw_rectangle(app, range, 0.f, 0x33FF00FF);
|
||||||
|
}
|
||||||
|
}
|
||||||
draw_set_clip(app, prev_clip);
|
draw_set_clip(app, prev_clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,16 +369,42 @@ code_index_new_scope_delim(Code_Index_File* index, Arena* arena, Code_Index_Scop
|
||||||
|
|
||||||
Code_Index_Scope_Delim *result = index->scope_delim_free;
|
Code_Index_Scope_Delim *result = index->scope_delim_free;
|
||||||
index->scope_delim_free = result->next;
|
index->scope_delim_free = result->next;
|
||||||
result->next = 0;
|
block_zero_struct(result);
|
||||||
|
|
||||||
sll_queue_push(index->scope_delim_list.first, index->scope_delim_list.last, result);
|
|
||||||
index->scope_delim_list.count += 1;
|
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->pos = range;
|
result->pos = range;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
code_index_scope_delim_insert(Code_Index_Scope_Delim_List* list, Code_Index_Scope_Delim* prev, Code_Index_Scope_Delim* delim)
|
||||||
|
{
|
||||||
|
if (!prev)
|
||||||
|
{
|
||||||
|
delim->next = list->first;
|
||||||
|
if (list->first) list->first->prev = delim;
|
||||||
|
else list->last = delim;
|
||||||
|
list->first = delim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Code_Index_Scope_Delim* next = prev->next;
|
||||||
|
prev->next = delim;
|
||||||
|
delim->prev = prev;
|
||||||
|
delim->next = next;
|
||||||
|
if (next) next->prev = delim;
|
||||||
|
if (prev == list->last) list->last = delim;
|
||||||
|
}
|
||||||
|
list->count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
code_index_free_scope_delim(Code_Index_File* index, Code_Index_Scope_Delim* delim)
|
||||||
|
{
|
||||||
|
delim->next = index->scope_delim_free;
|
||||||
|
index->scope_delim_free = delim;
|
||||||
|
}
|
||||||
|
|
||||||
function Code_Index_Note*
|
function Code_Index_Note*
|
||||||
code_index_new_note(Code_Index_File* index, Arena* arena, Code_Index_Note_Kind kind, Range_i64 range, Code_Index_Nest_Stack* parent)
|
code_index_new_note(Code_Index_File* index, Arena* arena, Code_Index_Note_Kind kind, Range_i64 range, Code_Index_Nest_Stack* parent)
|
||||||
{
|
{
|
||||||
|
@ -392,10 +418,8 @@ code_index_new_note(Code_Index_File* index, Arena* arena, Code_Index_Note_Kind k
|
||||||
|
|
||||||
Code_Index_Note *result = index->note_free;
|
Code_Index_Note *result = index->note_free;
|
||||||
index->note_free = result->next;
|
index->note_free = result->next;
|
||||||
result->next = 0;
|
block_zero_struct(result);
|
||||||
|
|
||||||
sll_queue_push(index->note_list.first, index->note_list.last, result);
|
|
||||||
index->note_list.count += 1;
|
|
||||||
result->file = index;
|
result->file = index;
|
||||||
result->note_kind = kind;
|
result->note_kind = kind;
|
||||||
result->pos = range;
|
result->pos = range;
|
||||||
|
@ -403,11 +427,38 @@ code_index_new_note(Code_Index_File* index, Arena* arena, Code_Index_Note_Kind k
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
code_index_note_insert(Code_Index_Note_List* list, Code_Index_Note* prev, Code_Index_Note* note)
|
||||||
|
{
|
||||||
|
if (!prev)
|
||||||
|
{
|
||||||
|
note->next = list->first;
|
||||||
|
if (!list->last) list->last = note;
|
||||||
|
list->first = note;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Code_Index_Note* next = prev->next;
|
||||||
|
prev->next = note;
|
||||||
|
note->next = next;
|
||||||
|
if (prev == list->last) list->last = note;
|
||||||
|
}
|
||||||
|
list->count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
code_index_free_note(Code_Index_File* index, Code_Index_Note* note)
|
||||||
|
{
|
||||||
|
block_zero_struct(note);
|
||||||
|
note->next = index->note_free;
|
||||||
|
index->note_free = note;
|
||||||
|
}
|
||||||
|
|
||||||
function Tree_Sitter_Code_Index_Update_State
|
function Tree_Sitter_Code_Index_Update_State
|
||||||
tree_sitter_code_index_update_state_create(
|
tree_sitter_code_index_update_state_create(
|
||||||
Application_Links* app,
|
Application_Links* app,
|
||||||
Buffer_ID buffer_id,
|
Buffer_ID buffer_id,
|
||||||
Code_Index_File_Storage code_index_storage,
|
Code_Index_File_Storage* code_index_storage,
|
||||||
Arena* scratch
|
Arena* scratch
|
||||||
){
|
){
|
||||||
Tree_Sitter_Code_Index_Update_State state = {};
|
Tree_Sitter_Code_Index_Update_State state = {};
|
||||||
|
@ -415,11 +466,21 @@ tree_sitter_code_index_update_state_create(
|
||||||
state.buffer_id = buffer_id;
|
state.buffer_id = buffer_id;
|
||||||
state.language = tree_sitter_language_for_buffer(app, state.buffer_id);
|
state.language = tree_sitter_language_for_buffer(app, state.buffer_id);
|
||||||
if (!state.language) return state;
|
if (!state.language) return state;
|
||||||
state.index_arena = code_index_storage.arena;
|
|
||||||
state.index = code_index_storage.file;
|
if (code_index_storage != 0)
|
||||||
|
{
|
||||||
|
state.index_arena = code_index_storage->arena;
|
||||||
|
state.index = code_index_storage->file;
|
||||||
|
} else {
|
||||||
|
state.index_arena = make_arena_system(KB(16));
|
||||||
|
state.index = push_array_zero(&state.index_arena, Code_Index_File, 1);
|
||||||
|
}
|
||||||
|
|
||||||
state.buffer_contents = push_whole_buffer(app, scratch, state.buffer_id);
|
state.buffer_contents = push_whole_buffer(app, scratch, state.buffer_id);
|
||||||
state.query = tree_sitter_query_init(
|
state.query = tree_sitter_query_init(
|
||||||
app, state.buffer_id, state.language->queries.ptr[Tree_Sitter_Language_Query_Tags]
|
app,
|
||||||
|
state.buffer_id,
|
||||||
|
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags]
|
||||||
);
|
);
|
||||||
state.nest_stack_first = 0;
|
state.nest_stack_first = 0;
|
||||||
state.nest_stack_last = 0;
|
state.nest_stack_last = 0;
|
||||||
|
@ -427,20 +488,21 @@ tree_sitter_code_index_update_state_create(
|
||||||
state.last_note_match_id = max_u32;
|
state.last_note_match_id = max_u32;
|
||||||
state.ok = true;
|
state.ok = true;
|
||||||
|
|
||||||
|
/* Freeing all delims is undesired for incremental updates, and unnecessary if
|
||||||
|
we're working with a wholly new index. The same will be true for notes soon.
|
||||||
if (state.index->scope_delim_list.last) {
|
if (state.index->scope_delim_list.last) {
|
||||||
state.index->scope_delim_list.last->next = state.index->scope_delim_free;
|
state.index->scope_delim_list.last->next = state.index->scope_delim_free;
|
||||||
}
|
}
|
||||||
state.index->scope_delim_free = state.index->scope_delim_list.first;
|
state.index->scope_delim_free = state.index->scope_delim_list.first;
|
||||||
state.index->scope_delim_list.first = 0;
|
block_zero_struct(&state.index->scope_delim_list);
|
||||||
state.index->scope_delim_list.last = 0;
|
|
||||||
|
|
||||||
if (state.index->note_list.last) {
|
if (state.index->note_list.last) {
|
||||||
state.index->note_list.last->next = state.index->note_free;
|
state.index->note_list.last->next = state.index->note_free;
|
||||||
}
|
}
|
||||||
state.index->note_free = state.index->note_list.first;
|
state.index->note_free = state.index->note_list.first;
|
||||||
state.index->note_list.first = 0;
|
block_zero_struct(&state.index->note_list);
|
||||||
state.index->note_list.last = 0;
|
*/
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,28 +537,41 @@ tree_sitter_code_index_update_process_query_match(
|
||||||
|
|
||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
{
|
||||||
code_index_new_scope_delim(state->index, &state->index_arena, kind, type_range);
|
Code_Index_Scope_Delim* delim = code_index_new_scope_delim(
|
||||||
|
state->index, &state->index_arena, kind, type_range
|
||||||
|
);
|
||||||
|
|
||||||
|
zdll_push_back(state->index->scope_delim_list.first, state->index->scope_delim_list.last, delim);
|
||||||
|
state->index->scope_delim_list.count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("definition.class")))
|
else if (string_match(capture_name, SCu8("definition.class")))
|
||||||
{
|
{
|
||||||
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Type, type_range, state->nest_stack_last);
|
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Type, type_range, state->nest_stack_last);
|
||||||
state->last_note_match_id = query_match.id;
|
state->last_note_match_id = query_match.id;
|
||||||
|
sll_queue_push(state->index->note_list.first, state->index->note_list.last, state->last_note);
|
||||||
|
state->index->note_list.count += 1;
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("definition.function")))
|
else if (string_match(capture_name, SCu8("definition.function")))
|
||||||
{
|
{
|
||||||
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Function, type_range, state->nest_stack_last);
|
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Function, type_range, state->nest_stack_last);
|
||||||
state->last_note_match_id = query_match.id;
|
state->last_note_match_id = query_match.id;
|
||||||
|
sll_queue_push(state->index->note_list.first, state->index->note_list.last, state->last_note);
|
||||||
|
state->index->note_list.count += 1;
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("definition.method")))
|
else if (string_match(capture_name, SCu8("definition.method")))
|
||||||
{
|
{
|
||||||
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Function, type_range, state->nest_stack_last);;
|
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Function, type_range, state->nest_stack_last);;
|
||||||
state->last_note_match_id = query_match.id;
|
state->last_note_match_id = query_match.id;
|
||||||
|
sll_queue_push(state->index->note_list.first, state->index->note_list.last, state->last_note);
|
||||||
|
state->index->note_list.count += 1;
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("definition.type")))
|
else if (string_match(capture_name, SCu8("definition.type")))
|
||||||
{
|
{
|
||||||
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Type, type_range, state->nest_stack_last);
|
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Type, type_range, state->nest_stack_last);
|
||||||
state->last_note_match_id = query_match.id;
|
state->last_note_match_id = query_match.id;
|
||||||
|
sll_queue_push(state->index->note_list.first, state->index->note_list.last, state->last_note);
|
||||||
|
state->index->note_list.count += 1;
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("name")))
|
else if (string_match(capture_name, SCu8("name")))
|
||||||
{
|
{
|
||||||
|
@ -511,14 +586,14 @@ function void
|
||||||
tree_sitter_code_index_update_complete(
|
tree_sitter_code_index_update_complete(
|
||||||
Application_Links* app,
|
Application_Links* app,
|
||||||
Tree_Sitter_Code_Index_Update_State* state,
|
Tree_Sitter_Code_Index_Update_State* state,
|
||||||
Arena* scratch
|
Arena* scratch,
|
||||||
|
bool update_was_incremental
|
||||||
){
|
){
|
||||||
tree_sitter_query_end(&state->query);
|
tree_sitter_query_end(&state->query);
|
||||||
if (state->ok)
|
if (state->ok)
|
||||||
{
|
{
|
||||||
Code_Index_Nest* free_nests = state->index->nest_list.first;
|
Code_Index_Nest* free_nests = state->index->nest_list.first;
|
||||||
state->index->nest_list.first = 0;
|
block_zero_struct(&state->index->nest_list);
|
||||||
state->index->nest_list.last = 0;
|
|
||||||
|
|
||||||
Code_Index_Scope_Delim* delim_at = state->index->scope_delim_list.first;
|
Code_Index_Scope_Delim* delim_at = state->index->scope_delim_list.first;
|
||||||
while (delim_at != 0)
|
while (delim_at != 0)
|
||||||
|
@ -543,13 +618,14 @@ tree_sitter_code_index_update_complete(
|
||||||
Code_Index_Nest* nest = free_nests;
|
Code_Index_Nest* nest = free_nests;
|
||||||
if (nest->nest_list.first)
|
if (nest->nest_list.first)
|
||||||
{
|
{
|
||||||
nest->nest_list.last->next = free_nests;
|
nest->nest_list.last->next = nest->next;
|
||||||
free_nests = nest->nest_list.first;
|
free_nests = nest->nest_list.first;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free_nests = nest->next;
|
free_nests = nest->next;
|
||||||
}
|
}
|
||||||
|
block_zero_struct(nest);
|
||||||
|
|
||||||
nest->kind = CodeIndexNest_Scope;
|
nest->kind = CodeIndexNest_Scope;
|
||||||
nest->delim = delim_at->kind;
|
nest->delim = delim_at->kind;
|
||||||
|
@ -589,14 +665,19 @@ tree_sitter_code_index_update_complete(
|
||||||
delim_at = delim_at->next;
|
delim_at = delim_at->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(PS): this should just be for the new notes - if a note wasn't
|
||||||
|
// updated incrementally this frame, then it already has it's text
|
||||||
for (Code_Index_Note* note = state->index->note_list.first; note != 0 && note->next != note; note = note->next)
|
for (Code_Index_Note* note = state->index->note_list.first; note != 0 && note->next != note; note = note->next)
|
||||||
{
|
{
|
||||||
note->text = push_string_copy(&state->index_arena, string_substring(state->buffer_contents, note->pos));
|
note->text = push_string_copy(&state->index_arena, string_substring(state->buffer_contents, note->pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
code_index_lock();
|
if (!update_was_incremental)
|
||||||
code_index_set_file(state->buffer_id, state->index_arena, state->index);
|
{
|
||||||
code_index_unlock();
|
code_index_lock();
|
||||||
|
code_index_set_file(state->buffer_id, state->index_arena, state->index);
|
||||||
|
code_index_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
buffer_clear_layout_cache(app, state->buffer_id);
|
buffer_clear_layout_cache(app, state->buffer_id);
|
||||||
}
|
}
|
||||||
|
@ -611,13 +692,10 @@ tree_sitter_code_index_update_full_file(Application_Links* app, Buffer_ID buffer
|
||||||
{
|
{
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
|
|
||||||
Code_Index_File_Storage storage;
|
|
||||||
storage.arena = make_arena_system(KB(16));
|
|
||||||
storage.file = push_array_zero(&storage.arena, Code_Index_File, 1);
|
|
||||||
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
|
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
|
||||||
app,
|
app,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
storage,
|
0,
|
||||||
scratch
|
scratch
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -633,7 +711,7 @@ tree_sitter_code_index_update_full_file(Application_Links* app, Buffer_ID buffer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_sitter_code_index_update_complete(app, &state, scratch);
|
tree_sitter_code_index_update_complete(app, &state, scratch, false);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,13 +724,10 @@ tree_sitter_code_index_update_async(Async_Context* actx, String_Const_u8 data)
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
|
|
||||||
acquire_global_frame_mutex(app);
|
acquire_global_frame_mutex(app);
|
||||||
Code_Index_File_Storage storage;
|
|
||||||
storage.arena = make_arena_system(KB(16));
|
|
||||||
storage.file = push_array_zero(&storage.arena, Code_Index_File, 1);
|
|
||||||
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
|
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
|
||||||
app,
|
app,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
storage,
|
0,
|
||||||
scratch
|
scratch
|
||||||
);
|
);
|
||||||
release_global_frame_mutex(app);
|
release_global_frame_mutex(app);
|
||||||
|
@ -669,49 +744,9 @@ tree_sitter_code_index_update_async(Async_Context* actx, String_Const_u8 data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_sitter_code_index_update_complete(app, &state, scratch);
|
tree_sitter_code_index_update_complete(app, &state, scratch, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
function void
|
|
||||||
tree_sitter_code_index_update_incremental(Application_Links* app, Buffer_ID buffer_id)
|
|
||||||
{
|
|
||||||
// TODO(PS): @Collapse with tree_sitter_code_index_update_state_create
|
|
||||||
Tree_Sitter_Code_Index_Update_State state = {};
|
|
||||||
state.ok = false;
|
|
||||||
state.buffer_id = buffer_id;
|
|
||||||
state.language = tree_sitter_language_for_buffer(app, state.buffer_id);
|
|
||||||
if (!state.language) return state;
|
|
||||||
|
|
||||||
Code_Index_File_Storage* storage = code_index_get_file_storage(state.buffer_id);
|
|
||||||
state.index_arena = storage->arena;
|
|
||||||
state.index = storage->file;
|
|
||||||
state.buffer_contents = push_whole_buffer(app, scratch, state.buffer_id);
|
|
||||||
state.query = tree_sitter_query_init(
|
|
||||||
app, state.buffer_id, state.language->queries.ptr[Tree_Sitter_Language_Query_Tags]
|
|
||||||
);
|
|
||||||
state.nest_stack_first = 0;
|
|
||||||
state.nest_stack_last = 0;
|
|
||||||
state.last_note = 0;
|
|
||||||
state.last_note_match_id = max_u32;
|
|
||||||
state.ok = true;
|
|
||||||
|
|
||||||
TSQueryMatch query_match;
|
|
||||||
u32 capture_index;
|
|
||||||
while (state.ok && tree_sitter_query_continue(&state.query, &query_match, &capture_index))
|
|
||||||
{
|
|
||||||
tree_sitter_code_index_update_process_query_match(
|
|
||||||
&state,
|
|
||||||
query_match,
|
|
||||||
capture_index,
|
|
||||||
scratch
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
tree_sitter_code_index_update_complete(app, &state, scratch);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function void
|
function void
|
||||||
tree_sitter_code_index_update_tick(Application_Links* app)
|
tree_sitter_code_index_update_tick(Application_Links* app)
|
||||||
{
|
{
|
||||||
|
@ -725,12 +760,191 @@ tree_sitter_code_index_update_tick(Application_Links* app)
|
||||||
Buffer_Tree_Sitter_Data* tree_data = scope_attachment(app, buffer_scope, buffer_tree_sitter_data_id, Buffer_Tree_Sitter_Data);
|
Buffer_Tree_Sitter_Data* tree_data = scope_attachment(app, buffer_scope, buffer_tree_sitter_data_id, Buffer_Tree_Sitter_Data);
|
||||||
if (!tree_data || !tree_data->tree) continue;
|
if (!tree_data || !tree_data->tree) continue;
|
||||||
|
|
||||||
#if 1
|
Range_i64 old_range = tree_data->last_update_old_range;
|
||||||
tree_sitter_code_index_update_full_file(app, buffer_id);
|
Range_i64 new_range = tree_data->last_update_new_range;
|
||||||
#else
|
if (old_range == new_range) continue;
|
||||||
tree_sitter_code_index_update_incremental(app, buffer_id);
|
|
||||||
#endif
|
Scratch_Block scratch(app);
|
||||||
|
Code_Index_File_Storage* storage = code_index_get_file_storage(buffer_id);
|
||||||
|
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
|
||||||
|
app,
|
||||||
|
buffer_id,
|
||||||
|
storage,
|
||||||
|
scratch
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find the largest, non-root node for us to reparse in its entirety
|
||||||
|
TSNode first_node = ts_node_descendant_for_byte_range(
|
||||||
|
state.query.first_node, new_range.min, new_range.max
|
||||||
|
);
|
||||||
|
|
||||||
|
printf("Initial Scope\n");
|
||||||
|
print_tree_sitter_tree(first_node, 0, "");
|
||||||
|
|
||||||
|
if (!ts_node_eq(first_node, state.query.first_node))
|
||||||
|
{
|
||||||
|
TSNode parent = ts_node_parent(first_node);
|
||||||
|
while (!ts_node_has_error(parent) && !ts_node_eq(parent, state.query.first_node))
|
||||||
|
{
|
||||||
|
first_node = parent;
|
||||||
|
parent = ts_node_parent(first_node);
|
||||||
|
printf("Ascending\n");
|
||||||
|
print_tree_sitter_tree(first_node, 0, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.query.first_node = first_node;
|
||||||
|
|
||||||
|
Range_i64 edit_range;
|
||||||
|
edit_range.min = (i64)ts_node_start_byte(state.query.first_node);
|
||||||
|
edit_range.max = (i64)ts_node_end_byte(state.query.first_node);
|
||||||
|
tree_data->last_update_node_range[0] = edit_range; // TODO(PS): TEMP - remove me once debugging is done
|
||||||
|
tree_data->last_update_node_range_count = 1;
|
||||||
|
|
||||||
|
// Free Scope Delimiters & Notes that fall within old_range
|
||||||
|
Code_Index_Scope_Delim* delim = state.index->scope_delim_list.first;
|
||||||
|
Code_Index_Scope_Delim* before_range = 0;
|
||||||
|
Code_Index_Scope_Delim* after_range = 0;
|
||||||
|
while (delim)
|
||||||
|
{
|
||||||
|
Code_Index_Scope_Delim* next = delim->next;
|
||||||
|
if (delim->pos.min < edit_range.min && delim->pos.max <= edit_range.min)
|
||||||
|
{
|
||||||
|
before_range = delim;
|
||||||
|
}
|
||||||
|
if (range_overlap(delim->pos, edit_range))
|
||||||
|
{
|
||||||
|
state.index->scope_delim_list.count -= 1;
|
||||||
|
zdll_remove(
|
||||||
|
state.index->scope_delim_list.first,
|
||||||
|
state.index->scope_delim_list.last,
|
||||||
|
delim
|
||||||
|
);
|
||||||
|
code_index_free_scope_delim(state.index, delim);
|
||||||
|
}
|
||||||
|
if (delim->pos.min >= edit_range.max)
|
||||||
|
{
|
||||||
|
after_range = delim;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delim = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Code_Index_Note* note = state.index->note_list.first;
|
||||||
|
Code_Index_Note* prev = 0;
|
||||||
|
Code_Index_Note* note_before_range = 0;
|
||||||
|
Code_Index_Note* note_after_range = 0;
|
||||||
|
while (note)
|
||||||
|
{
|
||||||
|
Code_Index_Note* next = note->next;
|
||||||
|
if (range_overlap(note->pos, edit_range))
|
||||||
|
{
|
||||||
|
Code_Index_Note* new_first = state.index->note_list.first;
|
||||||
|
Code_Index_Note* new_last = state.index->note_list.last;
|
||||||
|
Code_Index_Note* new_next = next;
|
||||||
|
|
||||||
|
if (note == state.index->note_list.first) new_first = next;
|
||||||
|
if (note == state.index->note_list.last)
|
||||||
|
{
|
||||||
|
if (prev) new_last = prev;
|
||||||
|
else new_last = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_first == 0) Assert(new_last == 0 && state.index->note_list.count == 1);
|
||||||
|
|
||||||
|
state.index->note_list.count -= 1;
|
||||||
|
state.index->note_list.first = new_first;
|
||||||
|
state.index->note_list.last = new_last;
|
||||||
|
if (prev) prev->next = new_next;
|
||||||
|
code_index_free_note(state.index, note);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev = note;
|
||||||
|
}
|
||||||
|
note = next;
|
||||||
|
}
|
||||||
|
if (state.index->note_list.count == 0) Assert(state.index->note_list.first == 0 && state.index->note_list.first == 0);
|
||||||
|
|
||||||
|
Code_Index_Scope_Delim* delim_prev = before_range;
|
||||||
|
TSQueryMatch query_match;
|
||||||
|
u32 capture_index;
|
||||||
|
while (state.ok && tree_sitter_query_continue(&state.query, &query_match, &capture_index))
|
||||||
|
{
|
||||||
|
// TODO(PS): @Collapse - the entire body of this while loop used to be in
|
||||||
|
// tree_sitter_code_index_update_process_query_match
|
||||||
|
// After we're done, see what we can do to collapse
|
||||||
|
|
||||||
|
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(state.query.query, type_capture.index, &length);
|
||||||
|
String_Const_u8 capture_name = SCu8((char*)tmp, length);
|
||||||
|
|
||||||
|
if (string_match(capture_name, SCu8("scope_begin")) || string_match(capture_name, SCu8("scope_end")))
|
||||||
|
{
|
||||||
|
Code_Index_Scope_Delim_Kind kind;
|
||||||
|
String_Const_u8 delim_char = string_substring(state.buffer_contents, type_range);
|
||||||
|
bool skip = false;
|
||||||
|
if (delim_char.str[0] == '{') kind = CodeIndexScopeDelim_ScopeOpen;
|
||||||
|
else if (delim_char.str[0] == '}') kind = CodeIndexScopeDelim_ScopeClose;
|
||||||
|
else if (delim_char.str[0] == '(') kind = CodeIndexScopeDelim_ParenOpen;
|
||||||
|
else if (delim_char.str[0] == ')') kind = CodeIndexScopeDelim_ParenClose;
|
||||||
|
else if (delim_char.str[0] == '[') kind = CodeIndexScopeDelim_BracketOpen;
|
||||||
|
else if (delim_char.str[0] == ']') kind = CodeIndexScopeDelim_BracketClose;
|
||||||
|
else skip = true;
|
||||||
|
|
||||||
|
if (!skip)
|
||||||
|
{
|
||||||
|
Code_Index_Scope_Delim* delim = code_index_new_scope_delim(
|
||||||
|
state.index, &state.index_arena, kind, type_range
|
||||||
|
);
|
||||||
|
code_index_scope_delim_insert(&state.index->scope_delim_list, delim_prev, delim);
|
||||||
|
delim_prev = delim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("definition.class")))
|
||||||
|
{
|
||||||
|
Code_Index_Note* note = code_index_new_note(state.index, &state.index_arena, CodeIndexNote_Type, type_range, state.nest_stack_last);
|
||||||
|
state.last_note_match_id = query_match.id;
|
||||||
|
code_index_note_insert(&state.index->note_list, state.last_note, note);
|
||||||
|
state.last_note = note;
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("definition.function")))
|
||||||
|
{
|
||||||
|
Code_Index_Note* note = code_index_new_note(state.index, &state.index_arena, CodeIndexNote_Function, type_range, state.nest_stack_last);
|
||||||
|
state.last_note_match_id = query_match.id;
|
||||||
|
code_index_note_insert(&state.index->note_list, state.last_note, note);
|
||||||
|
state.last_note = note;
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("definition.method")))
|
||||||
|
{
|
||||||
|
Code_Index_Note* note = code_index_new_note(state.index, &state.index_arena, CodeIndexNote_Function, type_range, state.nest_stack_last);;
|
||||||
|
state.last_note_match_id = query_match.id;
|
||||||
|
code_index_note_insert(&state.index->note_list, state.last_note, note);
|
||||||
|
state.last_note = note;
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("definition.type")))
|
||||||
|
{
|
||||||
|
Code_Index_Note* note = code_index_new_note(state.index, &state.index_arena, CodeIndexNote_Type, type_range, state.nest_stack_last);
|
||||||
|
state.last_note_match_id = query_match.id;
|
||||||
|
code_index_note_insert(&state.index->note_list, state.last_note, note);
|
||||||
|
state.last_note = note;
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("name")))
|
||||||
|
{
|
||||||
|
if (state.last_note != 0 && state.last_note_match_id == query_match.id)
|
||||||
|
{
|
||||||
|
state.last_note->pos = Ii64_size(type_range.start, type_range.end - type_range.start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_sitter_code_index_update_complete(app, &state, scratch, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_modified_set_clear();
|
buffer_modified_set_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1066,6 +1280,30 @@ CUSTOM_DOC("Creates a lister of locations that look like type definitions and de
|
||||||
|
|
||||||
char* prefix_buffer = " ";
|
char* prefix_buffer = " ";
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_tree_sitter_tree(TSNode cur_node, i32 level, const char* field)
|
||||||
|
{
|
||||||
|
TSPoint start = ts_node_start_point(cur_node);
|
||||||
|
TSPoint end = ts_node_end_point(cur_node);
|
||||||
|
// + 1 on ts positions becuase the first line/column are zero in treesitter,
|
||||||
|
printf("%.*s%s: %s [%d, %d] - [%d, %d]\n",
|
||||||
|
level*2, prefix_buffer, field, ts_node_type(cur_node),
|
||||||
|
start.row + 1, start.column + 1,
|
||||||
|
end.row + 1, end.column + 1);
|
||||||
|
|
||||||
|
u32 child_count = ts_node_child_count(cur_node);
|
||||||
|
for (u32 i = 0; i < child_count; ++i)
|
||||||
|
{
|
||||||
|
TSNode child = ts_node_child(cur_node, i);
|
||||||
|
if (ts_node_is_named(child))
|
||||||
|
{
|
||||||
|
field = ts_node_field_name_for_child(cur_node, i);
|
||||||
|
if (!field) field = "";
|
||||||
|
print_tree_sitter_tree(child, level + 1, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
write_tree_sitter_tree_to_buffer__inner(Application_Links *app, Arena *arena, Buffer_ID buffer_id,
|
write_tree_sitter_tree_to_buffer__inner(Application_Links *app, Arena *arena, Buffer_ID buffer_id,
|
||||||
TSNode cur_node, i32 level = 0, const char *field="")
|
TSNode cur_node, i32 level = 0, const char *field="")
|
||||||
|
|
|
@ -49,6 +49,7 @@ struct Buffer_Tree_Sitter_Data
|
||||||
// Code Index Update Requests
|
// Code Index Update Requests
|
||||||
Range_i64 last_update_old_range;
|
Range_i64 last_update_old_range;
|
||||||
Range_i64 last_update_new_range;
|
Range_i64 last_update_new_range;
|
||||||
|
Range_i64 last_update_node_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tree_Sitter_Query_Cursor
|
struct Tree_Sitter_Query_Cursor
|
||||||
|
@ -87,7 +88,6 @@ struct Tree_Sitter_Code_Index_Update_State
|
||||||
String_Const_u8 buffer_contents;
|
String_Const_u8 buffer_contents;
|
||||||
|
|
||||||
Tree_Sitter_Language_Definition* language;
|
Tree_Sitter_Language_Definition* language;
|
||||||
Tree_Sitter_Query_Cursor query;
|
|
||||||
|
|
||||||
Arena index_arena;
|
Arena index_arena;
|
||||||
Code_Index_File* index;
|
Code_Index_File* index;
|
||||||
|
@ -124,4 +124,6 @@ function Tree_Sitter_Code_Index_Update_State tree_sitter_code_index_update_full_
|
||||||
function void tree_sitter_code_index_update_tick(Application_Links *app);
|
function void tree_sitter_code_index_update_tick(Application_Links *app);
|
||||||
function void tree_sitter_code_index_update_async(Async_Context* actx, String_Const_u8 data);
|
function void tree_sitter_code_index_update_async(Async_Context* actx, String_Const_u8 data);
|
||||||
|
|
||||||
|
function void print_tree_sitter_tree(TSNode cur_node, i32 level, const char* field);
|
||||||
|
|
||||||
#endif //FCODER_TREE_SITTER_H
|
#endif //FCODER_TREE_SITTER_H
|
||||||
|
|
Loading…
Reference in New Issue