Commit b3d022b
authored
Add incremental invalidation engine (#641)
Replaces the old `remove_definitions_for_document` +
`invalidate_ancestor_chains` approach with a targeted invalidation
engine. When a file is updated or deleted, the engine traces through the
`name_dependents` reverse index to invalidate only the affected
declarations, names, and references — instead of requiring a full graph
rebuild.
## How it works
`consume_document_changes()` (renamed from `update()`) and
`delete_document()` run a three-step pipeline:
1. **`invalidate`** — read-only scan that seeds a worklist from old/new
definitions and references, building a `pending_detachments` side table
for definitions that need to be detached from their declarations
2. **`remove_document_data`** — cleans up phase 1 data (definitions,
references, names, strings) from maps
3. **`extend`** — merges new content and queues work items for the
resolver
The resolver still does `clear_declarations` + full rebuild. Wiring it
to drain `pending_work` incrementally is a follow-up.
### Invalidation worklist
The worklist processes three item types:
- **`Declaration`** — two modes:
- *Remove*: no definitions remain or owner was already removed
(orphaned). Cascades to members, singleton class, and descendants.
Orphaned definitions are re-queued for re-resolution (e.g. `class
Foo::Bar` survives even if `Foo` changes from a module to an alias).
- *Update*: declaration survives but its ancestor chain may have changed
(mixin added/removed, superclass changed). Clears ancestors/descendants
and re-queues ancestor resolution.
- **`Name`** — structural dependency broken (name's nesting or parent
scope removed). Unresolves the name and cascades to all dependents.
- **`References`** — ancestor context changed, but the name itself is
still valid. Needed for mixin-related invalidation:
```ruby
class Foo < Bar
CONST
end
# Another file adds:
class Foo
include Baz # Foo's ancestors changed, so references like CONST need re-evaluation
end
```
### Cascade differentiation
The `name_dependents` reverse index distinguishes `ChildName` (compact
syntax `Foo::Bar`) from `NestedName` (nested syntax `module Foo; class
Bar; end; end`):
- **Structural cascade** (name removed): both `ChildName` and
`NestedName` → `Name`
- **Ancestor-triggered cascade** (mixin changed): `ChildName` → `Name`
(resolves through parent), `NestedName` → `References` (only references
need rechecking)1 parent 00c630c commit b3d022b
6 files changed
Lines changed: 1603 additions & 135 deletions
File tree
- rust
- rubydex-sys/src
- rubydex/src
- model
- test_utils
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
643 | 643 | | |
644 | 644 | | |
645 | 645 | | |
646 | | - | |
| 646 | + | |
647 | 647 | | |
648 | 648 | | |
649 | 649 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
98 | | - | |
| 98 | + | |
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
126 | | - | |
| 126 | + | |
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
482 | 482 | | |
483 | 483 | | |
484 | 484 | | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
485 | 489 | | |
486 | 490 | | |
487 | 491 | | |
| |||
0 commit comments