Skip to content

Commit 577d885

Browse files
authored
Merge pull request #648 from aviatesk/avi/per-uri-cache
sync: Group per-file cache invalidations into a helper
2 parents cec6278 + aaf9a6c commit 577d885

8 files changed

Lines changed: 50 additions & 42 deletions

File tree

src/analysis/occurrence-analysis.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,10 @@ end
361361
function get_binding_occurrences!(
362362
state::ServerState, uri::URI, fi::FileInfo, st0::JS.SyntaxTree; kwargs...
363363
)
364+
cache_uri = canonical_cache_uri(state, uri)
364365
range_key = JS.byte_range(st0)
365366
return store!(state.binding_occurrences_cache) do cache::BindingOccurrencesCacheData
366-
file_cache = get(cache, uri, nothing)
367+
file_cache = get(cache, cache_uri, nothing)
367368
if file_cache !== nothing && haskey(file_cache, range_key)
368369
return cache, file_cache[range_key]
369370
end
@@ -383,7 +384,7 @@ function get_binding_occurrences!(
383384
else
384385
file_cache = BindingOccurrencesCacheEntry(file_cache, range_key => cache_result)
385386
end
386-
return BindingOccurrencesCacheData(cache, uri => file_cache), cache_result
387+
return BindingOccurrencesCacheData(cache, cache_uri => file_cache), cache_result
387388
end
388389
end
389390

@@ -603,9 +604,10 @@ function collect_inert_global_occurrences!(
603604
end
604605

605606
function invalidate_binding_occurrences_cache!(state::ServerState, uri::URI)
607+
cache_uri = canonical_cache_uri(state, uri)
606608
store!(state.binding_occurrences_cache) do cache::BindingOccurrencesCacheData
607-
if haskey(cache, uri)
608-
Base.delete(cache, uri), nothing
609+
if haskey(cache, cache_uri)
610+
Base.delete(cache, cache_uri), nothing
609611
else
610612
cache, nothing
611613
end

src/diagnostic.jl

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,11 +1507,7 @@ function get_lowering_diagnostics!(
15071507
cancel_flag::CancelFlag;
15081508
lookup_func = nothing
15091509
)
1510-
# For notebooks, every cell URI in a notebook resolves to the same
1511-
# concat-source `FileInfo`, so cache under the notebook URI to share
1512-
# entries across cells and to match the invalidation site
1513-
# (`cache_notebook_file_info!` invalidates the notebook URI).
1514-
cache_uri = @something get_notebook_uri_for_cell(server.state, uri) uri
1510+
cache_uri = canonical_cache_uri(server.state, uri)
15151511
return store!(server.state.lowering_diagnostics_cache) do cache::LoweringDiagnosticsCacheData
15161512
if haskey(cache, cache_uri)
15171513
return cache, cache[cache_uri]
@@ -1526,9 +1522,10 @@ function get_lowering_diagnostics!(
15261522
end
15271523

15281524
function invalidate_lowering_diagnostics_cache!(state::ServerState, uri::URI)
1525+
cache_uri = canonical_cache_uri(state, uri)
15291526
store!(state.lowering_diagnostics_cache) do cache::LoweringDiagnosticsCacheData
1530-
if haskey(cache, uri)
1531-
Base.delete(cache, uri), nothing
1527+
if haskey(cache, cache_uri)
1528+
Base.delete(cache, cache_uri), nothing
15321529
else
15331530
cache, nothing
15341531
end

src/did-change-watched-files.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,7 @@ function handle_jl_file_change!(server::Server, change::FileEvent)
149149
@assert change.type == FileChangeType.Deleted
150150
invalidate_unsynced_file_cache!(state, uri)
151151
end
152-
invalidate_document_symbol_cache!(state, uri)
153-
invalidate_binding_occurrences_cache!(state, uri)
154-
invalidate_lowering_diagnostics_cache!(state, uri)
152+
invalidate_per_file_caches!(state, uri)
155153
end
156154
request_diagnostic_refresh!(server)
157155
end

src/document-symbol.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,25 @@ function strip_name_from_detail(sym::DocumentSymbol)
6565
end
6666

6767
function get_document_symbols!(state::ServerState, uri::URI, fi::FileInfo)
68+
cache_uri = canonical_cache_uri(state, uri)
6869
return store!(state.document_symbol_cache) do cache::DocumentSymbolCacheData
69-
if haskey(cache, uri)
70-
symbols = cache[uri]
70+
if haskey(cache, cache_uri)
71+
symbols = cache[cache_uri]
7172
return cache, symbols
7273
end
7374
st0 = build_syntax_tree(fi)
7475
pos = Position(; line=0, character=0)
7576
(; mod) = get_context_info(state, uri, pos)
7677
symbols = extract_document_symbols(st0, fi, mod)
77-
return DocumentSymbolCacheData(cache, uri => symbols), symbols
78+
return DocumentSymbolCacheData(cache, cache_uri => symbols), symbols
7879
end
7980
end
8081

8182
function invalidate_document_symbol_cache!(state::ServerState, uri::URI)
83+
cache_uri = canonical_cache_uri(state, uri)
8284
store!(state.document_symbol_cache) do cache::DocumentSymbolCacheData
83-
if haskey(cache, uri)
84-
Base.delete(cache, uri), nothing
85+
if haskey(cache, cache_uri)
86+
Base.delete(cache, cache_uri), nothing
8587
else
8688
cache, nothing
8789
end

src/document-synchronization.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ function ParseStream!(s::Union{AbstractString,Vector{UInt8}})
44
return stream
55
end
66

7+
# Drop every per-file cache entry for `uri`. Called whenever a file's content
8+
# changes (didChange/didOpen, notebook cell edits, watched-file events) or its
9+
# module context changes (full-analysis updates). `clear_*_cache!` (e.g. for
10+
# diagnostic config changes) is separate because not all caches share that
11+
# invalidation trigger.
12+
function invalidate_per_file_caches!(state::ServerState, uri::URI)
13+
invalidate_document_symbol_cache!(state, uri)
14+
invalidate_binding_occurrences_cache!(state, uri)
15+
invalidate_lowering_diagnostics_cache!(state, uri)
16+
end
17+
718
"""
819
cache_file_info!(server::Server, uri::URI, version::Int, text::Union{AbstractString,Vector{UInt8}})
920
cache_file_info!(server::Server, uri::URI, version::Int, parsed_stream::JS.ParseStream)
@@ -30,9 +41,7 @@ function cache_file_info!(
3041
Base.PersistentDict(cache, uri => fi), nothing
3142
end
3243

33-
invalidate_document_symbol_cache!(state, uri)
34-
invalidate_binding_occurrences_cache!(state, uri)
35-
invalidate_lowering_diagnostics_cache!(state, uri)
44+
invalidate_per_file_caches!(state, uri)
3645

3746
if !state.suppress_notifications && any_deleted
3847
notify_diagnostics!(server; ensure_cleared=uri)

src/notebook.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ get_notebook_info(state::ServerState, uri::URI, default=nothing) =
77
get_notebook_uri_for_cell(state::ServerState, cell_uri::URI, default=nothing) =
88
get(load(state.cell_to_notebook), cell_uri, default)
99

10+
# Per-file caches (`document_symbol_cache`, `binding_occurrences_cache`,
11+
# `lowering_diagnostics_cache`) key on a single canonical URI per logical file.
12+
# For notebooks, every cell URI shares the same concat-source `FileInfo`, so the
13+
# canonical key is the notebook URI. Cache accessors and their invalidations
14+
# both run input through this helper so reads, writes, and invalidations always
15+
# meet on the same key.
16+
canonical_cache_uri(state::ServerState, uri::URI) =
17+
get_notebook_uri_for_cell(state, uri, uri)
18+
1019
function concatenate_cells(cells::Vector{NotebookCellInfo})
1120
source = ""
1221
cell_ranges = CellRange[]
@@ -28,9 +37,7 @@ function cache_notebook_file_info!(server::Server, notebook_uri::URI, notebook_i
2837
store!(state.file_cache) do cache
2938
Base.PersistentDict(cache, notebook_uri => fi), fi
3039
end
31-
invalidate_document_symbol_cache!(state, notebook_uri)
32-
invalidate_binding_occurrences_cache!(state, notebook_uri)
33-
invalidate_lowering_diagnostics_cache!(state, notebook_uri)
40+
invalidate_per_file_caches!(state, notebook_uri)
3441
return fi
3542
end
3643

src/types.jl

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -683,22 +683,15 @@ mutable struct ServerState
683683
# Cache for files not synced via document-synchronization (unsynced files).
684684
# Populated on-demand by `get_unsynced_file_info!`, invalidated by `workspace/didChangeWatchedFiles`.
685685
const unsynced_file_cache::UnsyncedFileCache
686-
# Document symbol cache for both synced and unsynced files.
687-
# Uses LWContainer for concurrent writes from:
688-
# - `get_document_symbols!` (on cache miss)
689-
# - `textDocument/didChange` (invalidates synced files)
690-
# - `workspace/didChangeWatchedFiles` (invalidates unsynced files)
686+
# Per-file caches keyed on the canonical (notebook-aware) URI of a logical file.
687+
# All three are dropped together via `invalidate_per_file_caches!` on content change
688+
# (didChange/didOpen, notebook cell edits, watched-file events).
689+
# `binding_occurrences_cache` and `lowering_diagnostics_cache` are additionally
690+
# invalidated by `update_analysis_cache!` when full-analysis changes module context,
691+
# since both embed `binfo.mod`. `lowering_diagnostics_cache` is also cleared wholesale
692+
# on diagnostic-affecting config changes via `clear_lowering_diagnostics_cache!`.
691693
const document_symbol_cache::DocumentSymbolCache
692-
# Binding occurrences cache for global binding analysis (references, rename).
693-
# Same invalidation pattern as document_symbol_cache.
694-
# TODO: This cache uses analysis context (module context from full-analysis).
695-
# It should also be invalidated when full-analysis updates module context,
696-
# but that is not yet implemented.
697694
const binding_occurrences_cache::BindingOccurrencesCache
698-
# Per-file cache of the diagnostics produced by `lowering_diagnostics!` over a
699-
# file's top-level statements. Lets cross-file `workspace/diagnostic`
700-
# invalidations (see `compute_workspace_diagnostic_result_id`) skip re-running
701-
# `jl_lower_for_scope_resolution` for files whose own content is unchanged.
702695
const lowering_diagnostics_cache::LoweringDiagnosticsCache
703696
const analysis_manager::AnalysisManager
704697
const extra_diagnostics::ExtraDiagnostics

src/utils/server.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ Returns a named tuple containing:
297297
to recognize, which are caused by JET implementation details
298298
"""
299299
function get_context_info(state::ServerState, uri::URI, pos::Position; lookup_func=nothing)
300-
lookup_uri = @something get_notebook_uri_for_cell(state, uri) uri
300+
lookup_uri = canonical_cache_uri(state, uri)
301301
if lookup_func !== nothing
302302
analysis_info = get_analysis_info(lookup_func, state.analysis_manager, lookup_uri)
303303
else
@@ -328,7 +328,7 @@ function get_context_module(analysis_result::AnalysisResult, uri::URI, pos::Posi
328328
return curmod
329329
end
330330
function get_context_module(state::ServerState, uri::URI, pos::Position; lookup_func=nothing)
331-
lookup_uri = @something get_notebook_uri_for_cell(state, uri) uri
331+
lookup_uri = canonical_cache_uri(state, uri)
332332
if lookup_func !== nothing
333333
analysis_info = get_analysis_info(lookup_func, state.analysis_manager, lookup_uri)
334334
else
@@ -346,7 +346,7 @@ get_post_processor(::OutOfScope) = LSPostProcessor(JET.PostProcessor())
346346
get_post_processor(analysis_result::AnalysisResult) = LSPostProcessor(JET.PostProcessor(analysis_result.actual2virtual))
347347

348348
function has_analyzed_context(state::ServerState, uri::URI; lookup_func=nothing)
349-
lookup_uri = @something get_notebook_uri_for_cell(state, uri) uri
349+
lookup_uri = canonical_cache_uri(state, uri)
350350
if lookup_func !== nothing
351351
analysis_info = get_analysis_info(lookup_func, state.analysis_manager, lookup_uri)
352352
else

0 commit comments

Comments
 (0)