diff options
| author | Bozhidar Batsov <bozhidar@toptal.com> | 2026-04-26 07:14:41 +0100 |
|---|---|---|
| committer | Bozhidar Batsov <bozhidar@toptal.com> | 2026-04-26 07:14:41 +0100 |
| commit | 69adda8f55aaeedcee77948318c3e389665019db (patch) | |
| tree | 90b33a5edeea12c5ca76f381e40234a2293493d8 /projectile.el | |
| parent | 67981d6d93b957edf3359d94f6216837427834bc (diff) | |
Memoize per-function nil results in the root cache (#1836)
Previously a root function returning nil stored nil in the cache,
which is indistinguishable from a missing entry, so on the next call
the function was re-run. When a project's root is found by the third
function in projectile-project-root-functions, the first two
re-walked the tree on every call - and projectile-project-root is hot
in mode-line / company / spaceline updates.
Store the symbol 'none for unsuccessful entries and treat it as a
cache hit on lookup. The overall-failure marker already used 'none
in a separate slot, so this just extends the same convention to the
per-function entries.
Diffstat (limited to 'projectile.el')
| -rw-r--r-- | projectile.el | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/projectile.el b/projectile.el index 0530925..d88819f 100644 --- a/projectile.el +++ b/projectile.el @@ -1482,17 +1482,22 @@ If DIR is not supplied it's set to the current directory by default." ;; `projectile-root-local' reads a buffer-local variable rather ;; than inspecting DIR, so its result must not be cached - two ;; buffers in the same directory can legitimately disagree. + ;; For other functions, both successes and per-function failures + ;; (stored as the 'none sentinel) are memoized, so functions + ;; earlier in the list that returned nil aren't re-walked on + ;; every call. (seq-some (lambda (func) (if (eq func 'projectile-root-local) (funcall func dir) (let* ((cache-key (cons func dir)) (cache-value (gethash cache-key projectile-project-root-cache))) - (if (and cache-value (file-exists-p cache-value)) - cache-value - (let ((value (funcall func (file-truename dir)))) - (puthash cache-key value projectile-project-root-cache) - value))))) + (cond + ((eq cache-value 'none) nil) + ((and cache-value (file-exists-p cache-value)) cache-value) + (t (let ((value (funcall func (file-truename dir)))) + (puthash cache-key (or value 'none) projectile-project-root-cache) + value)))))) projectile-project-root-functions) ;; if we get here, we have failed to find a root by all ;; conventional means, and we assume the failure isn't transient |
