Compare commits

..

No commits in common. "8ad2b5bbffb4d140889b1c0233187074f13bdb4f" and "ee082e42d1e744d57d43236d55fcfc90f068ce9f" have entirely different histories.

13 changed files with 362 additions and 1112 deletions

View File

@ -257,7 +257,6 @@ get_active_edit_behaviors(Models *models, Editing_File *file){
api(custom) function b32 api(custom) function b32
buffer_replace_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string) buffer_replace_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string)
{ {
ProfileScope(app, "buffer_replace_range");
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
Editing_File *file = imp_get_file(models, buffer_id); Editing_File *file = imp_get_file(models, buffer_id);
b32 result = false; b32 result = false;
@ -339,7 +338,7 @@ buffer_seek_character_class(Application_Links *app, Buffer_ID buffer, Character_
Scratch_Block scratch(app); Scratch_Block scratch(app);
Gap_Buffer *gap_buffer = &file->state.buffer; Gap_Buffer *gap_buffer = &file->state.buffer;
List_String_Const_u8 chunks_list = buffer_get_chunks(scratch, gap_buffer); List_String_Const_u8 chunks_list = buffer_get_chunks(scratch, gap_buffer);
if (chunks_list.node_count > 0){ if (chunks_list.node_count > 0){
// TODO(allen): If you are reading this comment, then I haven't revisited this to tighten it up yet. // TODO(allen): If you are reading this comment, then I haven't revisited this to tighten it up yet.
// buffer_seek_character_class was originally implemented using the chunk indexer helper // buffer_seek_character_class was originally implemented using the chunk indexer helper
@ -359,7 +358,7 @@ buffer_seek_character_class(Application_Links *app, Buffer_ID buffer, Character_
chunks.vals[chunks.count] = node->string; chunks.vals[chunks.count] = node->string;
chunks.count += 1; chunks.count += 1;
} }
i64 size = buffer_size(gap_buffer); i64 size = buffer_size(gap_buffer);
start_pos = clamp(-1, start_pos, size); start_pos = clamp(-1, start_pos, size);
Buffer_Chunk_Position pos = buffer_get_chunk_position(chunks, size, start_pos); Buffer_Chunk_Position pos = buffer_get_chunk_position(chunks, size, start_pos);
@ -735,22 +734,22 @@ buffer_get_setting(Application_Links *app, Buffer_ID buffer_id, Buffer_Setting_I
{ {
*value_out = file->settings.unimportant; *value_out = file->settings.unimportant;
}break; }break;
case BufferSetting_Unkillable: case BufferSetting_Unkillable:
{ {
*value_out = (file->settings.never_kill || file->settings.unkillable); *value_out = (file->settings.never_kill || file->settings.unkillable);
}break; }break;
case BufferSetting_ReadOnly: case BufferSetting_ReadOnly:
{ {
*value_out = file->settings.read_only; *value_out = file->settings.read_only;
}break; }break;
case BufferSetting_RecordsHistory: case BufferSetting_RecordsHistory:
{ {
*value_out = history_is_activated(&file->state.history); *value_out = history_is_activated(&file->state.history);
}break; }break;
default: default:
{ {
result = false; result = false;
@ -778,17 +777,17 @@ buffer_set_setting(Application_Links *app, Buffer_ID buffer_id, Buffer_Setting_I
file_set_unimportant(file, false); file_set_unimportant(file, false);
} }
}break; }break;
case BufferSetting_Unkillable: case BufferSetting_Unkillable:
{ {
file->settings.unkillable = (value != 0); file->settings.unkillable = (value != 0);
}break; }break;
case BufferSetting_ReadOnly: case BufferSetting_ReadOnly:
{ {
file->settings.read_only = (value != 0); file->settings.read_only = (value != 0);
}break; }break;
case BufferSetting_RecordsHistory: case BufferSetting_RecordsHistory:
{ {
if (value){ if (value){
@ -802,14 +801,14 @@ buffer_set_setting(Application_Links *app, Buffer_ID buffer_id, Buffer_Setting_I
} }
} }
}break; }break;
default: default:
{ {
result = 0; result = 0;
}break; }break;
} }
} }
return(result); return(result);
} }
@ -855,7 +854,7 @@ buffer_save(Application_Links *app, Buffer_ID buffer_id, String_Const_u8 file_na
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
Editing_File *file = imp_get_file(models, buffer_id); Editing_File *file = imp_get_file(models, buffer_id);
b32 result = false; b32 result = false;
if (api_check_buffer(file)){ if (api_check_buffer(file)){
b32 skip_save = false; b32 skip_save = false;
@ -864,7 +863,7 @@ buffer_save(Application_Links *app, Buffer_ID buffer_id, String_Const_u8 file_na
skip_save = true; skip_save = true;
} }
} }
if (!skip_save){ if (!skip_save){
Thread_Context *tctx = app->tctx; Thread_Context *tctx = app->tctx;
Scratch_Block scratch(tctx); Scratch_Block scratch(tctx);
@ -873,7 +872,7 @@ buffer_save(Application_Links *app, Buffer_ID buffer_id, String_Const_u8 file_na
result = true; result = true;
} }
} }
return(result); return(result);
} }
@ -892,16 +891,16 @@ buffer_kill(Application_Links *app, Buffer_ID buffer_id, Buffer_Kill_Flag flags)
if (models->end_buffer != 0){ if (models->end_buffer != 0){
models->end_buffer(app, file->id); models->end_buffer(app, file->id);
} }
buffer_unbind_name_low_level(working_set, file); buffer_unbind_name_low_level(working_set, file);
if (file->canon.name_size != 0){ if (file->canon.name_size != 0){
buffer_unbind_file(working_set, file); buffer_unbind_file(working_set, file);
} }
file_free(tctx, models, file); file_free(tctx, models, file);
working_set_free_file(&models->heap, working_set, file); working_set_free_file(&models->heap, working_set, file);
Layout *layout = &models->layout; Layout *layout = &models->layout;
Node *order = &working_set->touch_order_sentinel; Node *order = &working_set->touch_order_sentinel;
Node *file_node = order->next; Node *file_node = order->next;
for (Panel *panel = layout_get_first_open_panel(layout); for (Panel *panel = layout_get_first_open_panel(layout);
@ -920,7 +919,7 @@ buffer_kill(Application_Links *app, Buffer_ID buffer_id, Buffer_Kill_Flag flags)
Assert(file_node != order); Assert(file_node != order);
} }
} }
Child_Process_Container *child_processes = &models->child_processes; Child_Process_Container *child_processes = &models->child_processes;
for (Node *node = child_processes->child_process_active_list.next; for (Node *node = child_processes->child_process_active_list.next;
node != &child_processes->child_process_active_list; node != &child_processes->child_process_active_list;
@ -930,7 +929,7 @@ buffer_kill(Application_Links *app, Buffer_ID buffer_id, Buffer_Kill_Flag flags)
child_process->out_file = 0; child_process->out_file = 0;
} }
} }
result = BufferKillResult_Killed; result = BufferKillResult_Killed;
} }
else{ else{
@ -957,20 +956,20 @@ buffer_reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl
Plat_Handle handle = {}; Plat_Handle handle = {};
if (system_load_handle(scratch, (char*)file->canon.name_space, &handle)){ if (system_load_handle(scratch, (char*)file->canon.name_space, &handle)){
File_Attributes attributes = system_load_attributes(handle); File_Attributes attributes = system_load_attributes(handle);
char *file_memory = push_array(scratch, char, (i32)attributes.size); char *file_memory = push_array(scratch, char, (i32)attributes.size);
if (file_memory != 0){ if (file_memory != 0){
if (system_load_file(handle, file_memory, (i32)attributes.size)){ if (system_load_file(handle, file_memory, (i32)attributes.size)){
system_load_close(handle); system_load_close(handle);
// TODO(allen): try(perform a diff maybe apply edits in reopen) // TODO(allen): try(perform a diff maybe apply edits in reopen)
i32 line_numbers[16]; i32 line_numbers[16];
i32 column_numbers[16]; i32 column_numbers[16];
View *vptrs[16]; View *vptrs[16];
i32 vptr_count = 0; i32 vptr_count = 0;
Layout *layout = &models->layout; Layout *layout = &models->layout;
for (Panel *panel = layout_get_first_open_panel(layout); for (Panel *panel = layout_get_first_open_panel(layout);
panel != 0; panel != 0;
@ -986,15 +985,15 @@ buffer_reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl
++vptr_count; ++vptr_count;
} }
} }
Working_Set *working_set = &models->working_set; Working_Set *working_set = &models->working_set;
file_free(tctx, models, file); file_free(tctx, models, file);
working_set_file_default_settings(working_set, file); working_set_file_default_settings(working_set, file);
file_create_from_string(tctx, models, file, SCu8(file_memory, attributes.size), attributes); file_create_from_string(tctx, models, file, SCu8(file_memory, attributes.size), attributes);
for (i32 i = 0; i < vptr_count; ++i){ for (i32 i = 0; i < vptr_count; ++i){
view_set_file(tctx, models, vptrs[i], file); view_set_file(tctx, models, vptrs[i], file);
vptrs[i]->file = file; vptrs[i]->file = file;
i64 line = line_numbers[i]; i64 line = line_numbers[i];
i64 col = column_numbers[i]; i64 col = column_numbers[i];
@ -1304,13 +1303,13 @@ panel_set_split(Application_Links *app, Panel_ID panel_id, Panel_Split_Kind kind
{ {
panel->split.v_f32 = clamp(0.f, t, 1.f); panel->split.v_f32 = clamp(0.f, t, 1.f);
}break; }break;
case PanelSplitKind_FixedPixels_Max: case PanelSplitKind_FixedPixels_Max:
case PanelSplitKind_FixedPixels_Min: case PanelSplitKind_FixedPixels_Min:
{ {
panel->split.v_i32 = i32_round32(t); panel->split.v_i32 = i32_round32(t);
}break; }break;
default: default:
{ {
print_message(app, string_u8_litexpr("Invalid split kind passed to panel_set_split, no change made to view layout")); print_message(app, string_u8_litexpr("Invalid split kind passed to panel_set_split, no change made to view layout"));
@ -1452,7 +1451,7 @@ view_get_setting(Application_Links *app, View_ID view_id, View_Setting_ID settin
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
View *view = imp_get_view(models, view_id); View *view = imp_get_view(models, view_id);
b32 result = false; b32 result = false;
if (api_check_view(view)){ if (api_check_view(view)){
result = true; result = true;
@ -1461,17 +1460,17 @@ view_get_setting(Application_Links *app, View_ID view_id, View_Setting_ID settin
{ {
*value_out = view->show_whitespace; *value_out = view->show_whitespace;
}break; }break;
case ViewSetting_ShowScrollbar: case ViewSetting_ShowScrollbar:
{ {
*value_out = !view->hide_scrollbar; *value_out = !view->hide_scrollbar;
}break; }break;
case ViewSetting_ShowFileBar: case ViewSetting_ShowFileBar:
{ {
*value_out = !view->hide_file_bar; *value_out = !view->hide_file_bar;
}break; }break;
default: default:
{ {
result = false; result = false;
@ -1486,7 +1485,7 @@ view_set_setting(Application_Links *app, View_ID view_id, View_Setting_ID settin
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
View *view = imp_get_view(models, view_id); View *view = imp_get_view(models, view_id);
b32 result = false; b32 result = false;
if (api_check_view(view)){ if (api_check_view(view)){
result = true; result = true;
@ -1495,17 +1494,17 @@ view_set_setting(Application_Links *app, View_ID view_id, View_Setting_ID settin
{ {
view->show_whitespace = (b8)value; view->show_whitespace = (b8)value;
}break; }break;
case ViewSetting_ShowScrollbar: case ViewSetting_ShowScrollbar:
{ {
view->hide_scrollbar = (b8)!value; view->hide_scrollbar = (b8)!value;
}break; }break;
case ViewSetting_ShowFileBar: case ViewSetting_ShowFileBar:
{ {
view->hide_file_bar = (b8)!value; view->hide_file_bar = (b8)!value;
}break; }break;
default: default:
{ {
result = false; result = false;
@ -1638,7 +1637,7 @@ view_set_mark(Application_Links *app, View_ID view_id, Buffer_Seek seek)
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
View *view = imp_get_view(models, view_id); View *view = imp_get_view(models, view_id);
b32 result = false; b32 result = false;
if (api_check_view(view)){ if (api_check_view(view)){
Editing_File *file = view->file; Editing_File *file = view->file;
@ -1832,19 +1831,19 @@ get_managed_scope_with_multiple_dependencies(Application_Links *app, Managed_Sco
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
Lifetime_Allocator *lifetime_allocator = &models->lifetime_allocator; Lifetime_Allocator *lifetime_allocator = &models->lifetime_allocator;
Scratch_Block scratch(app); Scratch_Block scratch(app);
// TODO(allen): revisit this // TODO(allen): revisit this
struct Node_Ptr{ struct Node_Ptr{
Node_Ptr *next; Node_Ptr *next;
Lifetime_Object *object_ptr; Lifetime_Object *object_ptr;
}; };
Node_Ptr *first = 0; Node_Ptr *first = 0;
Node_Ptr *last = 0; Node_Ptr *last = 0;
i32 member_count = 0; i32 member_count = 0;
b32 filled_array = true; b32 filled_array = true;
for (i32 i = 0; i < count; i += 1){ for (i32 i = 0; i < count; i += 1){
Dynamic_Workspace *workspace = get_dynamic_workspace(models, scopes[i]); Dynamic_Workspace *workspace = get_dynamic_workspace(models, scopes[i]);
@ -1852,13 +1851,13 @@ get_managed_scope_with_multiple_dependencies(Application_Links *app, Managed_Sco
filled_array = false; filled_array = false;
break; break;
} }
switch (workspace->user_type){ switch (workspace->user_type){
case DynamicWorkspace_Global: case DynamicWorkspace_Global:
{ {
// NOTE(allen): (global_scope INTERSECT X) == X for all X, therefore we emit nothing when a global group is in the key list. // NOTE(allen): (global_scope INTERSECT X) == X for all X, therefore we emit nothing when a global group is in the key list.
}break; }break;
case DynamicWorkspace_Unassociated: case DynamicWorkspace_Unassociated:
case DynamicWorkspace_Buffer: case DynamicWorkspace_Buffer:
case DynamicWorkspace_View: case DynamicWorkspace_View:
@ -1870,7 +1869,7 @@ get_managed_scope_with_multiple_dependencies(Application_Links *app, Managed_Sco
new_node->object_ptr = object; new_node->object_ptr = object;
member_count += 1; member_count += 1;
}break; }break;
case DynamicWorkspace_Intersected: case DynamicWorkspace_Intersected:
{ {
Lifetime_Key *key = (Lifetime_Key*)workspace->user_back_ptr; Lifetime_Key *key = (Lifetime_Key*)workspace->user_back_ptr;
@ -1885,14 +1884,14 @@ get_managed_scope_with_multiple_dependencies(Application_Links *app, Managed_Sco
} }
} }
}break; }break;
default: default:
{ {
InvalidPath; InvalidPath;
}break; }break;
} }
} }
Managed_Scope result = 0; Managed_Scope result = 0;
if (filled_array){ if (filled_array){
Lifetime_Object **object_ptr_array = push_array(scratch, Lifetime_Object*, member_count); Lifetime_Object **object_ptr_array = push_array(scratch, Lifetime_Object*, member_count);
@ -1907,7 +1906,7 @@ get_managed_scope_with_multiple_dependencies(Application_Links *app, Managed_Sco
Lifetime_Key *key = lifetime_get_or_create_intersection_key(lifetime_allocator, object_ptr_array, member_count); Lifetime_Key *key = lifetime_get_or_create_intersection_key(lifetime_allocator, object_ptr_array, member_count);
result = (Managed_Scope)key->dynamic_workspace.scope_id; result = (Managed_Scope)key->dynamic_workspace.scope_id;
} }
return(result); return(result);
} }
@ -2641,7 +2640,7 @@ buffer_set_face(Application_Links *app, Buffer_ID buffer_id, Face_ID id)
{ {
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
Editing_File *file = imp_get_file(models, buffer_id); Editing_File *file = imp_get_file(models, buffer_id);
b32 did_change = false; b32 did_change = false;
if (api_check_buffer(file)){ if (api_check_buffer(file)){
Face *face = font_set_face_from_id(&models->font_set, id); Face *face = font_set_face_from_id(&models->font_set, id);
@ -2913,13 +2912,13 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B
if (api_check_buffer(file)){ if (api_check_buffer(file)){
Thread_Context *tctx = app->tctx; Thread_Context *tctx = app->tctx;
Face *face = file_get_face(models, file); Face *face = file_get_face(models, file);
Gap_Buffer *buffer = &file->state.buffer; Gap_Buffer *buffer = &file->state.buffer;
Layout_Function *layout_func = file_get_layout_func(file); Layout_Function *layout_func = file_get_layout_func(file);
Vec2_f32 dim = rect_dim(rect); Vec2_f32 dim = rect_dim(rect);
i64 line_count = buffer_line_count(buffer); i64 line_count = buffer_line_count(buffer);
i64 line_number = buffer_point.line_number; i64 line_number = buffer_point.line_number;
f32 y = -buffer_point.pixel_shift.y; f32 y = -buffer_point.pixel_shift.y;
@ -2934,13 +2933,13 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B
} }
y = next_y; y = next_y;
} }
Range_i64 visible_line_number_range = Ii64(buffer_point.line_number, line_number); Range_i64 visible_line_number_range = Ii64(buffer_point.line_number, line_number);
Range_i64 visible_range = Ii64(buffer_get_first_pos_from_line_number(buffer, visible_line_number_range.min), Range_i64 visible_range = Ii64(buffer_get_first_pos_from_line_number(buffer, visible_line_number_range.min),
buffer_get_last_pos_from_line_number(buffer, visible_line_number_range.max)); buffer_get_last_pos_from_line_number(buffer, visible_line_number_range.max));
i64 item_count = range_size_inclusive(visible_range); i64 item_count = range_size_inclusive(visible_range);
Arena arena = make_arena_system(); Arena arena = make_arena_system();
Arena *arena_ptr = push_array_zero(&arena, Arena, 1); Arena *arena_ptr = push_array_zero(&arena, Arena, 1);
*arena_ptr = arena; *arena_ptr = arena;
@ -2993,16 +2992,16 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64
if (layout == 0){ if (layout == 0){
return(result); return(result);
} }
Layout_Function *layout_func = layout->layout_func; Layout_Function *layout_func = layout->layout_func;
Rect_f32 rect = layout->rect; Rect_f32 rect = layout->rect;
if (range_contains_inclusive(layout->visible_line_number_range, line_number)){ if (range_contains_inclusive(layout->visible_line_number_range, line_number)){
Editing_File *file = imp_get_file(models, layout->buffer_id); Editing_File *file = imp_get_file(models, layout->buffer_id);
if (api_check_buffer(file)){ if (api_check_buffer(file)){
f32 width = rect_width(rect); f32 width = rect_width(rect);
Face *face = file_get_face(models, file); Face *face = file_get_face(models, file);
for (i64 line_number_it = layout->visible_line_number_range.first;; for (i64 line_number_it = layout->visible_line_number_range.first;;
line_number_it += 1){ line_number_it += 1){
Layout_Item_List line = file_get_line_layout(app->tctx, models, file, Layout_Item_List line = file_get_line_layout(app->tctx, models, file,
@ -3014,7 +3013,7 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64
} }
result.min = result.max; result.min = result.max;
} }
result += rect.y0 - layout->point.pixel_shift.y; result += rect.y0 - layout->point.pixel_shift.y;
} }
} }
@ -3024,7 +3023,7 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64
else if (line_number > layout->visible_line_number_range.max){ else if (line_number > layout->visible_line_number_range.max){
result = If32(rect.y1, rect.y1); result = If32(rect.y1, rect.y1);
} }
return(result); return(result);
} }
@ -3038,14 +3037,14 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id
if (api_check_buffer(file)){ if (api_check_buffer(file)){
Gap_Buffer *buffer = &file->state.buffer; Gap_Buffer *buffer = &file->state.buffer;
i64 line_number = buffer_get_line_index(buffer, pos) + 1; i64 line_number = buffer_get_line_index(buffer, pos) + 1;
if (range_contains_inclusive(layout->visible_line_number_range, line_number)){ if (range_contains_inclusive(layout->visible_line_number_range, line_number)){
Rect_f32 rect = layout->rect; Rect_f32 rect = layout->rect;
f32 width = rect_width(rect); f32 width = rect_width(rect);
Face *face = file_get_face(models, file); Face *face = file_get_face(models, file);
Layout_Function *layout_func = layout->layout_func; Layout_Function *layout_func = layout->layout_func;
f32 y = 0.f; f32 y = 0.f;
Layout_Item_List line = {}; Layout_Item_List line = {};
for (i64 line_number_it = layout->visible_line_number_range.first;; for (i64 line_number_it = layout->visible_line_number_range.first;;
@ -3058,7 +3057,7 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id
} }
y += line.height; y += line.height;
} }
// TODO(allen): optimization: This is some fairly heavy computation. We really // TODO(allen): optimization: This is some fairly heavy computation. We really
// need to accelerate the (pos -> item) lookup within a single // need to accelerate the (pos -> item) lookup within a single
// Buffer_Layout_Item_List. // Buffer_Layout_Item_List.
@ -3082,7 +3081,7 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id
} }
} }
} }
Vec2_f32 shift = V2f32(rect.x0, rect.y0 + y) - layout->point.pixel_shift; Vec2_f32 shift = V2f32(rect.x0, rect.y0 + y) - layout->point.pixel_shift;
result.p0 += shift; result.p0 += shift;
result.p1 += shift; result.p1 += shift;

View File

@ -6,145 +6,50 @@
global Code_Index global_code_index = {}; global Code_Index global_code_index = {};
function bool
delims_are_open_close_pair(Code_Index_Scope_Delim_Kind a, Code_Index_Scope_Delim_Kind b)
{
if (a == CodeIndexScopeDelim_ScopeOpen) return b == CodeIndexScopeDelim_ScopeClose;
if (a == CodeIndexScopeDelim_ParenOpen) return b == CodeIndexScopeDelim_ParenClose;
if (a == CodeIndexScopeDelim_BracketOpen) return b == CodeIndexScopeDelim_BracketClose;
return false;
}
////////////////////////////////
// NOTE(allen): Code_Index_Note_List
function void
code_index_note_list_init(Code_Index_Note_List_New* list)
{
list->sentinel_first.next = &list->sentinel_last;
list->sentinel_last.next = 0;
list->count = 0;
}
function void
code_index_note_list_hash_init(Code_Index_Note_List_New* list)
{
list->sentinel_first.next_in_hash = &list->sentinel_last;
list->sentinel_first.prev_in_hash = 0;
list->sentinel_last.next_in_hash = 0;
list->sentinel_last.prev_in_hash = &list->sentinel_first;
list->count = 0;
}
function void
code_index_note_list_insert(Code_Index_Note_List_New* list, Code_Index_Note* prev, Code_Index_Note* note)
{
Assert(prev != 0);
Code_Index_Note* next = prev->next;
prev->next = note;
note->next = next;
list->count += 1;
}
function void
code_index_note_list_hash_insert(Code_Index_Note_List_New* list, Code_Index_Note* prev, Code_Index_Note* note)
{
Assert(prev != 0);
Code_Index_Note* next = prev->next_in_hash;
prev->next_in_hash = note;
note->prev_in_hash = prev;
note->next_in_hash = next;
next->prev_in_hash = note;
list->count += 1;
}
function void
code_index_note_list_hash_append(Code_Index_Note_List_New* list, Code_Index_Note* note)
{
Code_Index_Note* prev = list->sentinel_last.prev_in_hash;
Code_Index_Note* next = &list->sentinel_last;
prev->next_in_hash = note;
note->prev_in_hash = prev;
note->next_in_hash = next;
next->prev_in_hash = note;
list->count += 1;
}
function void
code_index_note_list_remove(Code_Index_Note_List_New* list, Code_Index_Note* prev, Code_Index_Note* note)
{
Assert(note->next != 0);
Assert(list->count > 0);
Code_Index_Note* next = note->next;
prev->next = next;
list->count -= 1;
note->next = 0;
}
function void
code_index_note_list_hash_remove(Code_Index_Note_List_New* list, Code_Index_Note* note)
{
Assert(note->prev_in_hash != 0 && note->next_in_hash != 0);
Assert(list->count > 0);
Code_Index_Note* prev = note->prev_in_hash;
Code_Index_Note* next = note->next_in_hash;
prev->next_in_hash = next;
next->prev_in_hash = prev;
list->count -= 1;
note->prev_in_hash = 0;
note->next_in_hash = 0;
}
//////////////////////////////// ////////////////////////////////
// NOTE(allen): Lookups // NOTE(allen): Lookups
// TODO(allen): accelerator for these nest lookups?
// Looks like the only one I ever actually use is the file one, not the array one.
function Code_Index_Nest* function Code_Index_Nest*
code_index_get_nest_from_list(Code_Index_Nest_List *list, i64 pos) code_index_get_nest_(Code_Index_Nest_Ptr_Array *array, i64 pos){
{
Code_Index_Nest *result = 0; Code_Index_Nest *result = 0;
i32 count = list->count; i32 count = array->count;
Code_Index_Nest *nest_at = list->first; Code_Index_Nest **nest_ptrs = array->ptrs;
for (i32 i = 0; i < count; i += 1){ for (i32 i = 0; i < count; i += 1){
if (nest_at->open.max <= pos && pos <= nest_at->close.min){ Code_Index_Nest *nest = nest_ptrs[i];
Code_Index_Nest *sub_nest = code_index_get_nest_from_list(&nest_at->nest_list, pos); if (nest->open.max <= pos && pos <= nest->close.min){
if (sub_nest != 0) Code_Index_Nest *sub_nest = code_index_get_nest_(&nest->nest_array, pos);
{ if (sub_nest != 0){
result = sub_nest; result = sub_nest;
} }
else else{
{ result = nest;
result = nest_at;
} }
break; break;
} }
nest_at = nest_at->next;
} }
return(result); return(result);
} }
function Code_Index_Nest* function Code_Index_Nest*
code_index_get_nest(Code_Index_File *file, i64 pos) code_index_get_nest(Code_Index_File *file, i64 pos){
{ return(code_index_get_nest_(&file->nest_array, pos));
Code_Index_Nest* result = code_index_get_nest_from_list(&file->nest_list, pos);
return result;
} }
function Code_Index_Note_List_New* function Code_Index_Note_List*
code_index__list_from_string(String_Const_u8 string) code_index__list_from_string(String_Const_u8 string){
{
u64 hash = table_hash_u8(string.str, string.size); u64 hash = table_hash_u8(string.str, string.size);
u64 index = hash % ArrayCount(global_code_index.name_hash); Code_Index_Note_List *result = &global_code_index.name_hash[hash % ArrayCount(global_code_index.name_hash)];
Code_Index_Note_List_New *result = &global_code_index.name_hash[index];
return(result); return(result);
} }
function Code_Index_Note* function Code_Index_Note*
code_index_note_from_string(String_Const_u8 string){ code_index_note_from_string(String_Const_u8 string){
Code_Index_Note_List_New *list = code_index__list_from_string(string); Code_Index_Note_List *list = code_index__list_from_string(string);
Code_Index_Note *result = 0; Code_Index_Note *result = 0;
for (Code_Index_Note *node = list->sentinel_first.next_in_hash; for (Code_Index_Note *node = list->first;
node != &list->sentinel_last; node != 0;
node = node->next_in_hash){ node = node->next_in_hash){
if (string_match(string, node->text)){ if (string_match(string, node->text)){
result = node; result = node;
@ -159,16 +64,10 @@ code_index_note_from_string(String_Const_u8 string){
// NOTE(allen): Global Code Index // NOTE(allen): Global Code Index
function void function void
code_index_init(void) code_index_init(void){
{
global_code_index.mutex = system_mutex_make(); global_code_index.mutex = system_mutex_make();
global_code_index.node_arena = make_arena_system(KB(4)); global_code_index.node_arena = make_arena_system(KB(4));
global_code_index.buffer_to_index_file = make_table_u64_u64(global_code_index.node_arena.base_allocator, 500); global_code_index.buffer_to_index_file = make_table_u64_u64(global_code_index.node_arena.base_allocator, 500);
for (int i = 0; i < ArrayCount(global_code_index.name_hash); i++)
{
code_index_note_list_hash_init(&global_code_index.name_hash[i]);
}
} }
function Code_Index_File_Storage* function Code_Index_File_Storage*
@ -198,6 +97,36 @@ code_index_push_nest(Code_Index_Nest_List *list, Code_Index_Nest *nest){
list->count += 1; list->count += 1;
} }
function Code_Index_Nest_Ptr_Array
code_index_nest_ptr_array_from_list(Arena *arena, Code_Index_Nest_List *list){
Code_Index_Nest_Ptr_Array array = {};
array.ptrs = push_array_zero(arena, Code_Index_Nest*, list->count);
array.count = list->count;
i32 counter = 0;
for (Code_Index_Nest *node = list->first;
node != 0;
node = node->next){
array.ptrs[counter] = node;
counter += 1;
}
return(array);
}
function Code_Index_Note_Ptr_Array
code_index_note_ptr_array_from_list(Arena *arena, Code_Index_Note_List *list){
Code_Index_Note_Ptr_Array array = {};
array.ptrs = push_array_zero(arena, Code_Index_Note*, list->count);
array.count = list->count;
i32 counter = 0;
for (Code_Index_Note *node = list->first;
node != 0;
node = node->next){
array.ptrs[counter] = node;
counter += 1;
}
return(array);
}
function void function void
code_index_lock(void){ code_index_lock(void){
system_mutex_acquire(global_code_index.mutex); system_mutex_acquire(global_code_index.mutex);
@ -210,16 +139,13 @@ code_index_unlock(void){
function void function void
code_index__hash_file(Code_Index_File *file){ code_index__hash_file(Code_Index_File *file){
// TODO(PS): @RemoveWholeFileHashing - this isn't necessary since, to support incremental updates
// we insert nodes into the hash table when the node is created
#if 0
for (Code_Index_Note *node = file->note_list.first; for (Code_Index_Note *node = file->note_list.first;
node != 0; node != 0;
node = node->next){ node = node->next){
Code_Index_Note_List_New *list = code_index__list_from_string(node->text); Code_Index_Note_List *list = code_index__list_from_string(node->text);
code_index_note_list_hash_insert(list, list->sentinel_last.prev_in_hash, node); zdll_push_back_NP_(list->first, list->last, node, next_in_hash, prev_in_hash);
list->count += 1;
} }
#endif
} }
function void function void
@ -227,8 +153,9 @@ code_index__clear_file(Code_Index_File *file){
for (Code_Index_Note *node = file->note_list.first; for (Code_Index_Note *node = file->note_list.first;
node != 0; node != 0;
node = node->next){ node = node->next){
Code_Index_Note_List_New *list = code_index__list_from_string(node->text); Code_Index_Note_List *list = code_index__list_from_string(node->text);
code_index_note_list_hash_remove(list, node); zdll_remove_NP_(list->first, list->last, node, next_in_hash, prev_in_hash);
list->count -= 1;
} }
} }
@ -269,30 +196,21 @@ code_index_erase_file(Buffer_ID buffer){
} }
} }
function Code_Index_File_Storage* function Code_Index_File*
code_index_get_file_storage(Buffer_ID buffer){ code_index_get_file(Buffer_ID buffer){
Code_Index_File_Storage *result = 0; Code_Index_File *result = 0;
Table_Lookup lookup = table_lookup(&global_code_index.buffer_to_index_file, buffer); Table_Lookup lookup = table_lookup(&global_code_index.buffer_to_index_file, buffer);
if (lookup.found_match){ if (lookup.found_match){
u64 val = 0; u64 val = 0;
table_read(&global_code_index.buffer_to_index_file, lookup, &val); table_read(&global_code_index.buffer_to_index_file, lookup, &val);
result = (Code_Index_File_Storage*)IntAsPtr(val); Code_Index_File_Storage *storage = (Code_Index_File_Storage*)IntAsPtr(val);
result = storage->file;
} }
return(result); return(result);
} }
function Code_Index_File*
code_index_get_file(Buffer_ID buffer)
{
Code_Index_File *result = 0;
Code_Index_File_Storage *storage = code_index_get_file_storage(buffer);
if (storage) result = storage->file;
return result;
}
function void function void
index_shift(i64 *ptr, Range_i64 old_range, u64 new_size) index_shift(i64 *ptr, Range_i64 old_range, u64 new_size){
{
i64 i = *ptr; i64 i = *ptr;
if (old_range.min <= i && i < old_range.max){ if (old_range.min <= i && i < old_range.max){
*ptr = old_range.first; *ptr = old_range.first;
@ -303,95 +221,27 @@ index_shift(i64 *ptr, Range_i64 old_range, u64 new_size)
} }
function void function void
code_index_shift_list(Code_Index_Nest_List *list, Range_i64 old_range, u64 new_size) code_index_shift(Code_Index_Nest_Ptr_Array *array,
{ Range_i64 old_range, u64 new_size){
i32 count = list->count; i32 count = array->count;
Code_Index_Nest *nest = list->first; Code_Index_Nest **nest_ptr = array->ptrs;
for (i32 i = 0; i < count; i += 1, nest = nest->next) for (i32 i = 0; i < count; i += 1, nest_ptr += 1){
{ Code_Index_Nest *nest = *nest_ptr;
index_shift(&nest->open.min, old_range, new_size); index_shift(&nest->open.min, old_range, new_size);
index_shift(&nest->open.max, old_range, new_size); index_shift(&nest->open.max, old_range, new_size);
if (nest->is_closed) if (nest->is_closed){
{
index_shift(&nest->close.min, old_range, new_size); index_shift(&nest->close.min, old_range, new_size);
index_shift(&nest->close.max, old_range, new_size); index_shift(&nest->close.max, old_range, new_size);
} }
code_index_shift_list(&nest->nest_list, old_range, new_size); code_index_shift(&nest->nest_array, old_range, new_size);
} }
} }
function void function void
code_index_shift_list(Code_Index_Scope_Delim_List *list, Range_i64 old_range, u64 new_size) code_index_shift(Code_Index_File *file, Range_i64 old_range, u64 new_size){
{ code_index_shift(&file->nest_array, 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_list(Code_Index_Note_List *list, Range_i64 old_range, u64 new_size)
{
i32 count = list->count;
Code_Index_Note *note = list->first;
for (i32 i = 0; i < count; i += 1, note = note->next)
{
if (old_range.min == old_range.max)
{
if (old_range.max <= note->pos.min)
{
note->pos.min = note->pos.min + new_size - (old_range.max - old_range.min);
note->pos.max = note->pos.max + new_size - (old_range.max - old_range.min);
}
}
else
{
if (old_range.min <= note->pos.min && note->pos.min < old_range.max) {
note->pos.min = old_range.first;
} else if (old_range.max <= note->pos.min) {
note->pos.min = note->pos.min + new_size - (old_range.max - old_range.min);
}
if (old_range.min < note->pos.max && note->pos.max <= old_range.max) {
note->pos.max = old_range.first;
} else if (old_range.max <= note->pos.max) {
note->pos.max = note->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);
code_index_shift_list(&file->note_list, old_range, new_size);
}
//////////////////////////////// ////////////////////////////////
// NOTE(allen): Parser Helpers // NOTE(allen): Parser Helpers
@ -727,6 +577,8 @@ generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state){
generic_parse_inc(state); generic_parse_inc(state);
} }
result->nest_array = code_index_nest_ptr_array_from_list(state->arena, &result->nest_list);
state->in_preprocessor = false; state->in_preprocessor = false;
return(result); return(result);
@ -805,6 +657,8 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state){
} }
} }
result->nest_array = code_index_nest_ptr_array_from_list(state->arena, &result->nest_list);
state->scope_counter -= 1; state->scope_counter -= 1;
return(result); return(result);
@ -885,6 +739,8 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state){
generic_parse_inc(state); generic_parse_inc(state);
} }
result->nest_array = code_index_nest_ptr_array_from_list(state->arena, &result->nest_list);
state->paren_counter -= 1; state->paren_counter -= 1;
return(result); return(result);
@ -947,6 +803,11 @@ generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *sta
} }
} }
if (result){
index->nest_array = code_index_nest_ptr_array_from_list(state->arena, &index->nest_list);
index->note_array = code_index_note_ptr_array_from_list(state->arena, &index->note_list);
}
return(result); return(result);
} }

View File

@ -7,37 +7,17 @@
#if !defined(FCODER_CODE_INDEX_H) #if !defined(FCODER_CODE_INDEX_H)
#define FCODER_CODE_INDEX_H #define FCODER_CODE_INDEX_H
typedef i32 Code_Index_Scope_Delim_Kind;
enum {
CodeIndexScopeDelim_ScopeOpen,
CodeIndexScopeDelim_ScopeClose,
CodeIndexScopeDelim_ParenOpen,
CodeIndexScopeDelim_ParenClose,
CodeIndexScopeDelim_BracketOpen,
CodeIndexScopeDelim_BracketClose
};
struct Code_Index_Scope_Delim {
Code_Index_Scope_Delim_Kind kind;
i32 depth;
Range_i64 pos;
Code_Index_Scope_Delim* next;
Code_Index_Scope_Delim* prev;
};
struct Code_Index_Scope_Delim_List {
Code_Index_Scope_Delim* first;
Code_Index_Scope_Delim* last;
i32 count;
};
struct Code_Index_Nest_List{ struct Code_Index_Nest_List{
struct Code_Index_Nest *first; struct Code_Index_Nest *first;
struct Code_Index_Nest *last; struct Code_Index_Nest *last;
i32 count; i32 count;
}; };
struct Code_Index_Nest_Ptr_Array{
struct Code_Index_Nest **ptrs;
i32 count;
};
typedef i32 Code_Index_Nest_Kind; typedef i32 Code_Index_Nest_Kind;
enum{ enum{
CodeIndexNest_Scope, CodeIndexNest_Scope,
@ -49,10 +29,7 @@ enum{
struct Code_Index_Nest{ struct Code_Index_Nest{
Code_Index_Nest *next; Code_Index_Nest *next;
// TODO(PS): kind and delim are redundant, I don't want to break virtual indentation just yet
// so Im leaving them both here.
Code_Index_Nest_Kind kind; Code_Index_Nest_Kind kind;
Code_Index_Scope_Delim_Kind delim;
b32 is_closed; b32 is_closed;
Range_i64 open; Range_i64 open;
Range_i64 close; Range_i64 close;
@ -61,6 +38,7 @@ struct Code_Index_Nest{
Code_Index_Nest *parent; Code_Index_Nest *parent;
Code_Index_Nest_List nest_list; Code_Index_Nest_List nest_list;
Code_Index_Nest_Ptr_Array nest_array;
}; };
typedef i64 Code_Index_Note_Kind; typedef i64 Code_Index_Note_Kind;
@ -89,20 +67,17 @@ struct Code_Index_Note_List{
i32 count; i32 count;
}; };
struct Code_Index_Note_List_New { struct Code_Index_Note_Ptr_Array{
Code_Index_Note sentinel_first; Code_Index_Note **ptrs;
Code_Index_Note sentinel_last;
i32 count; i32 count;
}; };
struct Code_Index_File{ struct Code_Index_File{
Code_Index_Scope_Delim_List scope_delim_list;
Code_Index_Nest_List nest_list; Code_Index_Nest_List nest_list;
Code_Index_Nest_Ptr_Array nest_array;
Code_Index_Note_List note_list; Code_Index_Note_List note_list;
Code_Index_Note_Ptr_Array note_array;
Buffer_ID buffer; Buffer_ID buffer;
Code_Index_Scope_Delim* scope_delim_free;
Code_Index_Note* note_free;
String_Pool string_pool;
}; };
struct Code_Index_File_Storage{ struct Code_Index_File_Storage{
@ -121,7 +96,7 @@ struct Code_Index{
Code_Index_File_Storage *storage_last; Code_Index_File_Storage *storage_last;
i32 storage_count; i32 storage_count;
Code_Index_Note_List_New name_hash[10000]; Code_Index_Note_List name_hash[10000];
}; };
//////////////////////////////// ////////////////////////////////

View File

@ -13,24 +13,24 @@ CUSTOM_UI_COMMAND_SIG(jump_to_definition)
CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the user.") CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the user.")
{ {
char *query = "Definition:"; char *query = "Definition:";
Scratch_Block scratch(app); Scratch_Block scratch(app);
Lister_Block lister(app, scratch); Lister_Block lister(app, scratch);
lister_set_query(lister, query); lister_set_query(lister, query);
lister_set_default_handlers(lister); lister_set_default_handlers(lister);
code_index_lock(); code_index_lock();
for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always);
buffer != 0; buffer != 0;
buffer = get_buffer_next(app, buffer, Access_Always)){ buffer = get_buffer_next(app, buffer, Access_Always)){
Code_Index_File *file = code_index_get_file(buffer); Code_Index_File *file = code_index_get_file(buffer);
if (file != 0){ if (file != 0){
Code_Index_Note* note = file->note_list.first; for (i32 i = 0; i < file->note_array.count; i += 1){
for (i32 i = 0; i < file->note_list.count; i += 1, note = note->next){ Code_Index_Note *note = file->note_array.ptrs[i];
Tiny_Jump *jump = push_array(scratch, Tiny_Jump, 1); Tiny_Jump *jump = push_array(scratch, Tiny_Jump, 1);
jump->buffer = buffer; jump->buffer = buffer;
jump->pos = note->pos.first; jump->pos = note->pos.first;
String_Const_u8 sort = {}; String_Const_u8 sort = {};
switch (note->note_kind){ switch (note->note_kind){
case CodeIndexNote_Type: case CodeIndexNote_Type:
@ -51,13 +51,13 @@ CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the
} }
} }
code_index_unlock(); code_index_unlock();
Lister_Result l_result = run_lister(app, lister); Lister_Result l_result = run_lister(app, lister);
Tiny_Jump result = {}; Tiny_Jump result = {};
if (!l_result.canceled && l_result.user_data != 0){ if (!l_result.canceled && l_result.user_data != 0){
block_copy_struct(&result, (Tiny_Jump*)l_result.user_data); block_copy_struct(&result, (Tiny_Jump*)l_result.user_data);
} }
if (result.buffer != 0){ if (result.buffer != 0){
View_ID view = get_this_ctx_view(app, Access_Always); View_ID view = get_this_ctx_view(app, Access_Always);
point_stack_push_view_cursor(app, view); point_stack_push_view_cursor(app, view);
@ -68,36 +68,31 @@ CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the
CUSTOM_UI_COMMAND_SIG(jump_to_definition_at_cursor) CUSTOM_UI_COMMAND_SIG(jump_to_definition_at_cursor)
CUSTOM_DOC("Jump to the first definition in the code index matching an identifier at the cursor") CUSTOM_DOC("Jump to the first definition in the code index matching an identifier at the cursor")
{ {
View_ID view = get_active_view(app, Access_Visible); View_ID view = get_active_view(app, Access_Visible);
if (view != 0) if (view != 0){
{ Scratch_Block scratch(app);
Scratch_Block scratch(app); String_Const_u8 query = push_token_or_word_under_active_cursor(app, scratch);
String_Const_u8 query = push_token_or_word_under_active_cursor(app, scratch);
code_index_lock();
code_index_lock(); for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always);
for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); buffer != 0;
buffer != 0; buffer = get_buffer_next(app, buffer, Access_Always)){
buffer = get_buffer_next(app, buffer, Access_Always) Code_Index_File *file = code_index_get_file(buffer);
){ if (file != 0){
Code_Index_File *file = code_index_get_file(buffer); for (i32 i = 0; i < file->note_array.count; i += 1){
if (file != 0) Code_Index_Note *note = file->note_array.ptrs[i];
{ if (string_match(note->text, query)){
Code_Index_Note *note = file->note_list.first; point_stack_push_view_cursor(app, view);
for (i32 i = 0; i < file->note_list.count; i += 1, note = note->next) jump_to_location(app, view, buffer, note->pos.first);
{ goto done;
if (string_match(note->text, query)) }
{ }
point_stack_push_view_cursor(app, view); }
jump_to_location(app, view, buffer, note->pos.first);
goto done;
}
} }
} done:;
code_index_unlock();
} }
done:;
code_index_unlock();
}
} }
global String_Const_u8 code_index_note_strs[] = { global String_Const_u8 code_index_note_strs[] = {
@ -127,20 +122,20 @@ lister_add_from_buffer_code_index_filtered(Lister* lister, Buffer_ID buffer, Are
{ {
Code_Index_File* file_notes = code_index_get_file(buffer); Code_Index_File* file_notes = code_index_get_file(buffer);
if (!file_notes) return; if (!file_notes) return;
for (Code_Index_Note* note = file_notes->note_list.first; for (Code_Index_Note* note = file_notes->note_list.first;
note != 0; note != 0;
note = note->next) note = note->next)
{ {
if (!note_is_of_kind(kinds, kinds_count, note)) continue; if (!note_is_of_kind(kinds, kinds_count, note)) continue;
if (filter_all_but_last && note->next_in_hash) continue; if (filter_all_but_last && note->next_in_hash) continue;
String_Const_u8 sort = code_index_note_strs[note->note_kind]; String_Const_u8 sort = code_index_note_strs[note->note_kind];
Tiny_Jump *jump = push_array(scratch, Tiny_Jump, 1); Tiny_Jump *jump = push_array(scratch, Tiny_Jump, 1);
jump->buffer = buffer; jump->buffer = buffer;
jump->pos = note->pos.start; jump->pos = note->pos.start;
lister_add_item(lister, note->text, sort, jump, 0); lister_add_item(lister, note->text, sort, jump, 0);
} }
} }
@ -153,7 +148,7 @@ run_jump_lister(Application_Links* app, Lister* lister)
if (!l_result.canceled && l_result.user_data != 0){ if (!l_result.canceled && l_result.user_data != 0){
block_copy_struct(&result, (Tiny_Jump*)l_result.user_data); block_copy_struct(&result, (Tiny_Jump*)l_result.user_data);
} }
if (result.buffer != 0) if (result.buffer != 0)
{ {
View_ID view = get_this_ctx_view(app, Access_Always); View_ID view = get_this_ctx_view(app, Access_Always);
@ -169,7 +164,7 @@ lister_search_filtered(Application_Links* app, char* query, Code_Index_Note_Kind
Lister_Block lister(app, scratch); Lister_Block lister(app, scratch);
lister_set_query(lister, query); lister_set_query(lister, query);
lister_set_default_handlers(lister); lister_set_default_handlers(lister);
for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always);
buffer != 0; buffer = get_buffer_next(app, buffer, Access_Always)) buffer != 0; buffer = get_buffer_next(app, buffer, Access_Always))
{ {

View File

@ -92,7 +92,7 @@ BUFFER_HOOK_SIG(custom_end_buffer){
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
BUFFER_EDIT_RANGE_SIG(custom_buffer_edit_range){ BUFFER_EDIT_RANGE_SIG(custom_buffer_edit_range){
ProfileScope(app, "custom edit range"); ProfileScope(app, "default edit range");
Scratch_Block scratch(app); Scratch_Block scratch(app);
Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); Managed_Scope scope = buffer_get_managed_scope(app, buffer_id);
@ -101,7 +101,6 @@ BUFFER_EDIT_RANGE_SIG(custom_buffer_edit_range){
b8 trigger_code_index_update = false; b8 trigger_code_index_update = false;
{ // Tree Sitter { // Tree Sitter
ProfileScope(app, "Tree Sitter Shift");
Buffer_Tree_Sitter_Data* tree_data = scope_attachment(app, scope, buffer_tree_sitter_data_id, Buffer_Tree_Sitter_Data); Buffer_Tree_Sitter_Data* tree_data = scope_attachment(app, scope, buffer_tree_sitter_data_id, Buffer_Tree_Sitter_Data);
// TODO(PS): if there's not tree_data, we actually want to block // TODO(PS): if there's not tree_data, we actually want to block
@ -143,12 +142,9 @@ BUFFER_EDIT_RANGE_SIG(custom_buffer_edit_range){
buffer_shift_fade_ranges(buffer_id, old_range.max, (new_range.max - old_range.max)); buffer_shift_fade_ranges(buffer_id, old_range.max, (new_range.max - old_range.max));
{ {
ProfileScope(app, "Code Index Shift");
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) { if (file != 0) code_index_shift(file, old_range, range_size(new_range));
code_index_shift(file, old_range, range_size(new_range));
}
code_index_unlock(); code_index_unlock();
} }
@ -391,20 +387,6 @@ 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);
Range_i64 last_update_range = tree_data->last_update_node_range;
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);
} }

View File

@ -45,10 +45,10 @@ go_to_definition(Application_Links* app, String_Const_u8 lexeme, View_ID view)
// and then loop // and then loop
if (string_match(go_to_definition_last_lexeme, lexeme)) if (string_match(go_to_definition_last_lexeme, lexeme))
{ {
Code_Index_Note_List_New* list = code_index__list_from_string(lexeme); Code_Index_Note_List* list = code_index__list_from_string(lexeme);
u64 i = 0; u64 i = 0;
for (Code_Index_Note *it = list->sentinel_first.next_in_hash; for (Code_Index_Note *it = list->first;
it != &list->sentinel_last; it != 0;
it = it->next_in_hash, i++){ it = it->next_in_hash, i++){
if (string_match(lexeme, it->text) && i > go_to_definition_last_lexeme_index){ if (string_match(lexeme, it->text) && i > go_to_definition_last_lexeme_index){
note = it; note = it;

View File

@ -273,6 +273,44 @@ default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){
return(region); return(region);
} }
function void
recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range,
Code_Index_Nest_Ptr_Array *array, i32 counter){
Code_Index_Nest **ptr = array->ptrs;
Code_Index_Nest **ptr_end = ptr + array->count;
for (;ptr < ptr_end; ptr += 1){
Code_Index_Nest *nest = *ptr;
if (!nest->is_closed){
break;
}
if (range.first <= nest->close.max){
break;
}
}
ARGB_Color argb = finalize_color(defcolor_text_cycle, counter);
for (;ptr < ptr_end; ptr += 1){
Code_Index_Nest *nest = *ptr;
if (range.max <= nest->open.min){
break;
}
paint_text_color(app, layout_id, nest->open, argb);
if (nest->is_closed){
paint_text_color(app, layout_id, nest->close, argb);
}
recursive_nest_highlight(app, layout_id, range, &nest->nest_array, counter + 1);
}
}
function void
recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range,
Code_Index_File *file){
recursive_nest_highlight(app, layout_id, range, &file->nest_array, 0);
}
function void default_render_buffer( function void default_render_buffer(
Application_Links *app, Application_Links *app,
View_ID view_id, View_ID view_id,

View File

@ -19,7 +19,6 @@
#include "4coder_table.h" #include "4coder_table.h"
#include "4coder_events.h" #include "4coder_events.h"
#include "4coder_types.h" #include "4coder_types.h"
#include "4coder_string_pool.h"
#include "4coder_doc_content_types.h" #include "4coder_doc_content_types.h"
#include "4coder_default_colors.h" #include "4coder_default_colors.h"
#define DYNAMIC_LINK_API #define DYNAMIC_LINK_API
@ -31,7 +30,6 @@
#include "generated/command_metadata.h" #include "generated/command_metadata.h"
#endif #endif
#include "4coder_token.h" #include "4coder_token.h"
#include "generated/lexer_cpp.h" #include "generated/lexer_cpp.h"
@ -75,7 +73,7 @@
#include "4coder_stringf.cpp" #include "4coder_stringf.cpp"
#include "4coder_app_links_allocator.cpp" #include "4coder_app_links_allocator.cpp"
#include "4coder_system_allocator.cpp" #include "4coder_system_allocator.cpp"
#include "4coder_string_pool.cpp"
#include "4coder_file.cpp" #include "4coder_file.cpp"
#define DYNAMIC_LINK_API #define DYNAMIC_LINK_API

View File

@ -1,129 +0,0 @@
function void
string_pool_init(String_Pool* pool)
{
pool->free_first.next = &pool->free_last;
pool->free_last.prev = &pool->free_first;
}
function String_Pool_Free_List*
free_string_inner(String_Pool* pool, String_Const_u8 str)
{
String_Pool_Free_List* free_at = (String_Pool_Free_List*)str.str;
free_at->next = 0; free_at->prev = 0;
free_at->size = str.size;
String_Pool_Free_List* prev = 0;
for (String_Pool_Free_List* at = pool->free_first.next; at != &pool->free_last; at = prev->next)
{
u8* addr = (u8*)at;
if (addr < (u8*)free_at) prev = at;
else break;
}
if (prev)
{
String_Pool_Free_List* next = prev->next;
prev->next = free_at;
free_at->prev = prev;
free_at->next = next;
next->prev = free_at;
b8 should_merge = (u8*)prev + prev->size == (u8*)free_at;
if (should_merge) free_at = prev;
}
else
{
String_Pool_Free_List* prev = &pool->free_first;
String_Pool_Free_List* next = pool->free_first.next;
prev->next = free_at;
free_at->prev = prev;
free_at->next = next;
next->prev = free_at;
}
while ((u8*)free_at + free_at->size == (u8*)free_at->next)
{
String_Pool_Free_List* next = free_at->next;
free_at->size += next->size;
next->next->prev = free_at;
free_at->next = next->next;
}
return free_at;
}
function String_Pool_Free_List*
string_pool_push_buffer(String_Pool* pool, int size_provided, Arena* backing_arena)
{
u64 next_buffer_size = pool->last_buffer_size * 2;
if (next_buffer_size == 0) next_buffer_size = KB(4);
String_Const_u8 buffer_data = string_const_u8_push(backing_arena, next_buffer_size);
pool->last_buffer_size = next_buffer_size;
String_Pool_Buffer* buffer = (String_Pool_Buffer*)buffer_data.str;
buffer_data.str += sizeof(String_Pool_Buffer);
buffer_data.size -= sizeof(String_Pool_Buffer);
buffer->data = buffer_data;
buffer->next = pool->buffers;
pool->buffers = buffer;
return free_string_inner(pool, buffer_data);
}
function String_Const_u8
alloc_string(String_Pool* pool, int size_provided, Arena* backing_arena)
{
int size = ((size_provided + STRING_POOL_ALLOC_SIZE - 1) / STRING_POOL_ALLOC_SIZE) * STRING_POOL_ALLOC_SIZE;
String_Pool_Free_List* free_at = pool->free_first.next;
while (free_at != &pool->free_last && free_at->size < size) free_at = free_at->next;
if (free_at == &pool->free_last || free_at->size < size)
{
free_at = string_pool_push_buffer(pool, size, backing_arena);
}
Assert(free_at->size >= size);
String_Const_u8 result;
result.str = (u8*)free_at;
result.size = size;
String_Pool_Free_List* prev = free_at->prev;
String_Pool_Free_List* next = free_at->next;
if (free_at->size - size > 0)
{
u8* new_free_at_ptr = (u8*)free_at;
String_Pool_Free_List* new_free_at = (String_Pool_Free_List*)(new_free_at_ptr + size);
new_free_at->size = free_at->size - size;
prev->next = new_free_at;
new_free_at->prev = prev;
new_free_at->next = next;
next->prev = new_free_at;
}
else
{
prev->next = next;
next->prev = prev;
}
block_zero(result.str, result.size);
return result;
}
function String_Const_u8
alloc_string_copy(String_Pool* pool, String_Const_u8 src, Arena* backing_arena)
{
String_Const_u8 dst = alloc_string(pool, src.size+1, backing_arena);
dst.size = src.size;
block_copy_dynamic_array(dst.str, src.str, src.size);
dst.str[src.size] = 0;
return dst;
}
function void
free_string(String_Pool* pool, String_Const_u8 str)
{
free_string_inner(pool, str);
}

View File

@ -1,29 +0,0 @@
/* date = August 3rd 2025 5:01 pm */
#ifndef FCODER_STRING_POOL_H
#define FCODER_STRING_POOL_H
#define STRING_POOL_ALLOC_SIZE 64
struct String_Pool_Free_List
{
i64 size;
String_Pool_Free_List* next;
String_Pool_Free_List* prev;
};
struct String_Pool_Buffer
{
String_Const_u8 data;
String_Pool_Buffer* next;
};
struct String_Pool
{
String_Pool_Buffer* buffers;
String_Pool_Free_List free_first;
String_Pool_Free_List free_last;
u64 last_buffer_size;
};
#endif //FCODER_STRING_POOL_H

View File

@ -206,14 +206,6 @@ tree_sitter_query_init(Application_Links* app, Buffer_ID buffer_id, TSQuery* que
return result; return result;
} }
function Tree_Sitter_Query_Cursor
tree_sitter_query_init(Application_Links* app, Buffer_ID buffer_id, TSQuery* query, TSNode first_node)
{
Tree_Sitter_Query_Cursor result = tree_sitter_query_init(app, buffer_id, query);
result.first_node = first_node;
return result;
}
function bool function bool
tree_sitter_query_continue(Tree_Sitter_Query_Cursor* cursor, TSQueryMatch* match, u32* capture_index) tree_sitter_query_continue(Tree_Sitter_Query_Cursor* cursor, TSQueryMatch* match, u32* capture_index)
{ {
@ -364,70 +356,12 @@ tree_sitter_node_to_range(TSNode node)
return result; return result;
} }
function Code_Index_Scope_Delim*
code_index_new_scope_delim(Code_Index_File* index, Arena* arena, Code_Index_Scope_Delim_Kind kind, Range_i64 range)
{
if (!index->scope_delim_free)
{
int count = 32;
Code_Index_Scope_Delim* arr = push_array_zero(arena, Code_Index_Scope_Delim, count);
for (int i = 0; i < count-1; i++) arr[i].next = &arr[i+1];
index->scope_delim_free = arr;
}
Code_Index_Scope_Delim *result = index->scope_delim_free;
index->scope_delim_free = result->next;
block_zero_struct(result);
result->kind = kind;
result->pos = range;
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)
{ {
if (!index->note_free) Code_Index_Note *result = push_array(arena, Code_Index_Note, 1);
{ sll_queue_push(index->note_list.first, index->note_list.last, result);
int count = 32; index->note_list.count += 1;
Code_Index_Note* arr = push_array_zero(arena, Code_Index_Note, count);
for (int i = 0; i < count-1; i++) arr[i].next = &arr[i+1];
index->note_free = arr;
}
Code_Index_Note *result = index->note_free;
index->note_free = result->next;
block_zero_struct(result);
result->file = index; result->file = index;
result->note_kind = kind; result->note_kind = kind;
result->pos = range; result->pos = range;
@ -435,38 +369,10 @@ 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,
Arena* scratch Arena* scratch
){ ){
Tree_Sitter_Code_Index_Update_State state = {}; Tree_Sitter_Code_Index_Update_State state = {};
@ -474,48 +380,23 @@ 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 = make_arena_system(KB(16));
if (code_index_storage != 0) state.index = push_array_zero(&state.index_arena, Code_Index_File, 1);
{
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);
string_pool_init(&state.index->string_pool);
state.index->buffer = buffer_id;
}
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(
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;
state.last_note = 0; state.last_note = 0;
state.last_note_match_id = max_u32; state.last_note_match_id = max_u32;
code_index_note_list_hash_init(&state.new_notes);
state.ok = true; state.ok = true;
/* @RemoveOldFreeingCode = 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) {
state.index->scope_delim_list.last->next = state.index->scope_delim_free;
}
state.index->scope_delim_free = state.index->scope_delim_list.first;
block_zero_struct(&state.index->scope_delim_list);
if (state.index->note_list.last) {
state.index->note_list.last->next = state.index->note_free;
}
state.index->note_free = state.index->note_list.first;
block_zero_struct(&state.index->note_list);
*/
return state; return state;
} }
function void function void
tree_sitter_code_index_update_process_query_match( tree_sitter_code_index_update_process_query_match(
Tree_Sitter_Code_Index_Update_State* state, Tree_Sitter_Code_Index_Update_State* state,
Tree_Sitter_Query_Cursor query,
TSQueryMatch query_match, TSQueryMatch query_match,
u32 capture_index, u32 capture_index,
Arena* scratch Arena* scratch
@ -526,171 +407,103 @@ tree_sitter_code_index_update_process_query_match(
Range_i64 type_range = tree_sitter_node_to_range(type_node); Range_i64 type_range = tree_sitter_node_to_range(type_node);
u32 length; u32 length;
const char* tmp = ts_query_capture_name_for_id(query.query, type_capture.index, &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); String_Const_u8 capture_name = SCu8((char*)tmp, length);
if (string_match(capture_name, SCu8("scope_begin")) || string_match(capture_name, SCu8("scope_end"))) if (string_match(capture_name, SCu8("scope_begin")))
{ {
Code_Index_Scope_Delim_Kind kind; Code_Index_Nest* nest = push_array_zero(&state->index_arena, Code_Index_Nest, 1);
String_Const_u8 delim_char = string_substring(state->buffer_contents, type_range); nest->kind = CodeIndexNest_Scope;
bool skip = false; nest->open = type_range;
if (delim_char.str[0] == '{') kind = CodeIndexScopeDelim_ScopeOpen; nest->close = Ii64(max_i64);
else if (delim_char.str[0] == '}') kind = CodeIndexScopeDelim_ScopeClose; nest->file = state->index;
else if (delim_char.str[0] == '(') kind = CodeIndexScopeDelim_ParenOpen; if (state->nest_stack_last != 0)
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( nest->parent = state->nest_stack_last->nest;
state->index, &state->index_arena, kind, type_range code_index_push_nest(&nest->parent->nest_list, nest);
);
code_index_scope_delim_insert(&state->index->scope_delim_list, state->last_delim, delim);
state->last_delim = delim;
} }
Code_Index_Nest_Stack* stack = push_array_zero(scratch, Code_Index_Nest_Stack, 1);
stack->nest = nest;
stack->prev = state->nest_stack_last;
stack->match_id = query_match.id;
if (state->nest_stack_last != 0) state->nest_stack_last->next = stack;
else state->nest_stack_first = stack;
state->nest_stack_last = stack;
}
else if (string_match(capture_name, SCu8("scope_end")))
{
Assert(state->nest_stack_last != 0);
Assert(state->nest_stack_last->match_id == query_match.id);
Code_Index_Nest* nest = state->nest_stack_last->nest;
nest->close = type_range;
nest->is_closed = true;
nest->nest_array = code_index_nest_ptr_array_from_list(&state->index_arena, &nest->nest_list);
if (nest->parent == 0) code_index_push_nest(&state->index->nest_list, nest);
state->nest_stack_last = state->nest_stack_last->prev;
if (state->nest_stack_last != 0) state->nest_stack_last->next = 0;
}
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_match_id = query_match.id;
}
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_match_id = query_match.id;
}
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_match_id = query_match.id;
}
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_match_id = query_match.id;
} }
else if (string_match(capture_name, SCu8("name"))) else if (string_match(capture_name, SCu8("name")))
{ {
Range_i64 range = Ii64_size(type_range.start, type_range.end - type_range.start); if (state->last_note != 0 && state->last_note_match_id == query_match.id)
bool apply_name_to_last_note = state->new_notes.sentinel_last.prev_in_hash != 0; {
apply_name_to_last_note &= state->last_note_match_id == query_match.id; state->last_note->pos = Ii64_size(type_range.start, type_range.end - type_range.start);
if (apply_name_to_last_note) state->new_notes.sentinel_last.prev_in_hash->pos = range; }
}
else
{
Code_Index_Note_Kind kind;
if (string_match(capture_name, SCu8("definition.class"))) kind = CodeIndexNote_Type;
else if (string_match(capture_name, SCu8("definition.function"))) kind = CodeIndexNote_Function;
else if (string_match(capture_name, SCu8("definition.method"))) kind = CodeIndexNote_Function;
else if (string_match(capture_name, SCu8("definition.type"))) kind = CodeIndexNote_Type;
Code_Index_Note* note = code_index_new_note(state->index, &state->index_arena, kind, type_range, state->nest_stack_last);
code_index_note_list_hash_append(&state->new_notes, note);
state->last_note_match_id = query_match.id;
} }
} }
function void 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,
bool update_was_incremental
){ ){
ProfileScope(app, "Complete Code Index Update"); tree_sitter_query_end(&state->query);
if (state->ok) if (state->ok)
{ {
Code_Index_Nest* free_nests = state->index->nest_list.first; while (state->nest_stack_last != 0)
block_zero_struct(&state->index->nest_list);
Code_Index_Scope_Delim* delim_at = state->index->scope_delim_list.first;
while (delim_at != 0)
{ {
bool is_open = ( Code_Index_Nest* nest = state->nest_stack_last->nest;
delim_at->kind == CodeIndexScopeDelim_ScopeOpen || if (nest->parent != 0) code_index_push_nest(&nest->parent->nest_list, nest);
delim_at->kind == CodeIndexScopeDelim_ParenOpen || else code_index_push_nest(&state->index->nest_list, nest);
delim_at->kind == CodeIndexScopeDelim_BracketOpen nest->nest_array = code_index_nest_ptr_array_from_list(&state->index_arena, &nest->nest_list);
); state->nest_stack_last = state->nest_stack_last->prev;
if (is_open)
{
if (!free_nests)
{
int count = 32;
free_nests = push_array_zero(&state->index_arena, Code_Index_Nest, count);
for (int i = 0; i < count-2; i++)
{
free_nests[i].next = &free_nests[i+1];
}
}
Code_Index_Nest* nest = free_nests;
if (nest->nest_list.first)
{
nest->nest_list.last->next = nest->next;
free_nests = nest->nest_list.first;
}
else
{
free_nests = nest->next;
}
block_zero_struct(nest);
nest->kind = CodeIndexNest_Scope;
nest->delim = delim_at->kind;
nest->open = delim_at->pos;
nest->close = Ii64(max_i64);
nest->file = state->index;
if (state->nest_stack_last != 0)
{
nest->parent = state->nest_stack_last->nest;
code_index_push_nest(&nest->parent->nest_list, nest);
}
else
{
code_index_push_nest(&state->index->nest_list, nest);
}
Code_Index_Nest_Stack* stack = push_array_zero(scratch, Code_Index_Nest_Stack, 1);
stack->nest = nest;
stack->prev = state->nest_stack_last;
if (state->nest_stack_last != 0) state->nest_stack_last->next = stack;
else state->nest_stack_first = stack;
state->nest_stack_last = stack;
}
else
{
if (state->nest_stack_last != 0 && delims_are_open_close_pair(state->nest_stack_last->nest->delim, delim_at->kind))
{
Code_Index_Nest* nest = state->nest_stack_last->nest;
nest->close = delim_at->pos;
nest->is_closed = true;
state->nest_stack_last = state->nest_stack_last->prev;
if (state->nest_stack_last != 0) state->nest_stack_last->next = 0;
}
}
delim_at = delim_at->next;
} }
for (Code_Index_Note* note = state->index->note_list.first; note != 0 && note->next != note; note = note->next)
{ {
ProfileScope(app, "Update Global Name Table"); note->text = push_string_copy(&state->index_arena, string_substring(state->buffer_contents, note->pos));
Code_Index_Note* note = state->new_notes.sentinel_first.next_in_hash;
Code_Index_Note* next = 0;
for (int i = 0; i < state->new_notes.count; i++)
{
next = note->next_in_hash;
note->next = 0; note->next_in_hash = 0; note->prev_in_hash = 0;
String_Const_u8 source = string_substring(
state->buffer_contents,
note->pos
);
note->text = alloc_string_copy(
&state->index->string_pool,
source,
&state->index_arena
);
note->file = state->index;
Code_Index_Note_List_New* hash_list = code_index__list_from_string(note->text);
code_index_note_list_hash_append(hash_list, note);
code_index_note_insert(&state->index->note_list, state->last_note, note);
state->last_note = note;
note = next;
}
} }
if (!update_was_incremental) // Finish the Index
{ state->index->nest_array = code_index_nest_ptr_array_from_list(&state->index_arena, &state->index->nest_list);
code_index_lock(); state->index->note_array = code_index_note_ptr_array_from_list(&state->index_arena, &state->index->note_list);
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);
} }
@ -700,6 +513,36 @@ tree_sitter_code_index_update_complete(
} }
} }
function Tree_Sitter_Code_Index_Update_State
tree_sitter_code_index_update_full_file_async(Async_Context* actx, Buffer_ID buffer_id)
{
Application_Links* app = actx->app;
Scratch_Block scratch(app);
acquire_global_frame_mutex(app);
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
app,
buffer_id,
scratch
);
release_global_frame_mutex(app);
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);
if (async_check_canceled(actx))
{
state.ok = false;
break;
}
}
tree_sitter_code_index_update_complete(app, &state);
return state;
}
function Tree_Sitter_Code_Index_Update_State function Tree_Sitter_Code_Index_Update_State
tree_sitter_code_index_update_full_file(Application_Links* app, Buffer_ID buffer_id) tree_sitter_code_index_update_full_file(Application_Links* app, Buffer_ID buffer_id)
{ {
@ -708,31 +551,22 @@ tree_sitter_code_index_update_full_file(Application_Links* app, Buffer_ID buffer
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,
0,
scratch scratch
); );
Tree_Sitter_Query_Cursor query = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags]
);
TSQueryMatch query_match; TSQueryMatch query_match;
u32 capture_index; u32 capture_index;
while (state.ok && tree_sitter_query_continue(&query, &query_match, &capture_index)) while (state.ok && tree_sitter_query_continue(&state.query, &query_match, &capture_index))
{ {
tree_sitter_code_index_update_process_query_match( tree_sitter_code_index_update_process_query_match(
&state, &state,
query,
query_match, query_match,
capture_index, capture_index,
scratch scratch
); );
} }
tree_sitter_query_end(&query); tree_sitter_code_index_update_complete(app, &state);
tree_sitter_code_index_update_complete(app, &state, scratch, false);
return state; return state;
} }
@ -741,37 +575,7 @@ tree_sitter_code_index_update_async(Async_Context* actx, String_Const_u8 data)
{ {
if (data.size != sizeof(Buffer_ID)) return; if (data.size != sizeof(Buffer_ID)) return;
Buffer_ID buffer_id = *(Buffer_ID*)data.str; Buffer_ID buffer_id = *(Buffer_ID*)data.str;
Application_Links* app = actx->app; tree_sitter_code_index_update_full_file_async(actx, buffer_id);
Scratch_Block scratch(app);
acquire_global_frame_mutex(app);
Tree_Sitter_Code_Index_Update_State state = tree_sitter_code_index_update_state_create(
app,
buffer_id,
0,
scratch
);
Tree_Sitter_Query_Cursor query = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags]
);
release_global_frame_mutex(app);
TSQueryMatch query_match;
u32 capture_index;
while (state.ok && tree_sitter_query_continue(&query, &query_match, &capture_index))
{
tree_sitter_code_index_update_process_query_match(&state, query, query_match, capture_index, scratch);
if (async_check_canceled(actx))
{
state.ok = false;
break;
}
}
tree_sitter_query_end(&query);
tree_sitter_code_index_update_complete(app, &state, scratch, false);
} }
function void function void
@ -782,208 +586,13 @@ tree_sitter_code_index_update_tick(Application_Links* app)
modified_node != 0; modified_node != 0;
modified_node = modified_node->next modified_node = modified_node->next
){ ){
ProfileScope(app, "Incremental Parse");
Buffer_ID buffer_id = modified_node->buffer; Buffer_ID buffer_id = modified_node->buffer;
Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer_id); Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer_id);
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;
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;
if (old_range == new_range) continue;
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 root = ts_tree_root_node(tree_data->tree);
TSNode first_node = ts_node_descendant_for_byte_range(
root, new_range.min, new_range.max
);
TSNode last_node = first_node;
bool would_reparse_entire_file = ts_node_eq(first_node, root);
int query_count = 0;
Tree_Sitter_Query_Cursor queries[2];
if (would_reparse_entire_file)
{
TSNode prev_sibling = {0};
TSNode next_sibling = {0};
u32 child_count = ts_node_child_count(root);
for (u32 i = 0; i < child_count; i++)
{
TSNode child = ts_node_child(root, i);
u32 start_byte = ts_node_start_byte(child);
u32 end_byte = ts_node_end_byte(child);
if (end_byte <= new_range.min)
{
prev_sibling = child;
}
else if (start_byte >= new_range.max)
{
next_sibling = child;
break;
}
}
if (ts_node_is_null(prev_sibling) && ts_node_is_null(next_sibling))
{
queries[query_count++] = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags],
root
);
}
else
{
if (!ts_node_is_null(prev_sibling))
{
queries[query_count++] = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags],
prev_sibling
);
}
if (!ts_node_is_null(next_sibling))
{
queries[query_count++] = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags],
next_sibling
);
}
}
}
else
{
TSNode node_at = first_node;
TSNode parent = ts_node_parent(first_node);
while (!ts_node_has_error(parent) && !ts_node_eq(parent, root))
{
node_at = parent;
parent = ts_node_parent(node_at);
}
queries[query_count++] = tree_sitter_query_init(
app,
state.buffer_id,
state.language->queries.ptr[Tree_Sitter_Language_Query_Tags],
node_at
);
}
Range_i64 edit_range;
edit_range.min = (i64)ts_node_start_byte(queries[0].first_node);
edit_range.max = (i64)ts_node_end_byte(queries[query_count-1].first_node);
tree_data->last_update_node_range = edit_range; // TODO(PS): TEMP - remove me once debugging is done
// Free Scope Delimiters that fall within old_range
{
ProfileScope(app, "Free Scope Delimiters");
Code_Index_Scope_Delim* delim = state.index->scope_delim_list.first;
Code_Index_Scope_Delim* 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)
{
delim_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) break;
delim = next;
}
state.last_delim = delim_before_range;
}
// Free Scope Notes that fall within old_range
{
ProfileScope(app, "Free Notes");
Code_Index_Note* note = state.index->note_list.first;
Code_Index_Note* prev = 0;
Code_Index_Note* note_before_range = 0;
while (note)
{
Code_Index_Note* next = note->next;
if (note->pos.min < edit_range.min && note->pos.max <= edit_range.min)
{
note_before_range = note;
}
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);
Code_Index_Note_List_New* list = code_index__list_from_string(note->text);
code_index_note_list_hash_remove(list, note);
free_string(&state.index->string_pool, note->text);
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;
}
if (note->pos.min >= edit_range.max) break;
note = next;
}
state.last_note = note_before_range;
if (state.index->note_list.count == 0) Assert(state.index->note_list.first == 0 && state.index->note_list.first == 0);
}
{
ProfileScope(app, "Perform Query");
for (int i = 0; i < query_count; i++)
{
Tree_Sitter_Query_Cursor query = queries[i];
TSQueryMatch query_match;
u32 capture_index;
while (state.ok && tree_sitter_query_continue(&query, &query_match, &capture_index))
{
tree_sitter_code_index_update_process_query_match(
&state, query, query_match, capture_index, scratch
);
}
tree_sitter_query_end(&query);
}
}
tree_sitter_code_index_update_complete(app, &state, scratch, true);
} }
buffer_modified_set_clear(); buffer_modified_set_clear();
} }
@ -1049,19 +658,6 @@ draw_tree_sitter_node_colors(Application_Links* app, Text_Layout_ID text_layout_
if (!lang) return; if (!lang) return;
TSQuery* query = lang->queries.ptr[Tree_Sitter_Language_Query_Highlights]; TSQuery* query = lang->queries.ptr[Tree_Sitter_Language_Query_Highlights];
Managed_ID color_id = managed_id_get(app, SCu8("colors"), SCu8("defcolor_str_constant"));
Code_Index_File* file = code_index_get_file(buffer_id);
if (file != 0)
{
Code_Index_Scope_Delim* delim = file->scope_delim_list.first;
while (delim != 0)
{
paint_text_color_fcolor(app, text_layout_id, delim->pos, fcolor_id(color_id));
if (delim->next == delim) break;
delim = delim->next;
}
}
Range_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); Range_i64 visible_range = text_layout_get_visible_range(app, text_layout_id);
Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer_id); Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer_id);
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);
@ -1191,9 +787,9 @@ tree_sitter_list_all_query_results(
Code_Index_File* file = code_index_get_file(buffer); Code_Index_File* file = code_index_get_file(buffer);
if (file != 0) if (file != 0)
{ {
Code_Index_Note *note = file->note_list.first; for (i32 i = 0; i < file->note_array.count; i += 1)
for (i32 i = 0; i < file->note_list.count; i += 1, note = note->next)
{ {
Code_Index_Note *note = file->note_array.ptrs[i];
if (note->note_kind == note_kind) if (note->note_kind == note_kind)
{ {
print_position( print_position(
@ -1319,30 +915,6 @@ 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="")

View File

@ -49,7 +49,6 @@ 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
@ -88,16 +87,14 @@ 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;
Code_Index_Note_List_New new_notes;
Code_Index_Nest_Stack* nest_stack_first = 0; Code_Index_Nest_Stack* nest_stack_first = 0;
Code_Index_Nest_Stack* nest_stack_last = 0; Code_Index_Nest_Stack* nest_stack_last = 0;
Code_Index_Scope_Delim* last_delim = 0;
Code_Index_Note* last_note = 0; Code_Index_Note* last_note = 0;
u32 last_note_match_id = max_u32; u32 last_note_match_id = max_u32;
@ -127,6 +124,4 @@ 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

View File

@ -21,16 +21,9 @@ String_Const_u8 TS_CPP_TAGS_QUERY_SCM = string_u8_litexpr(R"DONE(
(class_specifier name: (type_identifier) @name) @definition.class (class_specifier name: (type_identifier) @name) @definition.class
"{" @scope_begin (_ "{" @scope_begin "}" @scope_end )
"(" @scope_begin (_ "(" @scope_begin ")" @scope_end )
"[" @scope_begin (_ "[" @scope_begin "]" @scope_end )
"}" @scope_end
")" @scope_end
"]" @scope_end
; (_ "{" @scope_begin "}" @scope_end )
; (_ "(" @scope_begin ")" @scope_end )
; (_ "[" @scope_begin "]" @scope_end )
)DONE"); )DONE");