views:

173

answers:

3

Resharper claims to eat it's own dogfood, specifically, they claim that many of the features of Resharper are written ontop of R# (OpenAPI). I'm writing a simple plugin to fix up comments of the current document of a selection. When this plugin is run, it throws an exception as follows:

Document can be modified inside a command scope only

I've researched the error and can't find anything to help with this, so I'm hoping that possibly, you've written a plugin to accomplish this. If not, I hope the snippet is enough to help others get their own plugins underway.

using System;
using System.IO;
using System.Windows.Forms;
using JetBrains.ActionManagement;
using JetBrains.DocumentModel;
using JetBrains.IDE;
using JetBrains.TextControl;
using JetBrains.Util;

namespace TinkerToys.Actions
{
    [ActionHandler("TinkerToys.RewriteComment")]
    public class RewriteCommentAction : IActionHandler
    {
        #region Implementation of IActionHandler

        /// <summary>
        ///             Updates action visual presentation. If presentation.Enabled is set to false, Execute
        ///             will not be called.
        /// </summary>
        /// <param name="context">DataContext</param>
        /// <param name="presentation">presentation to update</param>
        /// <param name="nextUpdate">delegate to call</param>
        public bool Update(IDataContext context, ActionPresentation presentation, DelegateUpdate nextUpdate)
        {
            ITextControl textControl = context.GetData(DataConstants.TEXT_CONTROL);
            return textControl != null;
        }

        /// <summary>
        ///             Executes action. Called after Update, that set ActionPresentation.Enabled to true.
        /// </summary>
        /// <param name="context">DataContext</param>
        /// <param name="nextExecute">delegate to call</param>
        public void Execute(IDataContext context, DelegateExecute nextExecute)
        {
            ITextControl textControl = context.GetData(DataConstants.TEXT_CONTROL);
            if (textControl != null) {
                TextRange textSelectRange;

                ISelectionModel textSelectionModel = textControl.SelectionModel;
                if ((textSelectionModel != null) && textSelectionModel.HasSelection()) {
                    textSelectRange = textSelectionModel.Range;
                } else {
                    textSelectRange = new TextRange(0, textControl.Document.GetTextLength());
                }

                IDocument textDocument = textControl.Document;
                String textSelection = textDocument.GetText(textSelectRange);
                if (textSelection != null) {
                    StringReader sReader = new StringReader(textSelection);
                    StringWriter sWriter = new StringWriter();
                    Converter.Convert(sReader, sWriter);
                    textSelection = sWriter.ToString();

                    textDocument.ReplaceText(textSelectRange, textSelection);
                }
            }
        }

        #endregion
    }
}

So what is this command scope it wants so badly? I had some additional logging in this prior to posting it so I'm absolutely certain that both the range and text are valid. In addition, the error seems to indicate that I'm missing some scope that I've been, as yet, unable to find.

A: 

If I understood, you want to take the selection, send it to a function and replace the selection by the function return value...

What about using the Visual Studio Macro to do the job? Is it something you will consider?

Hapkido
A: 

Yeah, I guess I could use a macro to accomplish the same task. In retrospect, I wrote a simple vs add-in to do the same thing. The reason why I was/am looking at R# is because it has language specific element parsing that it can provide in addition to the raw text. But for this problem I think a macro or standard add-in would also work fine.

Ajaxx
A: 

I'd like to see how to archive it in R#
Any working code ?

Maciej