Skip to content

Commit f9dd15b

Browse files
committed
full-analysis: Clean up methods from previous analysis modules
Delete methods defined in previous analysis modules after re-analysis. While this doesn't free memory (`Method` objects remain in `Core.methodtable`), it removes them from reflection APIs like `methods()`, preventing stale methods from appearing in signature help or completions.
1 parent 1906815 commit f9dd15b

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2121
- `.JETLSConfig.toml` is now only recognized at the workspace root.
2222
Previously, config files in subdirectories were also loaded, which was
2323
inconsistent with [the documentation](https://aviatesk.github.io/JETLS.jl/release/configuration/#config/file-based-config).
24+
- Clean up methods from previous analysis modules after re-analysis to prevent
25+
stale overload methods from appearing in signature help or completions.
2426

2527
### Internal
2628

src/analysis/full-analysis.jl

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,10 @@ function resolve_analysis_request(server::Server, request::AnalysisRequest)
284284
@goto next_request
285285
end
286286

287-
initial_analysis = request.prev_analysis_result === nothing
287+
prev_result = request.prev_analysis_result
288288
cancellable_token = request.cancellable_token
289289
if cancellable_token !== nothing
290-
begin_full_analysis_progress(server, cancellable_token, request.entry, initial_analysis)
290+
begin_full_analysis_progress(server, cancellable_token, request.entry, prev_result === nothing)
291291
end
292292

293293
local failed::Bool = false
@@ -303,6 +303,9 @@ function resolve_analysis_request(server::Server, request::AnalysisRequest)
303303
if cancellable_token !== nothing
304304
end_full_analysis_progress(server, cancellable_token)
305305
end
306+
if prev_result !== nothing
307+
cleanup_prev_methods(prev_result)
308+
end
306309
failed && @goto next_request
307310
end
308311
tm = round(time() - s, digits=2)
@@ -316,7 +319,7 @@ function resolve_analysis_request(server::Server, request::AnalysisRequest)
316319
# This ensures that clients using pull diagnostics (textDocument/diagnostic) will
317320
# re-request diagnostics now that module context is available, allowing
318321
# lowering/macro-expansion-error diagnostics to be properly reported.
319-
if initial_analysis && supports(server, :workspace, :diagnostics, :refreshSupport)
322+
if prev_result === nothing && supports(server, :workspace, :diagnostics, :refreshSupport)
320323
request_diagnostic_refresh!(server)
321324
end
322325

@@ -368,6 +371,33 @@ function has_any_parse_errors(server::Server, request::AnalysisRequest)
368371
end
369372
end
370373

374+
# Delete methods defined in previous analysis modules.
375+
# This doesn't free memory (Method objects remain in Core.methodtable), but removes them
376+
# from reflection APIs like `methods()`, preventing stale methods from appearing in
377+
# signature help or completions.
378+
function cleanup_prev_methods(prev_result::AnalysisResult)
379+
prev_modules = IdSet{Module}()
380+
for analyzed_file_info in values(prev_result.analyzed_file_infos)
381+
for module_range_info in analyzed_file_info.module_range_infos
382+
push!(prev_modules, last(module_range_info))
383+
end
384+
end
385+
methods_to_delete = Method[]
386+
Base.visit(Core.methodtable) do m::Method
387+
if parentmodule(m) in prev_modules
388+
push!(methods_to_delete, m)
389+
end
390+
end
391+
for m in methods_to_delete
392+
try
393+
Base.delete_method(m)
394+
catch e
395+
JETLS_DEV_MODE && @warn "Failed to delete method $m"
396+
JETLS_DEV_MODE && Base.showerror(stderr, e, catch_backtrace())
397+
end
398+
end
399+
end
400+
371401
function update_analysis_cache!(manager::AnalysisManager, analysis_result::AnalysisResult)
372402
analyzed_uris = analyzed_file_uris(analysis_result)
373403
store!(manager.cache) do cache

0 commit comments

Comments
 (0)