Domanda

I've got a custom plugin which uses a quickfix and the IDocument.InsertText() method. it inserts a comment at the end of the line of code with the highlighter that was selected but this messes up the position of the rest of the highlighters from the one selected to the end. Is there some way to refresh my daemons Execute function which is in charge of placing the highlights?
Any other ideas on ways to get around this?

Thank you, Yuval

Before fix: Before

After fix: After

È stato utile?

Soluzione

This is due to the abstract syntax tree getting out of sync with the text of the document. Normally, you'd modify the source file by manipulating the syntax tree, which in turn updates the text of the document. When modifying the text directly, you need to make sure the syntax tree is notified of the change, so it knows to update.

You can do this by wrapping the update in a transaction:

using(solution.CreateTransactionCookie(DefaultAction.Commit, "Update text"))
{
  document.InsertText(...);
}

You get to specify the default action that will happen when the transaction cookie's Dispose method is called - commit or rollback, and you can call methods directly on the transaction cookie, too. The text passed to the cookie is plain text and is only used for diagnostics purposes, so you can see the transaction that is currently active.

UPDATE:

After looking at the code, the issue here is that you can't modify the text of the document while there's a PSI transaction active. The PSI transaction indicates that you're going to modify the abstract syntax tree of the document, so you can't then modify the text of the document as well - you could easily get into a situation with two conflicting changes and no way to reconcile them.

The PSI transaction is being created by the BulbActionBase base class of the context action, before calling the ExecutePsiTransaction method. You can't modify the text directly in this method.

You have a couple of choices here. You could create a comment node using CSharpElementFactory.GetInstance(...).CreateComment(text) and then add it to the PSI tree using the methods in ModificationUtil, or you can leave ExecutePsiTransaction as an empty method (return null) and implement ExecuteAfterPsiTransaction and call Document.InsertText there (this is what the XAML InsertTextQuickFix class does). Because this method is called while in a transaction, but not while in a PSI transaction, it should update the text, and cause the PSI to be put back in sync.

Incidentally, ReSharper throws an exception when trying to modify the document while the PSI transaction is active, with an appropriate message. If you run Visual Studio with the command line devenv.exe /ReSharper.Internal, this exception should be shown as a tooltip like window in the status bar. Even better, if you're building a plugin, you can install a "checked" build, which includes more checks and reports exceptions by default.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top