aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorBradley Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-09 13:51:53 -0400
committerGitHub <noreply@github.com>2025-09-09 13:51:53 -0400
commit450cab982b4b5149059ac3f1b6c7675b0fc6dc91 (patch)
treebebc5095a5f554d00554407fdc33751906f6f36f /src/server
parent6e1b9e3fcecabf258f8f718e113f0b37f21e00ee (diff)
parentd7d113f5b20c791523fdb7b32b2107dc88b34317 (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.odin16
-rw-r--r--src/server/memory_index.odin5
-rw-r--r--src/server/workspace_symbols.odin90
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)
}
}