Parenthesis matching tagger and programmatic text changes

SyntaxEditor for WPF Forum

Posted 8 years ago by Matthew LeRoy
Version: 11.1.0541
Avatar
I'm implementing a simple expression editor using the SyntaxEditor control, and I've implemented a parenthesis matching tagger using some sample code I found in another post (here), and for the most part it seems to be working fine; matching sets of parens are dynamically highlighted as I move the caret/selection around, type, etc.

The problem I'm having is when I make some programmatic changes to the expression text using ITextChange objects (created using Document.CreateTextChange). I'll try to explain it as best I can.

One case where the issue occurs is if I have an expression like this:
(4 + 1)/(1 / 1e-10)
If I select the part of the expression within the second set of parentheses ('1 / 1e-10'), and then replace that selected text with a shorter expression (something as simple as just '1'), I end up with an exception being thrown in my parenthesis-matching tagger.

It looks like what happens is that when I first select the text to replace, my tagger gets a ViewSelectionChanged event and updates its local field which tracks the current token next to the caret (in my case, the last closing paren ')'). Then, when I call textChange.Apply() to apply my text replacement change, the TagsChanged event gets fired, but the ViewSelectionChanged event does not get fired. What happens then is that in my OnTagsChanged override in the parenthesis-matching tagger, I attempt to position a TextSnapshotReader one offset before the selected token (which is still set to the last closing paren, since the ViewSelectionChanged event was never raised), using a line like this:
reader.Offset = selectedToken.StartOffset - 1;
The problem is that the selectedToken's offset values are still the old offset values from the original text (in this example, StartOffset = 18, EndOffset = 19), but the text snapshot I'm operating on already has the replacement text, so it only has a length of 11. So, I get an exception thrown in set_Offset() when I try to set the offset to 17.

Any ideas on how to work around this problem? Is there some step or check that I'm missing? I feel like I should be getting a ViewSelectionChanged event when I apply the text change, *before* TagsChanged, which would allow me to update the selected token so it would have the correct offsets.

Comments (1)

Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Matthew,

Selection changes occur in response to text changes, since the text change being applied affects the document text and that affects the caret location.

What you'd want to do is first see if your reader's snapshot version is the same as the version used to track your ranges. If it's not, then you should translate your ranges to the newer snapshot. Assuming you are tracking TagVersionRange<T> sort of objects, you can do this kind of code to translate:
TextSnapshotRange targetSnapshotRange = item.VersionRange.Translate(reader.Snapshot);
Then the targetSnapshotRange will contain the tag's range relative to the reader's snapshot, which includes all the edits made between the two versions.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.