diff options
| author | Bradley Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-09-09 13:51:53 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-09 13:51:53 -0400 |
| commit | 450cab982b4b5149059ac3f1b6c7675b0fc6dc91 (patch) | |
| tree | bebc5095a5f554d00554407fdc33751906f6f36f /src/server | |
| parent | 6e1b9e3fcecabf258f8f718e113f0b37f21e00ee (diff) | |
| parent | d7d113f5b20c791523fdb7b32b2107dc88b34317 (diff) | |
Merge pull request #987 from BradLewis/feat/cache-packages-workspace-symbols
Cache workspace pkgs so we don't walk the file system each workspace symbol request
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/indexer.odin | 16 | ||||
| -rw-r--r-- | src/server/memory_index.odin | 5 | ||||
| -rw-r--r-- | src/server/workspace_symbols.odin | 90 |
3 files changed, 61 insertions, 50 deletions
diff --git a/src/server/indexer.odin b/src/server/indexer.odin index 1afa1e8..3ffc3c3 100644 --- a/src/server/indexer.odin +++ b/src/server/indexer.odin @@ -68,24 +68,14 @@ fuzzy_search :: proc( pkgs: []string, current_file: string, resolve_fields := false, + limit := 0, ) -> ( []FuzzyResult, bool, ) { - results, ok := memory_index_fuzzy_search(&indexer.index, name, pkgs, current_file, resolve_fields) - result := make([dynamic]FuzzyResult, context.temp_allocator) - + results, ok := memory_index_fuzzy_search(&indexer.index, name, pkgs, current_file, resolve_fields, limit = limit) if !ok { return {}, false } - - for r in results { - append(&result, r) - } - - slice.sort_by(result[:], proc(i, j: FuzzyResult) -> bool { - return j.score < i.score - }) - - return result[:], true + return results[:], true } diff --git a/src/server/memory_index.odin b/src/server/memory_index.odin index fb00dc1..80c137f 100644 --- a/src/server/memory_index.odin +++ b/src/server/memory_index.odin @@ -59,6 +59,7 @@ memory_index_fuzzy_search :: proc( pkgs: []string, current_file: string, resolve_fields := false, + limit := 0, ) -> ( []FuzzyResult, bool, @@ -147,7 +148,9 @@ memory_index_fuzzy_search :: proc( return j.score < i.score }) - if name == "" { + if limit > 0 { + return symbols[:min(limit, len(symbols))], true + } else if name == "" { return symbols[:], true } else { return symbols[:min(top, len(symbols))], true diff --git a/src/server/workspace_symbols.odin b/src/server/workspace_symbols.odin index a45fba5..11e7a8a 100644 --- a/src/server/workspace_symbols.odin +++ b/src/server/workspace_symbols.odin @@ -1,16 +1,24 @@ package server - import "core:fmt" import "core:log" import "core:os" import "core:path/filepath" import "core:strings" +import "core:time" import "src:common" dir_blacklist :: []string{"node_modules", ".git"} +WorkspaceCache :: struct { + time: time.Time, + pkgs: [dynamic]string, +} + +@(thread_local, private = "file") +cache: WorkspaceCache + @(private) walk_dir :: proc(info: os.File_Info, in_err: os.Errno, user_data: rawptr) -> (err: os.Error, skip_dir: bool) { pkgs := cast(^[dynamic]string)user_data @@ -31,50 +39,60 @@ walk_dir :: proc(info: os.File_Info, in_err: os.Errno, user_data: rawptr) -> (er } get_workspace_symbols :: proc(query: string) -> (workspace_symbols: []WorkspaceSymbol, ok: bool) { - workspace := common.config.workspace_folders[0] - uri := common.parse_uri(workspace.uri, context.temp_allocator) or_return - pkgs := make([dynamic]string, 0, context.temp_allocator) - symbols := make([dynamic]WorkspaceSymbol, 0, 100, context.temp_allocator) - - filepath.walk(uri.path, walk_dir, &pkgs) - - _pkg: for pkg in pkgs { - matches, err := filepath.glob(fmt.tprintf("%v/*.odin", pkg), context.temp_allocator) - - if len(matches) == 0 { - continue + if time.since(cache.time) > 20 * time.Second { + for pkg in cache.pkgs { + delete(pkg) } + clear(&cache.pkgs) + for workspace in common.config.workspace_folders { + uri := common.parse_uri(workspace.uri, context.temp_allocator) or_return + pkgs := make([dynamic]string, 0, context.temp_allocator) + + filepath.walk(uri.path, walk_dir, &pkgs) - for exclude_path in common.config.profile.exclude_path { - exclude_forward, _ := filepath.to_slash(exclude_path, context.temp_allocator) + _pkg: for pkg in pkgs { + matches, err := filepath.glob(fmt.tprintf("%v/*.odin", pkg), context.temp_allocator) - if exclude_forward[len(exclude_forward) - 2:] == "**" { - lower_pkg := strings.to_lower(pkg) - lower_exclude := strings.to_lower(exclude_forward[:len(exclude_forward) - 3]) - if strings.contains(lower_pkg, lower_exclude) { - continue _pkg + if len(matches) == 0 { + continue } - } else { - lower_pkg := strings.to_lower(pkg) - lower_exclude := strings.to_lower(exclude_forward) - if lower_pkg == lower_exclude { - continue _pkg + + for exclude_path in common.config.profile.exclude_path { + exclude_forward, _ := filepath.to_slash(exclude_path, context.temp_allocator) + + if exclude_forward[len(exclude_forward) - 2:] == "**" { + lower_pkg := strings.to_lower(pkg) + lower_exclude := strings.to_lower(exclude_forward[:len(exclude_forward) - 3]) + if strings.contains(lower_pkg, lower_exclude) { + continue _pkg + } + } else { + lower_pkg := strings.to_lower(pkg) + lower_exclude := strings.to_lower(exclude_forward) + if lower_pkg == lower_exclude { + continue _pkg + } + } } + + try_build_package(pkg) + append(&cache.pkgs, strings.clone(pkg, context.allocator)) } } + cache.time = time.now() + } - try_build_package(pkg) - - if results, ok := fuzzy_search(query, {pkg}, "", resolve_fields = true); ok { - for result in results { - symbol := WorkspaceSymbol { - name = result.symbol.name, - location = {range = result.symbol.range, uri = result.symbol.uri}, - kind = symbol_kind_to_type(result.symbol.type), - } - - append(&symbols, symbol) + limit :: 100 + symbols := make([dynamic]WorkspaceSymbol, 0, limit, context.temp_allocator) + if results, ok := fuzzy_search(query, cache.pkgs[:], "", resolve_fields = false, limit = limit); ok { + for result in results { + symbol := WorkspaceSymbol { + name = result.symbol.name, + location = {range = result.symbol.range, uri = result.symbol.uri}, + kind = symbol_kind_to_type(result.symbol.type), } + + append(&symbols, symbol) } } |