38

我正在尝试开始使用 Visual Studio (2010) 扩展,但我很难找到合适的材料。我有 SDK,但包含的示例似乎是装饰器、窗口和图标之类的东西。

我正在尝试制作一个可以直接与文本编辑器一起使用的扩展(例如,将类中的所有方法名称按字母顺序排列,或者将所有常量名称设为大写),但我找不到此类功能的演示,甚至是教程。

有谁知道我在哪里可以找到这种东西?

4

2 回答 2

60

我有完全相同的问题,现在已经浏览了几个小时的网络,直到我能够理解并解释你需要如何开始使用这样的扩展。

在下面的示例中,我们将创建一个小而笨的扩展,当进行编辑时,它总是会在代码文件的开头添加“Hello”。这是非常基本的,但应该让你知道如何继续开发这个东西。

请注意:您必须自己完全解析代码文件 - Visual Studio 不会为您提供有关类、方法或其他内容的位置以及它们包含的内容的任何信息。这是在使用代码格式化工具时要采取的最大障碍,并且不会包含在此答案中。[*]

对于那些跳过此答案的人,请确保您首先下载并安装了 Visual Studio SDK,否则您将找不到第一步中提到的项目类型。

创建项目

  1. 首先创建一个类型为“Visual C# > 扩展性 > VSIX 项目”的新项目(仅当您选择 .NET Framework 4 作为目标框架时才可见)。请注意,您可能必须选择“编辑器分类器”项目类型而不是“VSIX 项目”类型才能使其正常工作,s。在下面发表评论。

  2. 创建项目后,将打开“source.extension.vsixmanifest”文件,您可以设置产品名称、作者、版本、描述、图标等。我认为这一步很容易解释,您现在可以关闭选项卡,稍后通过打开 vsixmanifest 文件来恢复它。

创建侦听器类以获取有关文本编辑器实例创建的通知

接下来,我们需要在 Visual Studio 中创建文本编辑器时进行监听,并将我们的代码格式化工具绑定到它。VS2010 中的文本编辑器是IWpfTextView.

  1. 向我们的项目添加一个新类并将其命名TextViewCreationListener。这个类必须实现Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener接口。您需要在项目中添加对Microsoft.VisualStudio.Text.UI.Wpf的引用。程序集 DLL 位于 Visual StudioIntegration\Common\Assemblies\v4.0下的 Visual Studio SDK 目录中。

  2. 您必须实现TextViewCreated接口的方法。此方法有一个参数指定已创建的文本编辑器的实例。我们将创建一个新的代码格式化类,稍后将此实例传递给该类。

  3. 我们需要TextViewCreationListener通过指定属性使类对 Visual Studio 可见[Export(typeof(IWpfTextViewCreationListener))]将System.ComponentModel.Composition的引用添加到您的项目中以获取该Export属性。

  4. 此外,我们需要指定代码格式化程序应该与哪些类型的文件绑定到文本编辑器。我们只喜欢格式化代码文件而不喜欢纯文本文件,所以我们将属性添加[ContentType("code")]到侦听器类中。为此,您必须在项目中添加对Microsoft.VisualStudio.CoreUtility的引用。

  5. 此外,我们只想更改可编辑代码,而不是更改其周围的颜色或装饰(如示例项目中所示),因此我们将属性添加[TextViewRole(PredefinedTextViewRoles.Editable)]到类中。您再次需要一个新的参考,这次是Microsoft.VisualStudio.Text.UI

  6. 将类标记为内部密封。至少这是我的建议。现在你的类应该看起来像这样:

    [ContentType("code")]
    [Export(typeof(IWpfTextViewCreationListener))]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal sealed class TextViewCreationListener : IWpfTextViewCreationListener
    {
        public void TextViewCreated(IWpfTextView textView)
        {
        }
    }
    

为代码格式化创建一个类

接下来,我们需要一个类来处理代码格式化逻辑、排序方法等。同样,在此示例中,只要进行了编辑,它就会简单地将“Hello”添加到文件的开头。

  1. Formatter为您的项目添加一个名为的新类。

  2. 添加一个接受一个IWpfTextView参数的构造函数。请记住,我们想在TextViewCreated侦听器类的方法中将创建的编辑器实例传递给这个格式化类(只需添加new Formatter(textView);到那里的方法中)。

  3. 将传递的实例保存在成员变量中。稍后格式化代码时它会变得很方便(例如,用于检索插入符号的位置)。还要绑定编辑器实例的属性的ChangedPostChanged事件:TextBuffer

    public Formatter(IWpfTextView view)
    {
        _view = view;
        _view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed);
        _view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged);
    }
    
  4. Changed每次进行编辑(例如键入字符、粘贴代码或程序更改)时都会调用该事件。因为它也会对编程更改做出反应,所以我使用 bool 来确定我们的扩展或用户/其他任何东西是否正在更改代码,并且FormatCode()只有在我们的扩展尚未编辑时才调用我的自定义方法。否则,您将递归调用此方法,这会使 Visual Studio 崩溃:

    private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
    {
        if (!_isChangingText)
        {
            _isChangingText = true;
            FormatCode(e);
        }
    }
    
  5. PostChanged我们必须再次将事件处理程序中的这个 bool 成员变量重置为false.

  6. 让我们将事件的事件参数传递Changed给我们的自定义FormatCode方法,因为它们包含上次编辑和现在之间发生的变化。这些编辑存储在e.Changes类型的数组中INormalizedTextChangeCollection(我的帖子末尾的链接以获取有关此类型的更多信息)。我们遍历所有这些编辑并HandleChange使用此编辑生成的新文本调用我们的自定义方法。

    private void FormatCode(TextContentChangedEventArgs e)
    {
        if (e.Changes != null)
        {
            for (int i = 0; i < e.Changes.Count; i++)
            {
                HandleChange(e.Changes[0].NewText);
            }
        }
    }
    
  7. 在该HandleChange方法中,我们实际上可以扫描关键字以以特定方式处理这些关键字(请记住,您必须自己解析任何代码!) - 但在这里我们只是在文件开头添加“Hello”以进行测试。例如,我们必须改变TextBuffer我们的编辑器实例。为此,我们需要创建一个ITextEdit对象,我们可以使用它来操作文本并在之后应用它的更改。代码非常不言自明:

    private void HandleChange(string newText)
    {
        ITextEdit edit = _view.TextBuffer.CreateEdit();
        edit.Insert(0, "Hello");
        edit.Apply();
    }
    

编译此加载项时,Visual Studio 的实验性配置单元启动时仅加载了我们的扩展。创建一个新的 C# 文件并开始输入以查看结果。

我希望这能给你一些关于如何继续这个话题的想法。我现在必须自己去探索。

I highly recommend the documentation of the text model of the editor on MSDN to get hints about how you could do this and that. http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel


Footnotes

[*] Note that Visual Studio 2015 or newer come with the Rosyln Compiler Platform, which indeed already analyzes C# and VB.NET files for you (and probably other pre-installed languages too) and exposes their hierarchical syntactical structure, but I'm not an expert in this topic yet to give an answer on how to use these new services. The basic progress of starting an editor extension stays the same as described in this answer anyway. Be aware that - if you use these services - you will become dependent on Visual Studio 2015+, and the extension will not work in earlier versions.

于 2012-03-24T22:28:23.700 回答
6

只需查看 MSDN 上的“编辑器扩展入门”站点http://msdn.microsoft.com/en-us/library/dd885122.aspx

托尔斯滕

于 2011-07-29T19:14:27.003 回答