Visual Studio文本编辑器扩展

A.R*_*.R. 36 c# visual-studio-2010 visual-studio visual-studio-extensions

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

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

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

Ray*_*Ray 57

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

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

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

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

创建项目

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

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

创建一个监听器类以获得有关文本编辑器实例创建的通知

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

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

  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)
        {
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

创建用于代码格式化的类

接下来,我们需要一个处理代码格式化逻辑,排序方法等的类.同样,在这个例子中,只要编辑完成,它就会在文件的开头添加"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);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. Changed每次编辑时都会调用该事件(例如,键入字符,粘贴代码或编程更改).因为它也会对程序化更改做出反应,所以我使用bool来确定我们的扩展或用户/其他任何内容是否正在更改代码,并且FormatCode()只有在我们的扩展尚未编辑时才调用我的自定义方法.否则,您将递归调用此方法,这将导致Visual Studio崩溃:

    private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
    {
        if (!_isChangingText)
        {
            _isChangingText = true;
            FormatCode(e);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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);
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  7. 在该HandleChange方法中,我们实际上可以扫描关键字以便以特定方式处理这些关键字(请记住,您必须自己解析任何代码!) - 但是在这里我们只是笨拙地将"Hello"添加到文件的开头以进行测试.例如,我们必须更改TextBuffer编辑器实例.为此,我们需要创建一个ITextEdit对象,我们可以使用该对象操作文本并在之后应用它的更改.代码非常自我解释:

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

编译此加载项时,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项目类型来实现此功能.您的演示和我的扩展程序正常运行. (3认同)
  • 我必须在我的 VS2015 VSIX 项目中添加“编辑器分类器”才能使其正常工作。换句话说:`右键单击项目&gt; 添加&gt; 新项目&gt; Visual C# 项目&gt; 扩展性&gt; 编辑器分类器&gt; 添加`,然后它就可以工作了。感谢您的演练! (2认同)

Tho*_*ans 7

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

托尔斯滕