onevcat/VVDocumenter-Xcode

Undo and Redo bug

onevcat opened this issue · 2 comments

There is a bug when you do some "undo" and "redo" operations while leaving the inline placeholder of document comment unfilled. It might be something wrong related to string range calculation. See Discussion section below for more.

How to reproduce

Be sure to use a test file to do it.

  1. Type in /// above any code you want to do a documentation. Comment lines with at least one inline placeholder will be generated as usual.
  2. Do not fill that placeholder, move your cursor below to a new line of code you want to document with. Type in /// to generate a new doc comment.
  3. Press Cmd+Z to do undo operations, until everything goes back to the initial state.
  4. Then press Shift+Cmd+Z to redo twice. You will see the bug. You are not getting the right redo result as expected.

Discussion

A method of DVTSourceTextStorage (which is a subclass of NSTextStorage used by the Xcode editor) named replaceCharactersInRange:withString:withUndoManager: is used for replacing the typed in /// to the doc comments. It works well in Xcode 4 unless you try to do some redo operations with the docs. When doing redo, the line range's location can not be accessed correctly, due to a <# #> tag is being generating while creating the docs. After added, Xcode editor will recognize these tags as inline place holder and convert the <# #> (including the content between two #) to a DVTTextFoldInlineTokenAttachment object and set it to the attributes to the DVTSourceTextStorage (which is a subclass NSAtrributedString).

The converted token only takes 1 length in the DVTSourceTextStorage, so there is a mismatch of redo's range location and real needed range location. When you do a redo, the inserting place is wrong.

I am not familiar with NSTextView and NSUndoManager. I have tried other strategies like paste board and replace the attributed string directly. But all were without luck.

And as described in the Readme file, the undo manager is not working for Xcode 5 DP now. I guess the implement of replaceCharactersInRange:withString:withUndoManager: is changed. I will keep an eye on the newer release of Xcode 5 and see what I can do.

Solve

Solved in tag 0.2. See comment below.

Hi all, I fixed this in tag 0.2.

I am using a simulation of keyboard events now, instead of depending on Xcode's private framework. The undo&redo operations should work perfectly now in both Xcode4 and Xcode5 DP. If you are using version before tag0.2, I strongly recommend you update to the latest version (Download it and build again).

Cheers.

Please edit the README.md