语言服务和编辑器扩展点

编辑器提供扩展点,可以扩展为托管扩展性框架(MEF)组件部件,包括大多数语言服务功能。 以下是主要扩展点类别:

  • 内容类型

  • 分类类型和分类格式

  • 边距和滚动条

  • Tags

  • 装饰品

  • 鼠标处理器

  • 删除处理程序

  • 选项

  • IntelliSense

扩展内容类型

内容类型是编辑器处理的文本类型的定义,例如“text”、“code”或“CSharp”。 通过声明类型的 ContentTypeDefinition 变量并为新内容类型指定唯一名称来定义新的内容类型。 若要向编辑器注册内容类型,请将其导出为以下属性:

  • NameAttribute 是内容类型的名称。

  • BaseDefinitionAttribute 是派生此内容类型的内容类型的名称。 内容类型可能继承自多个其他内容类型。

    因为类 ContentTypeDefinition 是密封的,所以可以导出它,没有类型参数。

    以下示例演示内容类型定义上的导出属性。

[Export]
[Name("test")]
[BaseDefinition("code")]
[BaseDefinition("projection")]
internal static ContentTypeDefinition TestContentTypeDefinition;

内容类型可以基于零个或多个预先存在的内容类型。 以下是内置类型:

  • 任何:基本内容类型。 所有其他内容类型的父级。

  • 文本:非投影内容的基本类型。 继承自“any”。

  • 纯文本:对于非代码文本。 继承自“text”。

  • 代码:适用于所有类型的代码。 继承自“text”。

  • Inert:从任何类型的处理中排除文本。 此内容类型的文本永远不会应用任何扩展。

  • 投影:投影缓冲区的内容。 继承自“any”。

  • Intellisense:对于 IntelliSense 的内容。 继承自“text”。

  • Sighelp:签名帮助。 继承自“intellisense”。

  • Sighelp-doc:签名帮助文档。 继承自“intellisense”。

    以下是 Visual Studio 定义的一些内容类型,以及 Visual Studio 中托管的一些语言:

  • 基本

  • C/C++

  • ConsoleOutput

  • CSharp

  • CSS

  • ENC

  • FindResults

  • F#

  • HTML

  • JScript

  • XAML

  • XML

    若要发现可用内容类型的列表,请导入 IContentTypeRegistryService用于维护编辑器内容类型集合的 。 以下代码将此服务作为属性导入。

[Import]
internal IContentTypeRegistryService ContentTypeRegistryService { get; set; }

若要将内容类型与文件扩展名相关联,请使用 FileExtensionToContentTypeDefinition

注意

在 Visual Studio 中,文件扩展名是使用 ProvideLanguageExtensionAttribute 语言服务包注册的。 将 FileExtensionToContentTypeDefinition MEF 内容类型与以这种方式注册的文件扩展名相关联。

若要将文件扩展名导出到内容类型定义,必须包含以下属性:

[Export]
[FileExtension(".test")]
[ContentType("test")]
internal static FileExtensionToContentTypeDefinition TestFileExtensionDefinition;

管理 IFileExtensionRegistryService 文件扩展名和内容类型之间的关联。

扩展分类类型和分类格式

可以使用分类类型来定义要提供不同处理的文本类型(例如,将“关键字 (keyword)”文本设置为蓝色和“注释”文本绿色)。 通过声明类型的 ClassificationTypeDefinition 变量并为其指定唯一名称来定义新的分类类型。

若要向编辑器注册分类类型,请将其导出为以下属性:

  • NameAttribute:分类类型的名称。

  • BaseDefinitionAttribute:此分类类型继承的分类类型的名称。 所有分类类型都继承自“text”,分类类型可能继承自多个其他分类类型。

    因为类 ClassificationTypeDefinition 是密封的,所以可以导出它,没有类型参数。

    以下示例演示分类类型定义的导出属性。

[Export]
[Name("csharp.test")]
[BaseDefinition("test")]
internal static ClassificationTypeDefinition CSharpTestDefinition;

