You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: TECHNICAL.md
+20-4Lines changed: 20 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1088,7 +1088,7 @@ The `sortText` prefix ensures pages always appear before aliases in the list. Bo
1088
1088
1089
1089
**Front matter suppression:** `isLineInsideFrontMatter()` checks whether the cursor is between the first two `---` lines. If so, no completions are returned — front matter aliases are plain strings, not wikilinks.
1090
1090
1091
-
All four pure functions — `findInnermostOpenBracket()`, `findMatchingCloseBracket()`, `isLineInsideFrontMatter()`, and `isPositionInsideCode()` — live in `CompletionUtils.ts` with no VS Code dependency, and are fully unit-tested.
1091
+
All five pure functions — `findInnermostOpenBracket()`, `findMatchingCloseBracket()`, `isLineInsideFrontMatter()`, `isPositionInsideCode()`, and `hasNewCompleteWikilink()` — live in `CompletionUtils.ts` with no VS Code dependency, and are fully unit-tested.
1092
1092
1093
1093
**Code block detection:** `isPositionInsideCode(lines, lineIndex, charIndex)` scans lines 0 through `lineIndex` tracking fenced code block open/close state (supports both `` ` `` and `~` fences, respects fence length — a closing fence must use the same character and at least as many markers as the opener). If a fence is still open at `lineIndex`, the position is inside a code block. Separately checks inline code spans (`` ` ``) on the target line.
1094
1094
@@ -1097,7 +1097,7 @@ All four pure functions — `findInnermostOpenBracket()`, `findMatchingCloseBrac
1097
1097
The provider maintains a cached array of `CompletionItem[]` objects. The cache is rebuilt **eagerly** whenever `refresh()` is called — there is no dirty flag or lazy rebuild.
1098
1098
1099
1099
- **Eager rebuild:** `refresh()` calls `rebuildCache()` immediately, running three SQLite queries (`getAllPages`, `getAllAliases`, `getForwardReferencedPages`) and building lightweight plain data objects (not `CompletionItem` instances). This happens at index-update time (file save, create, delete, rename, periodic scan, rebuild), not at `[[` keystroke time.
1100
-
- **Not called on text-change debounce:** The 500ms `onDidChangeTextDocument` debounce handler does **not** call `completionProvider.refresh()`. This eliminates three SQLite queries on every typing pause. Forward references appear in autocomplete after the next file save.
1100
+
- **Selective text-change refresh:** The 500ms `onDidChangeTextDocument` debounce handler re-indexes the live buffer and calls `completionProvider.refresh()` **only when** `hasNewCompleteWikilink()` detects that the current document now contains at least one newly added complete wikilink compared to the page's last indexed links. This makes new forward references available without save while avoiding the refresh cost on ordinary typing edits.
1101
1101
- **Warm on activation:** `enterFullMode()` calls `completionProvider.refresh()` immediately after construction (post stale-scan), so the cache is warm before the user types the first `[[`.
1102
1102
- **Not called on editor switch:** The `onDidChangeActiveTextEditor` handler does **not** call `completionProvider.refresh()`. Completion data is global (all pages, aliases, forward refs) and is unaffected by which tab is focused. This avoids 3 SQLite queries on every tab switch.
1103
1103
- **Hot path:** `provideCompletionItems()` never touches the database. It builds `CompletionItem` instances from lightweight cached data objects with the per-call replacement range and returns them inside a `CompletionList`.
@@ -1128,11 +1128,11 @@ The listener only fires on deletions (where `rangeLength > 0` and `text` is empt
1128
1128
When the user types inside a wikilink, two things happen on every keystroke:
1129
1129
1130
1130
1. `WikilinkRenameTracker.onDocumentChanged` — records `pendingEdit` (the outermost wikilink position the cursor is inside). This edit state is cleared and rename detection runs when the cursor exits the wikilink.
1131
-
2. The 500 ms `onDidChangeTextDocument` debounce in `extension.ts` — re-indexes the live buffer into the in-memory DB so that newly typed forward references appear in autocomplete immediately.
1131
+
2. The 500 ms `onDidChangeTextDocument` debounce in `extension.ts` — re-indexes the live buffer into the in-memory DB and selectively refreshes autocomplete when a newly added complete wikilink is detected.
1132
1132
1133
1133
These two behaviours interact at the index: rename detection (`checkForRenames`) works by comparing the **current DB state** (the last-indexed link positions and names) against the live document. If the debounce fires and re-indexes the document before the cursor exits the wikilink, the DB is updated to reflect the edited name. When `checkForRenames` later runs after cursor exit, it compares the edited name in the DB against the same name in the live document — no difference is detected, and the rename dialog is never shown.
1134
1134
1135
-
**Guard:** The debounce callback in `extension.ts` checks `renameTracker.hasPendingEdit(doc.uri.toString())` before calling `indexFileContent`. If a pending edit is active for that document, the re-index is skipped for that tick. `WikilinkRenameTracker` exposes:
1135
+
**Guard:** The debounce callback in `extension.ts` checks `renameTracker.hasPendingEdit(doc.uri.toString())` before calling `indexFileContent` or refreshing completion. If a pending edit is active for that document, the re-index is skipped for that tick. `WikilinkRenameTracker` exposes:
1136
1136
1137
1137
```typescript
1138
1138
hasPendingEdit(docKey: string): boolean
@@ -1594,6 +1594,16 @@ If `resolveAlias(oldPageName)` returns the same page whose filename is `oldPageN
1594
1594
1595
1595
`updateLinksInWorkspace()` finds all `.md` and `.markdown` files, parses each for wikilinks, and creates a `WorkspaceEdit` that replaces every `[[oldPageName]]` with `[[newPageName]]`. After applying the edit, it saves modified files.
1596
1596
1597
+
**Notification progress:**
1598
+
1599
+
Accepted in-editor rename operations are wrapped in `withWikilinkRenameProgress()` (`WikilinkRenameProgressService.ts`), which shows a non-cancellable VS Code notification while the slow path runs. The tracker reports three coarse phases:
1600
+
1601
+
1. `Preparing rename operations`
1602
+
2. `Updating links across workspace`
1603
+
3. `Refreshing index`
1604
+
1605
+
The progress notification is only shown after the user confirms the rename or merge. Declined or dismissed prompts remain a no-op aside from the existing decline re-index path.
1606
+
1597
1607
### Post-rename index refresh
1598
1608
1599
1609
After a rename operation completes, `refreshIndexAfterRename()` ensures the index is consistent before releasing control:
@@ -1618,6 +1628,12 @@ After the renamed file is indexed at its new path, AS Notes checks for filename
1618
1628
1619
1629
This selection logic is isolated in `WikilinkExplorerMergeService.ts` so the ambiguity rules are unit-tested independently of the large `extension.ts` event handler.
1620
1630
1631
+
The user-confirmed refactor work that follows explorer renames is now extracted into `WikilinkExplorerRenameRefactorService.ts`. That helper applies the same notification UX as in-editor renames:
1632
+
1633
+
1. Accepted merge operations show `AS Notes: Applying rename updates` while the merge, delete, and target re-index complete.
1634
+
2. Accepted workspace-wide reference updates show `AS Notes: Updating wikilink references` while link replacement and stale-scan refresh complete.
1635
+
3. Declined explorer prompts do not show progress notifications.
1636
+
1621
1637
### Re-entrancy guard
1622
1638
1623
1639
The `isProcessing` flag prevents document-change events fired by the rename operation itself (file renames, workspace edits) from being treated as new user edits. It is set to `true` before any rename work begins and cleared in the `finally` block.
0 commit comments