Cache the JSON tree per tab instead of drawing it on tab switch - #253
Open
leoshone wants to merge 3 commits into
Open
Cache the JSON tree per tab instead of drawing it on tab switch#253leoshone wants to merge 3 commits into
leoshone wants to merge 3 commits into
Conversation
"Refresh JSON Tree" rebuilds every node, so the tree always came back fully collapsed - even when the user only wanted to re-read a document they were already looking at. Capture which nodes are expanded and which one is selected before the tree is thrown away, then re-apply that state onto the freshly built tree, matching nodes by path. Paths that no longer exist (the document changed in the meantime) are silently dropped, and nodes that are new stay collapsed. The state is keyed by node path, which is the list of keys from the tree root down to a node. The pure path arithmetic lives in the new TreeExpansion.h/.cpp so it can be unit tested without a window. DrawJsonTree() gained a bPreserveExpansion parameter that defaults to false, so every other caller (panel opening, formatting, compressing, sorting) keeps behaving exactly as before; only the refresh button opts in.
When "Follow current tab" is off (the default) the plugin never drew the
tree on its own, but it also never cleared it: the tree kept showing the
document of some earlier tab, with no indication that it belonged there.
With this change the tree is only ever drawn when the user asks for it
("Refresh JSON Tree"). Switching tabs stores the tree of the tab being
left and puts it back verbatim when the tab is activated again, so no
re-parsing happens and the expansion state and selection survive.
The "Follow current tab" option is kept and behaves exactly as before
when enabled: the document of the activated tab is parsed immediately.
Only its "off" path changes, from "do nothing" to "remember per tab".
Notes:
- Snapshots live in memory only and are dropped when the buffer is
closed, together with the association to the current buffer.
- "Auto format on open" now formats the document without drawing the
tree, so opening a file still cannot trigger a parse.
- Formatting now redraws the tree while preserving its expansion state,
which keeps it consistent with Refresh.
- Built on top of the TreeExpansion helpers introduced for Refresh.
Adds an option, off by default, that draws the tree of a json document as soon as the file is opened. It complements the per-tab snapshot caching: the document is parsed exactly once, and switching back to the tab afterwards replays the stored snapshot instead of parsing again. The check lives in RestoreTabState(), the single place reached when the tree of a tab has never been drawn, so opening a file, switching back to a tab and showing the panel are all covered by one code path. Drawing on open is initiated by the plugin, not by the user, so parse errors are reported as a node inside the tree rather than through a modal dialog: DrawJsonTree() takes a bSilent flag for that. The tree is drawn for documents whose language is JSON, the same criterion the existing "follow current tab" uses.
leoshone
force-pushed
the
fix/per-tab-tree-snapshot
branch
from
September 5, 2026 04:15
b5f684c to
ed4c3d8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With Follow current tab disabled (the default), the plugin neither follows
the active tab nor clears the tree. The tree keeps showing whichever document
happened to be parsed last, with nothing indicating that it belongs to a
different tab. Reproduce:
a.json, press Refresh JSON Tree.b.json— the tree still showsa.json.Enabling the option instead parses on every tab switch, which is not always
wanted either (large files, and it re-parses even when the user only wanted a
look at the tree of one tab).
Change
The tree is now drawn only when the user asks for it (Refresh JSON Tree).
Switching tabs stores the tree of the tab being left and puts it back verbatim
when that tab comes back, so:
The "Follow current tab" option is kept and behaves exactly as before when it
is enabled — the document of the activated tab is parsed immediately. Only its
offpath changes, from "do nothing" to "remember per tab". Users who rely onthe follow behaviour are unaffected, and no visible setting is removed.
Details:
together with the association to the current buffer (Notepad++ does not
guarantee whether
NPPN_FILECLOSEDorNPPN_BUFFERACTIVATEDarrives first).(
FormatJsonDocument()isFormatJson()minus the redraw), so opening a filecan no longer trigger a parse.
keeps it consistent with Refresh (see Keep the tree expansion state when refreshing the JSON tree #252).
TreeStatemodel (nodes + expansion + selection) next to theTreeExpansionhelpers.TreeExpansionis the "same document, tree rebuilt"case;
TreeStateis the "whole tree carried across tabs" case.Optional: draw the tree when a json file is opened
"Never parse on its own" is the right default, but it also means a user who
wants the tree right away has to press Refresh on every file. A new option,
Draw tree when a json file is opened (
DRAW_ON_OPEN, off by default),draws the tree once when a json document is opened.
It is deliberately built on top of the snapshot mechanism rather than next to
it: the check lives in
RestoreTabState(), the single place reached when thetree of a tab has never been drawn. So the document is parsed exactly once, and
from then on the tab behaves like any other — switching back replays the stored
snapshot and does not parse again. Opening a file, switching back to a tab and
showing the panel are all covered by that one code path.
Two details worth reviewing:
the existing Follow current tab uses.
failure must not stop the user with a dialog.
DrawJsonTree()takes abSilentflag for that and reports the failure as a node inside the treeinstead. Manual Refresh is unchanged and still reports errors as before.
Note on the diff
This branch is built on top of #252 (
TreeExpansion.h/.cpp), so its diffcurrently includes that PR as well. The change specific to this PR is
+602/-28 over 17 files; the total against
masteris +1073/-31 over 20files. If #252 is merged first, this PR collapses to its own commits.
Verification
TreeStateTestcases for snapshot capture/compare, 1
ProfileTestround-trip for the newsetting).
SendMessage(this host runs non-interactively, so no keyboard injection):after rewriting the document behind the tab's back, switching away and back
still shows the old snapshot, and only an explicit Refresh picks up the
new text. That distinguishes "replay a snapshot" from "re-parse quietly".
pressing Refresh; a second file gets its own tree; switching back shows the
right document; after the document is changed behind the plugin's back the
stale snapshot is kept (no re-parse); a new non-json file is not parsed;
Refresh still re-reads; with the option off nothing is drawn and manual
Refresh still works; and a malformed json file reports the error inside
the tree with no modal dialog, leaving Notepad++ responsive.