Compare commits
9 Commits
ee082e42d1
...
8ad2b5bbff
Author | SHA1 | Date |
---|---|---|
|
8ad2b5bbff | |
|
a92e364e37 | |
|
6d77862b78 | |
|
30ac43ce66 | |
|
12322796c2 | |
|
6d7f1281b2 | |
|
69dc4f8e04 | |
|
76863fc03a | |
|
1dfc106e8c |
|
@ -257,6 +257,7 @@ 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;
|
||||||
|
|
|
@ -6,50 +6,145 @@
|
||||||
|
|
||||||
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_(Code_Index_Nest_Ptr_Array *array, i64 pos){
|
code_index_get_nest_from_list(Code_Index_Nest_List *list, i64 pos)
|
||||||
|
{
|
||||||
Code_Index_Nest *result = 0;
|
Code_Index_Nest *result = 0;
|
||||||
i32 count = array->count;
|
i32 count = list->count;
|
||||||
Code_Index_Nest **nest_ptrs = array->ptrs;
|
Code_Index_Nest *nest_at = list->first;
|
||||||
for (i32 i = 0; i < count; i += 1){
|
for (i32 i = 0; i < count; i += 1){
|
||||||
Code_Index_Nest *nest = nest_ptrs[i];
|
if (nest_at->open.max <= pos && pos <= nest_at->close.min){
|
||||||
if (nest->open.max <= pos && pos <= nest->close.min){
|
Code_Index_Nest *sub_nest = code_index_get_nest_from_list(&nest_at->nest_list, pos);
|
||||||
Code_Index_Nest *sub_nest = code_index_get_nest_(&nest->nest_array, pos);
|
if (sub_nest != 0)
|
||||||
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*
|
function Code_Index_Note_List_New*
|
||||||
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);
|
||||||
Code_Index_Note_List *result = &global_code_index.name_hash[hash % ArrayCount(global_code_index.name_hash)];
|
u64 index = 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 *list = code_index__list_from_string(string);
|
Code_Index_Note_List_New *list = code_index__list_from_string(string);
|
||||||
Code_Index_Note *result = 0;
|
Code_Index_Note *result = 0;
|
||||||
for (Code_Index_Note *node = list->first;
|
for (Code_Index_Note *node = list->sentinel_first.next_in_hash;
|
||||||
node != 0;
|
node != &list->sentinel_last;
|
||||||
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;
|
||||||
|
@ -64,10 +159,16 @@ 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*
|
||||||
|
@ -97,36 +198,6 @@ 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);
|
||||||
|
@ -139,13 +210,16 @@ 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 *list = code_index__list_from_string(node->text);
|
Code_Index_Note_List_New *list = code_index__list_from_string(node->text);
|
||||||
zdll_push_back_NP_(list->first, list->last, node, next_in_hash, prev_in_hash);
|
code_index_note_list_hash_insert(list, list->sentinel_last.prev_in_hash, node);
|
||||||
list->count += 1;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
|
@ -153,9 +227,8 @@ 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 *list = code_index__list_from_string(node->text);
|
Code_Index_Note_List_New *list = code_index__list_from_string(node->text);
|
||||||
zdll_remove_NP_(list->first, list->last, node, next_in_hash, prev_in_hash);
|
code_index_note_list_hash_remove(list, node);
|
||||||
list->count -= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,21 +269,30 @@ code_index_erase_file(Buffer_ID buffer){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Code_Index_File*
|
function Code_Index_File_Storage*
|
||||||
code_index_get_file(Buffer_ID buffer){
|
code_index_get_file_storage(Buffer_ID buffer){
|
||||||
Code_Index_File *result = 0;
|
Code_Index_File_Storage *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);
|
||||||
Code_Index_File_Storage *storage = (Code_Index_File_Storage*)IntAsPtr(val);
|
result = (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;
|
||||||
|
@ -221,27 +303,95 @@ index_shift(i64 *ptr, Range_i64 old_range, u64 new_size){
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
code_index_shift(Code_Index_Nest_Ptr_Array *array,
|
code_index_shift_list(Code_Index_Nest_List *list, Range_i64 old_range, u64 new_size)
|
||||||
Range_i64 old_range, u64 new_size){
|
{
|
||||||
i32 count = array->count;
|
i32 count = list->count;
|
||||||
Code_Index_Nest **nest_ptr = array->ptrs;
|
Code_Index_Nest *nest = list->first;
|
||||||
for (i32 i = 0; i < count; i += 1, nest_ptr += 1){
|
for (i32 i = 0; i < count; i += 1, nest = nest->next)
|
||||||
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(&nest->nest_array, old_range, new_size);
|
code_index_shift_list(&nest->nest_list, old_range, new_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(&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
|
||||||
|
@ -577,8 +727,6 @@ 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);
|
||||||
|
@ -657,8 +805,6 @@ 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);
|
||||||
|
@ -739,8 +885,6 @@ 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);
|
||||||
|
@ -803,11 +947,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,34 @@
|
||||||
#if !defined(FCODER_CODE_INDEX_H)
|
#if !defined(FCODER_CODE_INDEX_H)
|
||||||
#define FCODER_CODE_INDEX_H
|
#define FCODER_CODE_INDEX_H
|
||||||
|
|
||||||
struct Code_Index_Nest_List{
|
typedef i32 Code_Index_Scope_Delim_Kind;
|
||||||
struct Code_Index_Nest *first;
|
enum {
|
||||||
struct Code_Index_Nest *last;
|
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;
|
i32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Code_Index_Nest_Ptr_Array{
|
struct Code_Index_Nest_List{
|
||||||
struct Code_Index_Nest **ptrs;
|
struct Code_Index_Nest *first;
|
||||||
|
struct Code_Index_Nest *last;
|
||||||
i32 count;
|
i32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +49,10 @@ 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;
|
||||||
|
@ -38,7 +61,6 @@ 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;
|
||||||
|
@ -67,17 +89,20 @@ struct Code_Index_Note_List{
|
||||||
i32 count;
|
i32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Code_Index_Note_Ptr_Array{
|
struct Code_Index_Note_List_New {
|
||||||
Code_Index_Note **ptrs;
|
Code_Index_Note sentinel_first;
|
||||||
|
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{
|
||||||
|
@ -96,7 +121,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 name_hash[10000];
|
Code_Index_Note_List_New name_hash[10000];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
|
@ -25,8 +25,8 @@ CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the
|
||||||
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){
|
||||||
for (i32 i = 0; i < file->note_array.count; i += 1){
|
Code_Index_Note* note = file->note_list.first;
|
||||||
Code_Index_Note *note = file->note_array.ptrs[i];
|
for (i32 i = 0; i < file->note_list.count; i += 1, note = note->next){
|
||||||
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;
|
||||||
|
@ -70,19 +70,24 @@ CUSTOM_DOC("Jump to the first definition in the code index matching an identifie
|
||||||
{
|
{
|
||||||
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);
|
Code_Index_File *file = code_index_get_file(buffer);
|
||||||
if (file != 0){
|
if (file != 0)
|
||||||
for (i32 i = 0; i < file->note_array.count; i += 1){
|
{
|
||||||
Code_Index_Note *note = file->note_array.ptrs[i];
|
Code_Index_Note *note = file->note_list.first;
|
||||||
if (string_match(note->text, query)){
|
for (i32 i = 0; i < file->note_list.count; i += 1, note = note->next)
|
||||||
|
{
|
||||||
|
if (string_match(note->text, query))
|
||||||
|
{
|
||||||
point_stack_push_view_cursor(app, view);
|
point_stack_push_view_cursor(app, view);
|
||||||
jump_to_location(app, view, buffer, note->pos.first);
|
jump_to_location(app, view, buffer, note->pos.first);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
@ -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, "default edit range");
|
ProfileScope(app, "custom 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,6 +101,7 @@ 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
|
||||||
|
@ -142,9 +143,12 @@ 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) 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 +391,20 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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* list = code_index__list_from_string(lexeme);
|
Code_Index_Note_List_New* list = code_index__list_from_string(lexeme);
|
||||||
u64 i = 0;
|
u64 i = 0;
|
||||||
for (Code_Index_Note *it = list->first;
|
for (Code_Index_Note *it = list->sentinel_first.next_in_hash;
|
||||||
it != 0;
|
it != &list->sentinel_last;
|
||||||
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;
|
||||||
|
|
|
@ -273,44 +273,6 @@ 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,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#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
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
@ -73,7 +75,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
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* 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
|
|
@ -206,6 +206,14 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -356,12 +364,70 @@ 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)
|
||||||
{
|
{
|
||||||
Code_Index_Note *result = push_array(arena, Code_Index_Note, 1);
|
if (!index->note_free)
|
||||||
sll_queue_push(index->note_list.first, index->note_list.last, result);
|
{
|
||||||
index->note_list.count += 1;
|
int count = 32;
|
||||||
|
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;
|
||||||
|
@ -369,10 +435,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,
|
||||||
Arena* scratch
|
Arena* scratch
|
||||||
){
|
){
|
||||||
Tree_Sitter_Code_Index_Update_State state = {};
|
Tree_Sitter_Code_Index_Update_State state = {};
|
||||||
|
@ -380,23 +474,48 @@ 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;
|
||||||
|
|
||||||
|
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_arena = make_arena_system(KB(16));
|
||||||
state.index = push_array_zero(&state.index_arena, Code_Index_File, 1);
|
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
|
||||||
|
@ -407,14 +526,100 @@ 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(state->query.query, type_capture.index, &length);
|
const char* tmp = ts_query_capture_name_for_id(query.query, type_capture.index, &length);
|
||||||
String_Const_u8 capture_name = SCu8((char*)tmp, length);
|
String_Const_u8 capture_name = SCu8((char*)tmp, length);
|
||||||
|
|
||||||
if (string_match(capture_name, SCu8("scope_begin")))
|
if (string_match(capture_name, SCu8("scope_begin")) || string_match(capture_name, SCu8("scope_end")))
|
||||||
{
|
{
|
||||||
Code_Index_Nest* nest = push_array_zero(&state->index_arena, Code_Index_Nest, 1);
|
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, state->last_delim, delim);
|
||||||
|
state->last_delim = delim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (string_match(capture_name, SCu8("name")))
|
||||||
|
{
|
||||||
|
Range_i64 range = Ii64_size(type_range.start, type_range.end - type_range.start);
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
tree_sitter_code_index_update_complete(
|
||||||
|
Application_Links* app,
|
||||||
|
Tree_Sitter_Code_Index_Update_State* state,
|
||||||
|
Arena* scratch,
|
||||||
|
bool update_was_incremental
|
||||||
|
){
|
||||||
|
ProfileScope(app, "Complete Code Index Update");
|
||||||
|
if (state->ok)
|
||||||
|
{
|
||||||
|
Code_Index_Nest* free_nests = state->index->nest_list.first;
|
||||||
|
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 = (
|
||||||
|
delim_at->kind == CodeIndexScopeDelim_ScopeOpen ||
|
||||||
|
delim_at->kind == CodeIndexScopeDelim_ParenOpen ||
|
||||||
|
delim_at->kind == CodeIndexScopeDelim_BracketOpen
|
||||||
|
);
|
||||||
|
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->kind = CodeIndexNest_Scope;
|
||||||
nest->open = type_range;
|
nest->delim = delim_at->kind;
|
||||||
|
nest->open = delim_at->pos;
|
||||||
nest->close = Ii64(max_i64);
|
nest->close = Ii64(max_i64);
|
||||||
nest->file = state->index;
|
nest->file = state->index;
|
||||||
if (state->nest_stack_last != 0)
|
if (state->nest_stack_last != 0)
|
||||||
|
@ -422,88 +627,70 @@ tree_sitter_code_index_update_process_query_match(
|
||||||
nest->parent = state->nest_stack_last->nest;
|
nest->parent = state->nest_stack_last->nest;
|
||||||
code_index_push_nest(&nest->parent->nest_list, 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);
|
Code_Index_Nest_Stack* stack = push_array_zero(scratch, Code_Index_Nest_Stack, 1);
|
||||||
stack->nest = nest;
|
stack->nest = nest;
|
||||||
stack->prev = state->nest_stack_last;
|
stack->prev = state->nest_stack_last;
|
||||||
stack->match_id = query_match.id;
|
|
||||||
if (state->nest_stack_last != 0) state->nest_stack_last->next = stack;
|
if (state->nest_stack_last != 0) state->nest_stack_last->next = stack;
|
||||||
else state->nest_stack_first = stack;
|
else state->nest_stack_first = stack;
|
||||||
state->nest_stack_last = stack;
|
state->nest_stack_last = stack;
|
||||||
}
|
}
|
||||||
else if (string_match(capture_name, SCu8("scope_end")))
|
else
|
||||||
|
{
|
||||||
|
if (state->nest_stack_last != 0 && delims_are_open_close_pair(state->nest_stack_last->nest->delim, delim_at->kind))
|
||||||
{
|
{
|
||||||
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;
|
Code_Index_Nest* nest = state->nest_stack_last->nest;
|
||||||
nest->close = type_range;
|
nest->close = delim_at->pos;
|
||||||
nest->is_closed = true;
|
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;
|
state->nest_stack_last = state->nest_stack_last->prev;
|
||||||
if (state->nest_stack_last != 0) state->nest_stack_last->next = 0;
|
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")))
|
|
||||||
{
|
delim_at = delim_at->next;
|
||||||
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);;
|
ProfileScope(app, "Update Global Name Table");
|
||||||
state->last_note_match_id = query_match.id;
|
Code_Index_Note* note = state->new_notes.sentinel_first.next_in_hash;
|
||||||
}
|
Code_Index_Note* next = 0;
|
||||||
else if (string_match(capture_name, SCu8("definition.type")))
|
for (int i = 0; i < state->new_notes.count; i++)
|
||||||
{
|
{
|
||||||
state->last_note = code_index_new_note(state->index, &state->index_arena, CodeIndexNote_Type, type_range, state->nest_stack_last);
|
next = note->next_in_hash;
|
||||||
state->last_note_match_id = query_match.id;
|
note->next = 0; note->next_in_hash = 0; note->prev_in_hash = 0;
|
||||||
}
|
|
||||||
else if (string_match(capture_name, SCu8("name")))
|
String_Const_u8 source = string_substring(
|
||||||
{
|
state->buffer_contents,
|
||||||
if (state->last_note != 0 && state->last_note_match_id == query_match.id)
|
note->pos
|
||||||
{
|
);
|
||||||
state->last_note->pos = Ii64_size(type_range.start, type_range.end - type_range.start);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
if (!update_was_incremental)
|
||||||
tree_sitter_code_index_update_complete(
|
|
||||||
Application_Links* app,
|
|
||||||
Tree_Sitter_Code_Index_Update_State* state
|
|
||||||
){
|
|
||||||
tree_sitter_query_end(&state->query);
|
|
||||||
if (state->ok)
|
|
||||||
{
|
{
|
||||||
while (state->nest_stack_last != 0)
|
|
||||||
{
|
|
||||||
Code_Index_Nest* nest = state->nest_stack_last->nest;
|
|
||||||
if (nest->parent != 0) code_index_push_nest(&nest->parent->nest_list, nest);
|
|
||||||
else code_index_push_nest(&state->index->nest_list, nest);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish the Index
|
|
||||||
state->index->nest_array = code_index_nest_ptr_array_from_list(&state->index_arena, &state->index->nest_list);
|
|
||||||
state->index->note_array = code_index_note_ptr_array_from_list(&state->index_arena, &state->index->note_list);
|
|
||||||
|
|
||||||
|
|
||||||
code_index_lock();
|
code_index_lock();
|
||||||
code_index_set_file(state->buffer_id, state->index_arena, state->index);
|
code_index_set_file(state->buffer_id, state->index_arena, state->index);
|
||||||
code_index_unlock();
|
code_index_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
buffer_clear_layout_cache(app, state->buffer_id);
|
buffer_clear_layout_cache(app, state->buffer_id);
|
||||||
}
|
}
|
||||||
|
@ -513,36 +700,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -551,22 +708,31 @@ 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(&state.query, &query_match, &capture_index))
|
while (state.ok && tree_sitter_query_continue(&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_code_index_update_complete(app, &state);
|
tree_sitter_query_end(&query);
|
||||||
|
tree_sitter_code_index_update_complete(app, &state, scratch, false);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,7 +741,37 @@ 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;
|
||||||
tree_sitter_code_index_update_full_file_async(actx, 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,
|
||||||
|
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
|
||||||
|
@ -586,13 +782,208 @@ 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;
|
||||||
|
|
||||||
tree_sitter_code_index_update_full_file(app, buffer_id);
|
Range_i64 old_range = tree_data->last_update_old_range;
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,6 +1049,19 @@ 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);
|
||||||
|
@ -787,9 +1191,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)
|
||||||
{
|
{
|
||||||
for (i32 i = 0; i < file->note_array.count; i += 1)
|
Code_Index_Note *note = file->note_list.first;
|
||||||
|
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(
|
||||||
|
@ -915,6 +1319,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,14 +88,16 @@ 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;
|
||||||
|
|
||||||
|
@ -124,4 +127,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
|
||||||
|
|
|
@ -21,9 +21,16 @@ 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_end )
|
"{" @scope_begin
|
||||||
(_ "(" @scope_begin ")" @scope_end )
|
"(" @scope_begin
|
||||||
(_ "[" @scope_begin "]" @scope_end )
|
"[" @scope_begin
|
||||||
|
"}" @scope_end
|
||||||
|
")" @scope_end
|
||||||
|
"]" @scope_end
|
||||||
|
|
||||||
|
; (_ "{" @scope_begin "}" @scope_end )
|
||||||
|
; (_ "(" @scope_begin ")" @scope_end )
|
||||||
|
; (_ "[" @scope_begin "]" @scope_end )
|
||||||
|
|
||||||
)DONE");
|
)DONE");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue