Visual Studio文本编辑器扩展

时间:2011-07-19 17:04:14

标签: c# visual-studio visual-studio-2010 visual-studio-extensions

我正在尝试开始使用Visual Studio(2010)扩展程序,并且我很难找到合适的材料。我有SDK,但包含的样本似乎是装饰,窗口和图标。

我正在尝试创建一个直接与文本编辑器一起工作的扩展(以字母方式对我的所有方法名称进行字母顺序排列,或者将所有常量名称设置为大写),但我找不到这个的演示功能类型,甚至是教程。

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

2 个答案:

答案 0 :(得分:57)

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

在我的下面的例子中,我们将创建一个小而笨的扩展,它将始终添加" Hello"在编辑完成后到代码文件的开头。它非常基础,但应该让你知道如何继续开发这个东西。

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

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

创建项目

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

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

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

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

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

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

    3. 我们需要通过指定属性TextViewCreationListener使[Export(typeof(IWpfTextViewCreationListener))]类对Visual Studio可见。将 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)
          {
          }
      }
      
    7. 创建代码格式化类

      接下来,我们需要一个处理代码格式化逻辑,排序方法等的类。同样,在这个例子中,它只需添加" Hello"无论何时进行编辑,都要到文件的开头。

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

      2. 添加一个带有IWpfTextView个参数的构造函数。请记住,我们希望将创建的编辑器实例传递给侦听器类的TextViewCreated方法中的此格式化类(只需将new Formatter(textView);添加到该方法中)。

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

        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中(s。我帖子末尾的链接,以获取有关此类型的更多信息)。我们遍历所有这些编辑,并使用此编辑生成的新文本调用我们的自定义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方法中,我们实际上可以扫描关键字以便以特定方式处理这些关键字(请记住,您必须自己解析任何代码!) - 但在这里我们只是笨拙地添加&#34 ;你好&#34;到文件的开头以进行测试。例如。我们必须更改编辑器实例的TextBuffer。为此,我们需要创建一个ITextEdit对象,我们可以使用该对象操作文本并在之后应用它的更改。代码非常自我解释:

        private void HandleChange(string newText)
        {
            ITextEdit edit = _view.TextBuffer.CreateEdit();
            edit.Insert(0, "Hello");
            edit.Apply();
        }
        
      8. 编译此加载项时,Visual Studio的实验配置单元启动时只加载了我们的扩展。创建一个新的C#文件并开始输入以查看结果。

        我希望这能为您提供一些如何继续本主题的建议。我现在必须自己探索。

        我强烈推荐MSDN上编辑器的文本模型文档,以获取有关如何执行此操作的提示。 http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel


        <强>脚注

        [*]请注意,Visual Studio 2015或更新版本附带Rosyln编译器平台,它确实已经为您分析了C#和VB.NET文件(也可能是其他预安装的语言)并公开了它们的分层语法结构,但是我还不是这个主题的专家,而是就如何使用这些新服务给出答案。无论如何,启动编辑器扩展的基本进度与本答案中描述的相同。请注意 - 如果您使用这些服务 - 您将依赖于Visual Studio 2015+,并且该扩展将无法在早期版本中使用。

答案 1 :(得分:7)

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

和Thorsten