准备工作
我打算在这篇中介绍一个完整的例子:ManagedMyC,这个例子包含在SDK中,在调试前请先安装SDK。在Microsoft Visual Studio 2008 SDK的Samples中,找到这个例子,然后在Visual Studio中打开:
调试
打开后,你可以编译调试。这是个集成模式的例子,默认在实验室环境下加载这个语言服务包,所以你将看到这样的结果:
事实上此时,我们的包还没有加载,语言服务的包只有当特定后缀的文件在VS中打开的时候才会加载。这个例子注册的后缀为”.myc”,这是个C语言的半成品语言服务。
打开一个.myc的文件,你可以选择一个示例文件,这个文件放在类似这样的路径下,...\Local\VSSDK_9.0_1.1\Example.ManagedMyC_F3D35F91\testfiles 你可以在工程中找到这个路径和两个测试文件。然后打开他们,现在我打开其中一个:
打开后将是这样:
我们看到,这是一段C代码,IDE为我们高亮了一些关键字,对于注释也有特定的颜色,另外你如果尝试编写一些个代码,还会发现,它还支持括号匹配、甚至还有错误提示。
这个例子已经很好的展示了语言服务的强大之处,上面所提到的功能都是语言服务所实现的。
初窥代码
宿主包
任何一个或多个服务都可以通过包的形式集成到VS中,语言服务也不例外,事实上语言服务必需依照这种扩展方式来扩展。在工程中找到UserSupplied文件夹下的Package.cs,这是个非常简单的类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [Microsoft.VisualStudio.Shell.PackageRegistration(UseManagedResourcesOnly= true )] [Microsoft.VisualStudio.Shell.DefaultRegistryRoot( @"Software\Microsoft\VisualStudio\9.0Exp" )] [Microsoft.VisualStudio.Shell.ProvideService( typeof (Babel.LanguageService))] [Microsoft.VisualStudio.Shell.ProvideLanguageExtension( typeof (Babel.LanguageService), Configuration.Extension)] [Microsoft.VisualStudio.Shell.ProvideLanguageService( typeof (Babel.LanguageService), Configuration.Name,0, CodeSense = true , EnableCommenting = true , MatchBraces = true , ShowCompletion = true , ShowMatchingBrace = true , AutoOutlining = true , EnableAsyncCompletion = true , CodeSenseDelay = 0)] [Guid( "7b98c6da-ca1b-4ff4-8638-b0ba4473c68e" )] class Package : BabelPackage { } |
1 | |
下面介绍一下类的关键属性,省略了几个属性,如有疑问请做功课,呵呵:
属性 |
说明 |
ProvideService |
说明这个包提供服务的类是什么 |
ProvideLanguageExtension |
说明这个包是个语言服务,并说明是哪个类,是什么后缀 |
ProvideLanguageService |
说明这个包是个语言服务,并说明是哪个类,语言服务的名称,这个语言服务提供了哪些功能,这里有注释、括号匹配等。 |
我们知道Package的这些属性大多是设置一些注册信息,以集成到VS中,这里的几个属性也是如此。值得注意的还有一点,这个类完全没有任何实现,只是继承自一个叫做BabelPackage的类,这个类是ManagedBabel中的类,你可以在工程的ManagedBabel文件夹下的Package.cs中找到,这个类实现了Microsoft.VisualStudio.Shell.Package大多数必需的重写。
语言服务类
看完包,来看看最重要的语言服务类在哪里,定位到UserSupplied文件夹下的LanguageService.cs,这个便是我们注册的语言服务,但是好像代码简单的出奇!但又继承了一个叫BabelLanguageService的类,于是我们刨根问底,再来看看BabelLanguageService,这个类在ManagedBabel文件夹下的LanguageService.cs中,继承自LanguageService。你是不是开始困扰哪来这么多Babel啊?实际上,为了让开发人员更方便的开发语言服务,微软在SDK中设计了基于Managed Package Framework的Managed Babel 。它是一系列cs文件,你在ManagedBabel文件夹下看到的就是Managed Babel的文件。微软并不推荐我们修改它们,但我的经验是,为了做出我们特有的功能,必须要修改其中的代码,但建议在修改时请保留原来的文件,只在工程中修改它们的拷贝就行了。
言归正传,这个BabelLanguageService的代码不算少,我并不打算现在就解释它。但到目前为止,我们必须要明确的问题是:语言服务需要一个包来承载,包需要继承于Microsoft.VisualStudio.Shell.Package;语言服务需要一个类,这个类继承于Microsoft.VisualStudio.Package.LanguageService;微软为了让我们更方便的编写语言服务,提供了一个称作Managed Babel的文件集,在开发语言服务的时候可以利用它们。
语言核心
还有两个文件你也许早就注意到了:在Generated文件夹下的lexer.lex和parser.y。没错!两个十分奇怪的文件,这不光体现在它的后缀,当你看到其中的代码时,你将几乎看不懂(除非你从事过编译器或解析器工作)。不过不用担心,在以后的章节中我将结合微软的文档,详细介绍这两个文件的编写,因为在实际的开发中,在这两个文件上花的时间将占到整个开发的80%以上!唯一遗憾的是,微软没有为这两个文件实现语言服务!呵呵!
小结
在本节中我们成功调试了ManagedMyC,并且了解了语言服务的基本组成,还知道了Managed Babel是一系列的文件,方便我们集成语言服务,另外初窥了.lex和.y文件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义