提供 IStandardClassificationService 对标准分类的访问权限。 内置分类类型包括:

  • "text"

  • “自然语言”(派生自“text”)

  • “正式语言”(派生自“text”)

  • “string”(派生自“literal”)

  • “character”(派生自“literal”)

  • “数字”(派生自“literal”)

    一组不同的错误类型继承自 ErrorTypeDefinition。 它们包括以下错误类型:

  • “语法错误”

  • “编译器错误”

  • “其他错误”

  • “warning”

    若要发现可用分类类型的列表,请导入 IClassificationTypeRegistryService该列表,该集合维护编辑器的分类类型集合。 以下代码将此服务作为属性导入。

[Import]
internal IClassificationTypeRegistryService ClassificationTypeRegistryService { get; set; }

可以为新的分类类型定义分类格式定义。 从 ClassificationFormatDefinition 中派生类,并使用类型 EditorFormatDefinition导出类,以及以下属性:

[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "test")]
[Name("test")]
[DisplayName("Test")]
[UserVisible(true)]
[Order(After = Priority.Default, Before = Priority.High)]
internal sealed class TestFormat : ClassificationFormatDefinition

若要发现可用格式的列表,请导入 IEditorFormatMapService该列表,该集合维护编辑器的格式集合。 以下代码将此服务作为属性导入。

[Import]
internal IEditorFormatMapService FormatMapService { get; set; }

扩展边距和滚动条

边距和滚动条是编辑器的主要视图元素,除了文本视图本身。 除了文本视图周围显示的标准边距外,还可以提供任意数量的边距。

实现用于 IWpfTextViewMargin 定义边距的接口。 还必须实现 IWpfTextViewMarginProvider 接口来创建边距。

