fix(editor): hide an emphasis whose text has been deleted instead of drawing it somewhere else - #2354
Merged
Merged
Conversation
…drawing it somewhere else
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
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.
Fixes #2341.
The problem
EmphasisManager.updateLayerBackgrounds()runs on every draw and skips any emphasis whose shape it cannot build. Skipping leaves that emphasis'sCAShapeLayerholding the last path it was given, so once the text under it is edited away the highlight goes on painting at its old position, over whatever now occupies that place.Search highlights had a worse version of it.
roundedPathForRangeanswers a range whose length no longer fits withrectForEndOffset(), the caret rect at the end of the document, so a stale.standardemphasis did not keep its old position: it jumped to the end of the editor and drew a highlight over nothing.This was split out of #2338, which fixed the crash on the same code path and deliberately left the behaviour alone, and the risk it names is why: an attribute-only edit invalidates lines, so clearing too eagerly could make a find highlight blink off and on during ordinary syntax highlighting traffic.
The fix
Two parts, and the second is what makes the first safe.
makeShapePathreturns nil when the emphasis range no longer fits the document, so a range that outran the text stops resolving to the caret rect at the end. An emphasis marks specific text; once that text is gone there is no shape to draw.Hiding rather than clearing the path is what answers the flicker risk. A line that is invalidated and re-typeset inside the same layout pass has its rects back before the draw, so nothing changes for it. A line invalidated outside the layout window has no rects and is not on screen either, so hiding it is not observable. When the range lays out again the layer is unhidden with its shape intact, rather than having to be rebuilt.
Verification
swift test --package-path LocalPackages/CodeEditTextView: 167 tests in 16 suites pass, including 2 new ones. Against the unfixed codeanEmphasisWhoseTextIsGoneStopsBeingDrawnfails: the layer is still visible after its text is deleted.anEmphasisWhoseTextIsStillThereKeepsBeingDrawn, fails any fix that hides too much.xcodebuild -scheme TablePro build: passes.No UI automation: the assertion is about which layers are hidden inside the editor's own layer tree, which XCUITest cannot see.