在此link的第一段末尾,它指出:
Visual Studio文本概述功能是通过使用投影缓冲区隐藏折叠文本来实现的,而 ASP.NET页面的Visual Studio编辑器使用投影来支持嵌入式语言,如Visual Basic和C#
我已经搜索过但没有找到任何示例或文档来完成此任务,有没有人知道如何做到这一点?我已经进行了分类工作并创建了一个我想要归类为C#代码的跨度的投影缓冲区。我将缓冲区上下文类型设置为" CSharp"但是跨度从未被分类。我还试图将我的内容类型基于"投影"但现在确实有效。
答案 0 :(得分:6)
Visual Studio中的投影缓冲区主要用于处理一种语言区域嵌入另一种语言的场景。经典的例子是HTML中的CSS和Javascript。同样,ASP.NET或Razor中的C#或VB。事实上,HTML编辑器处理许多语言,其投影缓冲区架构是可扩展的(我写了很多部分)。这样,样式块内的所有功能都由CSS编辑器处理,HTML编辑器不需要做太多。
当你得到它的工作方式时,投影缓冲区并不复杂。投影缓冲区形成图形,顶层缓冲区显示在视图中。投影缓冲区没有自己的内容,它由投影范围组成,而投影范围又是跟踪跨度(ITrackingSpan)或惰性区域(字符串)。
考虑HTML中的样式块。首先,您需要创建内容类型为"投影"的投影缓冲区。或者来自"投影"的其他内容类型。然后创建投影缓冲区,其中包含内容类型为" CSS"的CSS。从磁盘读取的文件位于文本缓冲区中,内容类型为" HTMLX" (" HTML"内容类型保留给经典Web窗体编辑器)。 HTML编辑器解析文件并将样式块内容和内联样式提取到单独的字符串中。内联样式片段被装饰到类中,因此它们看起来很好地形成了CSS编辑器。
现在构建投影映射。第一个CSS投影缓冲区填充有惰性字符串(它们表示用户不可见的CSS,如内联样式的装饰)以及从磁盘缓冲区(HTML)创建的跟踪跨度,用于定义用户可见的区域 - 具体来说,样式的内容块(多个)。
然后构建视图(顶层)缓冲区的投影。这些投影是一个跟踪跨度列表,它是从CSS编辑器投影缓冲区(不是HTML磁盘缓冲区)创建的跟踪跨度和从HTML磁盘缓冲区创建的跟踪跨距的组合,代表视图的HTML部分。
图表大致与此类似
View Buffer [ContentType = "projection"]
| \
| CSS Projection [ContentType = CSS]
| /
Disk Buffer [ContentType = HTMLX]
对视图缓冲区的HTML部分所做的编辑反映到磁盘缓冲区,HTML语言服务提供完成,语法检查等。样式块中的编辑转到CSS项目缓冲区,CSS编辑器提供完成和语法检查。它们也通过第二级投影反射到磁盘缓冲区。
现在,将命令转发到嵌入式语言(例如上下文菜单调用)并为Javascript或C#维护正确的断点映射是一个单独的代码。预测仅对与视图相关的事物有所帮助,控制器链和调试器操作必须单独处理。 HTML编辑器命令控制器可以识别嵌入式语言,并根据插入符位置将命令转发到相应的语言服务。
答案 1 :(得分:5)
我终于成功地将投影缓冲区嵌入到工具窗口中,并将它们连接到C#的语言服务。一个警告:这种方法仅适用于使用Roslyn的Visual Studio。我已发布了您可以使用的Github project以及随附的blog post。
你的问题的答案很长,涉及很多动人的部分,它不适合StackOverflow风格的Q& A。话虽如此,我将总结必要的步骤并包括一些相关的代码。
以下示例创建一个文件的投影缓冲区,该文件由文件的前100个字符组成。
我们首先为给定的文件路径创建IVsInvisibleEditor
并为其创建代码窗口。我们将此代码窗口的内容设置为IVsTextLines
的{{1}}。
然后,我们在此代码窗口的文本缓冲区中设置自定义角色IVsInvisibleEditor
。此角色允许我们通过MEF导出"CustomProjectionRole"
来自定义文本缓冲区。
ITextViewModelProvider
我们现在创建一个public IWpfTextViewHost CreateEditor(string filePath, int start = 0, int end = 100)
{
//IVsInvisibleEditors are in-memory represenations of typical Visual Studio editors.
//Language services, highlighting and error squiggles are hooked up to these editors
//for us once we convert them to WpfTextViews.
var invisibleEditor = GetInvisibleEditor(filePath);
var docDataPointer = IntPtr.Zero;
Guid guidIVsTextLines = typeof(IVsTextLines).GUID;
ErrorHandler.ThrowOnFailure(invisibleEditor.GetDocData(
fEnsureWritable: 1
, riid: ref guidIVsTextLines
, ppDocData: out docDataPointer));
IVsTextLines docData = (IVsTextLines)Marshal.GetObjectForIUnknown(docDataPointer);
//Create a code window adapter
var codeWindow = _editorAdapter.CreateVsCodeWindowAdapter(VisualStudioServices.OLEServiceProvider);
ErrorHandler.ThrowOnFailure(codeWindow.SetBuffer(docData));
//Get a text view for our editor which we will then use to get the WPF control for that editor.
IVsTextView textView;
ErrorHandler.ThrowOnFailure(codeWindow.GetPrimaryView(out textView));
//We add our own role to this text view. Later this will allow us to selectively modify
//this editor without getting in the way of Visual Studio's normal editors.
var roles = _editorFactoryService.DefaultRoles.Concat(new string[] { "CustomProjectionRole" });
var vsTextBuffer = docData as IVsTextBuffer;
var textBuffer = _editorAdapter.GetDataBuffer(vsTextBuffer);
textBuffer.Properties.AddProperty("StartPosition", start);
textBuffer.Properties.AddProperty("EndPosition", end);
var guid = VSConstants.VsTextBufferUserDataGuid.VsTextViewRoles_guid;
((IVsUserData)codeWindow).SetData(ref guid, _editorFactoryService.CreateTextViewRoleSet(roles).ToString());
_currentlyFocusedTextView = textView;
var textViewHost = _editorAdapter.GetWpfTextViewHost(textView);
return textViewHost;
}
来创建并返回IVsTextViewModelProvider
。这个ProjectionTextViewModel
在其Visual Buffer中保存了一个投影缓冲区。这意味着当显示此缓冲区时,投影缓冲区就是显示的内容。但是,后备数据缓冲区的语言服务正常运行。
ProjectionTextViewModel
希望这会让未来的访客有一个良好的开端。
答案 2 :(得分:1)
可以找到一个工作示例here,但根据警告评论,这不是一项简单的任务。
// Abandon all hope ye who enters here.
// https://twitter.com/Schabse/status/393092191356076032
// https://twitter.com/jasonmalinowski/status/393094145398407168
// Based on decompiled code from Microsoft.VisualStudio.Html.ContainedLanguage.Server
// Thanks to Jason Malinowski for helping me navigate this mess.
// All of this can go away when the Roslyn editor ships.
答案 3 :(得分:0)
您留下的评论似乎是在讨论大纲但不支持嵌入式语言。如果您尝试隐藏文字,可以查看此IntraText Code。
如果您通过将启动项目设置为devenv并将命令args设置为/ RootSuffix Exp来下载并安装或调试它,则可以打开文本文件并键入#CCCCCC或任何其他十六进制Web颜色。代码将崩溃并显示一个简单的图形。
据我所知,支持嵌入式语言,您必须编写自己的自定义语言服务。我希望能够支持现有的语言服务intellisense功能。然而,在视觉工作室中,当涉及到这种行为时,你似乎必须重新发明轮子。