@@ -11,10 +11,18 @@ local severity_levels = {
11
11
Hint = 4 ,
12
12
}
13
13
14
+ --- @class DiagStatus
15
+ --- @field value integer | nil
16
+ --- @field cache_version integer
17
+
14
18
--- A dictionary tree containing buffer-severity mappings.
15
19
--- @type table
16
20
local buffer_severity_dict = {}
17
21
22
+ --- The cache version number of the buffer-severity mappings.
23
+ --- @type integer
24
+ local BUFFER_SEVERITY_VERSION = 0
25
+
18
26
--- @param path string
19
27
--- @return string
20
28
local function uniformize_path (path )
@@ -80,6 +88,31 @@ local function is_using_coc()
80
88
return vim .g .coc_service_initialized == 1
81
89
end
82
90
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
+
83
116
function M .update ()
84
117
if not M .enable then
85
118
return
@@ -91,6 +124,7 @@ function M.update()
91
124
else
92
125
buffer_severity_dict = from_nvim_lsp ()
93
126
end
127
+ BUFFER_SEVERITY_VERSION = BUFFER_SEVERITY_VERSION + 1
94
128
log .node (" diagnostics" , buffer_severity_dict , " update" )
95
129
log .profile_end (profile )
96
130
if view .is_buf_valid (view .get_bufnr ()) then
@@ -100,33 +134,34 @@ function M.update()
100
134
end
101
135
102
136
--- @param node Node
103
- function M .update_node_severity_level (node )
137
+ --- @return DiagStatus | nil
138
+ function M .get_diag_status (node )
104
139
if not M .enable then
105
- return
140
+ return nil
106
141
end
107
142
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
110
147
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
129
163
end
164
+ return nil
130
165
end
131
166
132
167
function M .setup (opts )
0 commit comments