Visual studio 在自定义Visual Studio语言服务中支持用户指定的文件扩展名

Visual studio 在自定义Visual Studio语言服务中支持用户指定的文件扩展名,visual-studio,vsx,languageservice,Visual Studio,Vsx,Languageservice,我正在开发一个定制的VisualStudio语言服务,对于将文件扩展名绑定到特定语言服务的方式,我有几个问题 “示例语言”的源文件有两个主要文件扩展名:.e1和.e2。我的扩展有一个类ExampleLanguagePackage,它扩展了 当您使用该文件时→ 打开命令并选择一个C文件(例如,“打开”按钮有一个下拉箭头,允许您选择“打开…”。单击该按钮时,将显示在“CSharp编辑器(默认)”、“CSharp编辑器带编码”或其他任何选项中打开文件的选项。如何为我的语言提供类似的功能,提供“示例语言

我正在开发一个定制的VisualStudio语言服务,对于将文件扩展名绑定到特定语言服务的方式,我有几个问题

“示例语言”的源文件有两个主要文件扩展名:
.e1
.e2
。我的扩展有一个类
ExampleLanguagePackage
,它扩展了

  • 当您使用该文件时→ 打开命令并选择一个C文件(例如,“打开”按钮有一个下拉箭头,允许您选择“打开…”。单击该按钮时,将显示在“CSharp编辑器(默认)”、“CSharp编辑器带编码”或其他任何选项中打开文件的选项。如何为我的语言提供类似的功能,提供“示例语言(默认)”和“示例语言带编码”选项

  • 当你打开工具时→ 选项。。。→ 文本编辑器→ 文件扩展名,您可以(例如)将
    .foo
    扩展名绑定到“Microsoft Visual C#”或其他任何选项。如何扩展此页面以允许用户定义的文件扩展名与“示例语言”关联

  • 注册这些项目时,我还应注意什么


  • 通过为您的语言添加自定义的实现,并使用注册属性组合来注册,可以解决这些问题。这个接口的实际实现超出了这个问题的范围,但是接口本身的文档(并链接到该页面)以及项目中的一个示例实现帮助了我的初始实现

    为了支持示例语言,我将做出以下假设

    • 您已经实现了一个抽象类
      ExampleEditorFactory
      ,它提供了
      IVsEditorFactory
      的核心实现。该类应该有一个受保护的构造函数,该构造函数带有一个
      bool
      参数,用于指定工厂是否应提示用户进行编码(类似于
      DjangoEditorFactory
      的一个构造函数)。
      • 您有一个类
        exampleeditorfactorywithoutencode
        ,它扩展了
        ExampleEditorFactory
        ,并构造基类,为
        promptforencode
        参数指定
        false
        。这个类应该用属性标记
      • 您有一个类
        ExampleEditorFactoryWithEncoding
        ,它扩展了
        ExampleEditorFactory
        ,并构造了基类,为
        PromptForEncode
        参数指定
        true
        。这个类应该用属性标记
    • 您已将以下条目添加到VSPackage.resx资源文件中。常数可以更改,但请注意,我使用了下面的常量值101和102。
      • 101=示例语言
      • 102=带有编码的示例语言
    注册编辑工厂 首先要做的是注册编辑器工厂。这是分两部分完成的

    首先,使用。此属性将工厂显示名称的资源标识符与工厂类型本身相关联

    [ProvideEditorFactory(typeof(ExampleEditorFactoryWithoutEncoding), 101)]
    [ProvideEditorFactory(typeof(ExampleEditorFactoryWithEncoding), 102)]
    
    接下来,在
    ExampleLanguagePackage
    的方法中,在调用
    base.Initialize()之后添加对的调用

    将逻辑视图与编辑器工厂关联 我还没有找到我想要的关于属性用例的所有信息,但至少包括以下内容是很重要的。确保向您创建的两个工厂注册逻辑视图

    [ProvideEditorLogicalView(typeof(ExampleEditorFactoryWithoutEncoding), VSConstants.LOGVIEWID.TextView_string)]
    [ProvideEditorLogicalView(typeof(ExampleEditorFactoryWithEncoding), VSConstants.LOGVIEWID.TextView_string)]
    
    如果未完成此步骤,则在输出窗口中双击可将您带到代码行的功能将无法按预期工作。例如,假设输出窗口包含如下所示的行

    c:\dev\file.e1(14,3): unexpected expression
    
    当您双击此输出行以转到文件c:\dev\file.e1的第14行第3列时,关联TextView逻辑视图允许IDE使用您的工厂。否则,它将使用不同的工厂来打开文档的新副本,并且新窗口可能会缺少许多功能

    将标准文件扩展名
    .e1
    .e2
    与编辑器关联 此步骤为原始问题1中描述的.e1和.e2文件提供了“打开方式…”支持。此步骤通过属性完成

    主工厂的默认优先级似乎为50。使用显式编码的工厂的优先级应该低于此值,49似乎是一个不错的选择。请注意,无需指定
    NameResourceID
    命名参数,因为它已由上面的
    providededitorfactoryattribute
    用法指定(生成的注册表项相同)

    *
    扩展与编辑器工厂关联 此步骤为所有其他文件提供“打开方式…”支持,并添加对原始问题2中所述文件扩展名选项的支持。此步骤还使用
    providededitorextensionAttribute
    属性,但使用低得多的优先级值来确保其他文件类型的默认编辑器不会被设置覆盖。与前一步一样,具有显式编码的工厂的优先级较低

    [ProvideEditorExtension(typeof(ExampleEditorFactoryWithoutEncoding), ".*", 2)]
    [ProvideEditorExtension(typeof(ExampleEditorFactoryWithEncoding), ".*", 1)]
    
    最后说明 这个答案没有涵盖几个细节

    • (对于Visual Studio 2012非常重要)如果您计划支持Visual Studio 2012,请参阅主题以了解有关新属性(或文档记录不完整的属性)的详细信息
    • (重要性未知)
      ProvideEditorFactoryAttribute
      不支持指定值(向下搜索页面)。该值通常会添加到
      ExampleEditorFactoryWithEncoding
      的注册中,并且该值将是
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithoutEncoding), ".e1", 50)]
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithoutEncoding), ".e2", 50)]
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithEncoding), ".e1", 49)]
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithEncoding), ".e2", 49)]
      
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithoutEncoding), ".*", 2)]
      [ProvideEditorExtension(typeof(ExampleEditorFactoryWithEncoding), ".*", 1)]