@@ -11,10 +11,18 @@ local severity_levels = {
1111 Hint = 4 ,
1212}
1313
14+ --- @class DiagStatus
15+ --- @field value integer | nil
16+ --- @field cache_version integer
17+
1418--- A dictionary tree containing buffer-severity mappings.
1519--- @type table
1620local buffer_severity_dict = {}
1721
22+ --- The cache version number of the buffer-severity mappings.
23+ --- @type integer
24+ local BUFFER_SEVERITY_VERSION = 0
25+
1826--- @param path string
1927--- @return string
2028local function uniformize_path (path )
@@ -80,6 +88,31 @@ local function is_using_coc()
8088 return vim .g .coc_service_initialized == 1
8189end
8290
91+ --- @param node Node
92+ --- @return DiagStatus
93+ local function from_cache (node )
94+ local nodepath = uniformize_path (node .absolute_path )
95+ local max_severity = nil
96+ if not node .nodes then
97+ -- direct cache hit for files
98+ max_severity = buffer_severity_dict [nodepath ]
99+ else
100+ -- dirs should be searched in the list of cached buffer names by prefix
101+ for bufname , severity in pairs (buffer_severity_dict ) do
102+ local node_contains_buf = vim .startswith (bufname , nodepath .. " /" )
103+ if node_contains_buf then
104+ if severity == M .severity .max then
105+ max_severity = severity
106+ break
107+ else
108+ max_severity = math.min (max_severity or severity , severity )
109+ end
110+ end
111+ end
112+ end
113+ return { value = max_severity , cache_version = BUFFER_SEVERITY_VERSION }
114+ end
115+
83116function M .update ()
84117 if not M .enable then
85118 return
@@ -91,6 +124,7 @@ function M.update()
91124 else
92125 buffer_severity_dict = from_nvim_lsp ()
93126 end
127+ BUFFER_SEVERITY_VERSION = BUFFER_SEVERITY_VERSION + 1
94128 log .node (" diagnostics" , buffer_severity_dict , " update" )
95129 log .profile_end (profile )
96130 if view .is_buf_valid (view .get_bufnr ()) then
@@ -100,33 +134,34 @@ function M.update()
100134end
101135
102136--- @param node Node
103- function M .update_node_severity_level (node )
137+ --- @return DiagStatus | nil
138+ function M .get_diag_status (node )
104139 if not M .enable then
105- return
140+ return nil
106141 end
107142
108- local is_folder = node .nodes ~= nil
109- local nodepath = uniformize_path (node .absolute_path )
143+ -- dir but we shouldn't show on dirs at all
144+ if node .nodes ~= nil and not M .show_on_dirs then
145+ return nil
146+ end
110147
111- if is_folder then
112- local max_severity = nil
113- if M .show_on_dirs and (not node .open or M .show_on_open_dirs ) then
114- for bufname , severity in pairs (buffer_severity_dict ) do
115- local node_contains_buf = vim .startswith (bufname , nodepath .. " /" )
116- if node_contains_buf then
117- if severity == M .severity .max then
118- max_severity = severity
119- break
120- else
121- max_severity = math.min (max_severity or severity , severity )
122- end
123- end
124- end
125- end
126- node .diag_status = max_severity
127- else
128- node .diag_status = buffer_severity_dict [nodepath ]
148+ -- here, we do a lazy update of the diagnostic status carried by the node.
149+ -- This is by design, as diagnostics and nodes live in completely separate
150+ -- worlds, and this module is the link between the two
151+ if not node .diag_status or node .diag_status .cache_version < BUFFER_SEVERITY_VERSION then
152+ node .diag_status = from_cache (node )
153+ end
154+
155+ -- file
156+ if not node .nodes then
157+ return node .diag_status
158+ end
159+
160+ -- dir is closed or we should show on open_dirs
161+ if not node .open or M .show_on_open_dirs then
162+ return node .diag_status
129163 end
164+ return nil
130165end
131166
132167function M .setup (opts )
0 commit comments