若要向编辑器注册边距提供程序,必须将提供程序导出为以下属性:

  • NameAttribute:边距的名称。

  • OrderAttribute:相对于其他边距显示边距的顺序。

    以下是内置边距:

    • “Wpf 水平滚动条”

    • “Wpf 垂直滚动条”

    • “Wpf 行号边距”

      具有顺序属性的水平 After="Wpf Horizontal Scrollbar" 边距显示在内置边距下方,具有顺序属性 Before ="Wpf Horizontal Scrollbar" 的水平边距显示在内置边距上方。 具有顺序属性 After="Wpf Vertical Scrollbar" 的右垂直边距显示在滚动条右侧。 具有订单属性 After="Wpf Line Number Margin" 的左垂直边距显示在行号边距左侧(如果可见)。

  • MarginContainerAttribute:边距类型(左、右、上或下)。

  • ContentTypeAttribute:页边距有效的内容类型(例如“text”或“code”。

    以下示例显示了边距提供程序上显示行号边距右侧的边距的导出属性。

[Export(typeof(IWpfTextViewMarginProvider))]
[Name("TestMargin")]
[Order(Before = "Wpf Line Number Margin")]
[MarginContainer(PredefinedMarginNames.Left)]
[ContentType("text")]

扩展标记

标记是将数据与不同类型的文本相关联的方法。 在许多情况下,关联的数据显示为视觉效果,但并非所有标记都具有可视呈现。 可以通过实现 ITag自己的标记来定义自己的标记类型。 还必须实现 ITagger<T> 为给定的文本范围集提供标记,并提供 ITaggerProvider 标记器。 必须将标记器提供程序与以下属性一起导出:

  • ContentTypeAttribute:标记有效的内容类型(例如“text”或“code”。

  • TagTypeAttribute:标记的类型。

    以下示例显示了标记器提供程序上的导出属性。

<CodeContentPlaceHolder>8 内置了以下类型的标记:

[Import]
internal IViewTagAggregatorFactoryService ViewTagAggregatorFactoryService { get; set; }

Tags 和 MarkerFormatDefinitions

可以扩展 MarkerFormatDefinition 类以定义标记的外观。 必须使用以下属性导出类(作为 EditorFormatDefinition):

[Export(typeof(EditorFormatDefinition))]
[Name("MarkerFormatDefinition/HighlightWordFormatDefinition")]
[UserVisible(true)]
internal class HighlightWordFormatDefinition : MarkerFormatDefinition
{
    public HighlightWordFormatDefinition()
    {
        this.BackgroundColor = Colors.LightBlue;
        this.ForegroundColor = Colors.DarkBlue;
        this.DisplayName = "Highlight Word";
        this.ZOrder = 5;
    }
}

若要将此格式定义应用于标记,请引用在类的名称属性(而不是显示名称)中设置的名称。

注意

有关示例MarkerFormatDefinition,请参阅 Walkthrough: HighlightIng Text 中的 HighlightWordFormatDefinition 类。

扩展装饰

装饰定义可添加到文本视图中显示的文本或文本视图本身的视觉效果。 可以将自己的装饰定义为任何类型的 UIElement装饰。

在装饰类中,必须声明一个 AdornmentLayerDefinition。 若要注册装饰层,请将其导出为以下属性:

[Export]
[Name("TestEmbeddedAdornment")]
[Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
internal AdornmentLayerDefinition testLayerDefinition;

必须创建一个实现和处理其TextViewCreated事件的第二类IWpfTextViewCreationListener,方法是实例化装饰。 必须结合以下属性导出此类:

  • ContentTypeAttribute:装饰有效内容的种类(例如“text”或“code”。

  • TextViewRoleAttribute:此装饰有效的文本视图类型。 该类 PredefinedTextViewRoles 具有一组预定义的文本视图角色。 例如, Document 主要用于文件的文本视图。 Interactive 用于用户可以使用鼠标和键盘编辑或导航的文本视图。 视图的示例 Interactive 包括编辑器文本视图和 “输出 ”窗口。

    以下示例演示装饰提供程序上的导出属性。

[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("csharp")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class TestAdornmentProvider : IWpfTextViewCreationListener

空间谈判装饰是占用与文本相同的空间的装饰。 若要创建此类装饰,必须定义继承自 SpaceNegotiatingAdornmentTag的标记类,该标记类定义装饰所占用的空间量。

与所有装饰一样,必须导出装饰层定义。

[Export]
[Name("TestAdornment")]
[Order(After = DefaultAdornmentLayers.Text)]
internal AdornmentLayerDefinition testAdornmentLayer;

若要实例化空间协商装饰,除了实现IWpfTextViewCreationListener类(与其他类型的装饰一样),还必须创建实现ITaggerProvider的类。

若要注册标记器提供程序,必须将其与以下属性一起导出:

[Export(typeof(ITaggerProvider))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
[TagType(typeof(SpaceNegotiatingAdornmentTag))]
[TagType(typeof(TestSpaceNegotiatingTag))]
internal sealed class TestTaggerProvider : ITaggerProvider

扩展鼠标处理器

可以为鼠标输入添加特殊处理。 创建一个类,该类继承 MouseProcessorBase 并覆盖要处理的输入的鼠标事件。 还必须在第二类中实现 IMouseProcessorProvider ,并将其与 ContentTypeAttribute 指定鼠标处理程序有效的内容类型(例如“text”或“code”)一起导出。

以下示例显示鼠标处理器提供程序上的导出属性。

[Export(typeof(IMouseProcessorProvider))]
[Name("test mouse processor")]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Interactive)]
internal sealed class TestMouseProcessorProvider : IMouseProcessorProvider

扩展删除处理程序

可以通过创建实现 IDropHandler 的类和实现 IDropHandlerProvider 创建删除处理程序的第二个类来创建放置处理程序来自定义特定类型文本的行为。 必须将放置处理程序与以下属性一起导出:

  • DropFormatAttribute:此删除处理程序有效的文本格式。 以下格式按从高到低的优先级顺序进行处理:

    1. 任何自定义格式

    2. FileDrop

    3. EnhancedMetafile

    4. WaveAudio

    5. Riff

    6. Dif

    7. 区域设置

    8. 调色板

    9. PenData

    10. 可序列化

    11. SymbolicLink

    12. Xaml

    13. XamlPackage

    14. Tiff

    15. Bitmap

    16. Dib

    17. MetafilePicture

    18. CSV

    19. System.String

    20. HTML 格式

    21. UnicodeText

    22. OEMText

    23. 文本

  • NameAttribute:放置处理程序的名称。

  • OrderAttribute:默认放置处理程序之前或之后放置处理程序的顺序。 Visual Studio 的默认删除处理程序名为“DefaultFileDropHandler”。

    以下示例演示删除处理程序提供程序上的导出属性。

[Export(typeof(IDropHandlerProvider))]
[DropFormat("Text")]
[Name("TestDropHandler")]
[Order(Before="DefaultFileDropHandler")]
internal class TestDropHandlerProvider : IDropHandlerProvider

扩展编辑器选项

可以定义仅在特定范围内有效的选项,例如,在文本视图中。 编辑器提供了一组预定义选项:编辑器选项、视图选项和 Windows Presentation Foundation (WPF) 视图选项。 这些选项可在 DefaultTextViewOptionsa0/; 中找到DefaultOptionsDefaultWpfViewOptions

若要添加新选项,请从以下选项定义类之一派生类:

[Export(typeof(EditorOptionDefinition))]
internal sealed class TestOption : EditorOptionDefinition<bool>

扩展 IntelliSense

IntelliSense 是一组功能的一般术语,它提供有关结构化文本的信息和语句完成。 这些功能包括语句完成、签名帮助、快速信息和灯泡。 语句完成可帮助用户正确键入语言关键字 (keyword)或成员名称。 签名帮助显示用户刚刚键入的方法的签名或签名。 当鼠标悬停在类型或成员名称上时,快速信息会显示完整的签名。 灯泡在某些上下文中为某些标识符提供其他操作,例如,重命名一个匹配项后,重命名变量的所有匹配项。

在所有情况下,IntelliSense 功能的设计大致相同:

  • IntelliSense 代理 负责整个过程。

  • IntelliSense 会话 表示演示者触发与选定内容的提交或取消之间的事件序列。 会话通常由某些用户手势触发。

  • IntelliSense 控制器 负责确定会话何时应启动和结束。 它还决定何时应提交信息以及何时取消会话。

  • IntelliSense 提供内容并决定最佳匹配项。

  • IntelliSense 演示者 负责显示内容。

    在大多数情况下,我们建议至少提供源和控制器。 如果要自定义显示,还可以提供演示者。

实现 IntelliSense 源

若要自定义源,必须实现以下源接口的一个或多个:

重要

ISmartTagSource 已弃用以支持 ISuggestedActionsSource

此外,必须实现相同类型的提供程序:

必须连同以下属性一起导出提供程序:

  • NameAttribute:源的名称。

  • ContentTypeAttribute:源应用到的内容类型(例如“text”或“code”。

  • OrderAttribute:源应显示的顺序(相对于其他源)。

  • 以下示例显示完成源提供程序上的导出属性。

Export(typeof(ICompletionSourceProvider))]
[Name(" Test Statement Completion Provider")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestCompletionSourceProvider : ICompletionSourceProvider

有关实现 IntelliSense 源的详细信息,请参阅以下演练:

实现 IntelliSense 控制器

若要自定义控制器,必须实现 IIntellisenseController 接口。 此外,还必须实现控制器提供程序以及以下属性:

  • NameAttribute:控制器的名称。

  • ContentTypeAttribute:控制器应用到的内容类型(例如“text”或“code”。

  • OrderAttribute:控制器应显示的顺序(相对于其他控制器)。

    以下示例显示完成控制器提供程序上的导出属性。

Export(typeof(IIntellisenseControllerProvider))]
[Name(" Test Controller Provider")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestIntellisenseControllerProvider : IIntellisenseControllerProvider

有关使用 IntelliSense 控制器的详细信息,请参阅以下演练: