【问题标题】:Visual Studio Text Editor ExtensionVisual Studio 文本编辑器扩展
【发布时间】:2011-10-08 17:29:06
【问题描述】:

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

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

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

【问题讨论】:

  • @Pac-Man:可悲的是,我不得不把它放在次要位置(由于找不到资源),所以我从来没有完全解决它。如果我真的弄明白了,我会告诉你的。对于小型操作,我发现编写宏效果很好。
  • @Pac-Man:那确实是最棒的。我对 MSDN 的东西感到痛苦(有时)。可悲的是,我认为这个扩展只是那些“黑魔法”之一
  • 我希望我发布的答案中的链接可以帮助你。这些教程几乎解释了我需要了解的有关 VS 插件的所有信息,即使屏幕截图丢失。

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


【解决方案1】:

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

在下面的示例中,我们将创建一个小而笨拙的扩展,当进行编辑时,它总是会在代码文件的开头添加“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 位于 VisualStudioIntegration\Common\Assemblies\v4.0 下的 Visual Studio SDK 目录中。

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

  3. 我们需要通过指定属性[Export(typeof(IWpfTextViewCreationListener))] 使TextViewCreationListener 类对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)
        {
        }
    }
    

为代码格式化创建一个类

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

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

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

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

    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事件处理程序中的这个布尔成员变量再次重置为false

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

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

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


脚注

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

【讨论】:

  • 我通过使用“编辑器分类器”项目类型而不是 VISX 项目类型来完成这项工作。您的演示和我的扩展程序运行良好。
  • 请注意,您需要添加对 Microsoft.VisualStudio.Text.Data 的引用以进行事件处理。使用 VSIX 项目类型时我也无法让它工作,但当我使用编辑器分类器时它工作 - 要解决这个问题,您需要采取两个步骤: 1. 将项目添加为 VSIX 清单中的资产。 2. 在项目文件中,删除变量 IncludeAssemblyInVSIXContainer、IncludeDebugSymbolsInVSIXContainer 和 IncludeDebugSymbolsInLocalVSIXDeployment 或将其设置为 true。除此之外,很棒的教程 - 真的帮助了我!
  • 我没有在 VS 2013 包中标记编辑器分类器就可以正常工作。谢谢!
  • 我必须在我的 VS2015 VSIX 项目中添加 Editor Classifier 才能使其正常工作。换句话说:Right Click Project &gt; Add &gt; New Item &gt; Visual C# Items &gt; Extensibility &gt; Editor Classifier &gt; Add 之后它就起作用了。感谢您的演练!
  • @ElDoRado1239 是的,我放弃了扩展 VS,因为它一团糟。随意编辑我的答案,因为我不知道在哪里最好添加该步骤,以及它是否会替换任何其他步骤。
【解决方案2】:

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

索斯滕

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多