语法高亮不适用于 IVsInvisibleEditor
Syntax Highlight doesn't work for IVsInvisibleEditor
我创建了一个 IVsInvisibleEditor 实例。我使用以下代码来实现此目的:
public IWpfTextViewHost CreateEditor(string targetFile)
{
var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
var editorAdapter = componentModel.GetService<IVsEditorAdaptersFactoryService>();
var editorFactoryService = componentModel.GetService<ITextEditorFactoryService>();
var invisibleEditorManager = (IVsInvisibleEditorManager)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsInvisibleEditorManager));
IVsInvisibleEditor invisibleEditor;
ErrorHandler.ThrowOnFailure(invisibleEditorManager.RegisterInvisibleEditor(
targetFile,
pProject: null,
dwFlags: (uint)_EDITORREGFLAGS.RIEF_ENABLECACHING,
pFactory: null,
ppEditor: out invisibleEditor));
var docDataPointer = IntPtr.Zero;
Guid guidIVsTextLines = typeof(IVsTextLines).GUID;
ErrorHandler.ThrowOnFailure(invisibleEditor.GetDocData(
fEnsureWritable: 1,
riid: ref guidIVsTextLines,
ppDocData: out docDataPointer));
//Create a code window adapter
IVsTextLines docData = (IVsTextLines)Marshal.GetObjectForIUnknown(docDataPointer);
var codeWindow = editorAdapter.CreateVsCodeWindowAdapter(VisualStudioServices.OLEServiceProvider);
ErrorHandler.ThrowOnFailure(codeWindow.SetBuffer(docData));
IVsTextView textView;
ErrorHandler.ThrowOnFailure(codeWindow.GetPrimaryView(out textView));
var userData = (IVsUserData)codeWindow;
var uniqueMoniker = Guid.NewGuid().ToString();
Guid bufferMonikerGuid = typeof(IVsUserData).GUID;
userData.SetData(ref bufferMonikerGuid, uniqueMoniker);
var guid = VSConstants.VsTextBufferUserDataGuid.VsTextViewRoles_guid;
userData.SetData(ref guid, editorFactoryService.CreateTextViewRoleSet(editorFactoryService.DefaultRoles).ToString());
var host = editorAdapter.GetWpfTextViewHost(textView);
host.TextView.Options.SetOptionValue(DefaultTextViewHostOptions.ZoomControlId, false);
return host;
}
一切正常,除了没有语法突出显示,例如,如果我使用 C# (.cs) 文件在不可见的编辑器中显示。经过一些研究,我发现我还需要向 RDT 添加一个文档,这是我使用以下函数完成的:
uint RegisterDocument(string targetFile)
{
//Then when creating the IVsInvisibleEditor, find and lock the document
uint itemID;
IntPtr docData;
uint docCookie;
IVsHierarchy hierarchy;
var runningDocTable = (IVsRunningDocumentTable)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsRunningDocumentTable));
var result = runningDocTable.FindAndLockDocument(
dwRDTLockType: (uint)_VSRDTFLAGS.RDT_EditLock,
pszMkDocument: targetFile,
ppHier: out hierarchy,
pitemid: out itemID,
ppunkDocData: out docData,
pdwCookie: out docCookie);
return docCookie;
}
现在,如果我显示 C# 文件,则会显示高亮显示(智能感知也有效),但是如果我显示 sql 文件,那么我又一次没有语法高亮显示。现在,我进一步调查了一下,意识到也许我应该在文档上附加语言服务,所以我使用这段代码来实现:
Guid sqlGuid = LanguageServices.Guids.TSQL;
docData.SetLanguageServiceID(ref sqlGuid);
瞧,它起作用了,现在语法突出显示也适用于 sql 文件,但现在我有另一个问题,sql 文件上的多视图不起作用。例如,如果我有一个文件 MyQuery.sql 并且我用隐形编辑器打开它,它将被打开,语法将被显示并且一切都按预期工作,但是现在,如果我尝试打开同一个文件(虽然不可见编辑器仍然打开)然后我收到以下消息:
我认为使用 sql 文件时 RDT 的某些内容不正确,似乎当未附加语言服务时,添加到 RDT 会以某种方式被忽略,这很奇怪,因为相同的代码适用于C#文件。有没有其他方法可以使用隐形编辑器打开特定文件(可以是任何类型),我错过了什么吗?
在这个问题上花了几天时间,我终于找到了问题所在。所以,如果其他人也遇到麻烦,这里的解释是:
创建 InvisibleEditor 时,会发生很多事情 "underneath",应该设置的一件事也是特定 ITextBuffer 的 ContentType。当使用 sql 文件(作为名字参数传递给 RegisterInvisibleEditor 方法)时,ContentType 设置为纯文本(但对于 csharp 文件,它设置为 CSharp ContentType),这显然是错误的,但是,呼叫:
Guid sqlGuid = LanguageServices.Guids.TSQL;
docData.SetLanguageServiceID(ref sqlGuid);
应该可以解决这个问题,设置语言服务将设置正确的 ContentType,但出于某种原因,在我的情况下这不起作用。经过一些调试后,我发现当在解决方案资源管理器中通过 dbl 单击打开时,ContentType 与预期的不同。它是 "Sql Server Tools" ContentType 而不是 "T-SQL90",因此,我尝试使用 IVsTextBuffer 查找该类型的 guid:
Guid langId;
vsTextBuffer.GetLanguageServiceID(out langId);
这给了我正确的 guid,所以当替换为我的 tsql languange 服务时,它按预期工作。如果有人需要这些指南,可以在
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio.0\Languages
(取决于 VS 安装)。
最后,这是我用来映射这些 guid 的助手 class:
public static class LanguageServices
{
public static class Guids
{
public static Guid VisualBasic = new Guid("E34ACDC0-BAAE-11D0-88BF-00A0C9110049");
public static Guid CSharp = new Guid("694DD9B6-B865-4C5B-AD85-86356E9C88DC");
public static Guid FSharp = new Guid("bc6dd5a5-d4d6-4dab-a00d-a51242dbaf1b");
public static Guid CPlusPlus = new Guid("B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9");
public static Guid Css = new Guid("A764E898-518D-11d2-9A89-00C04F79EFC3");
public static Guid Html = new Guid("58E975A0-F8FE-11D2-A6AE-00104BCC7269");
public static Guid JavaScript = new Guid("59E2F421-410A-4fc9-9803-1F4E79216BE8");
public static Guid TSQL = new Guid("43AF1158-FED5-432e-8E8F-23B6FD592857");
public static Guid SQL = new Guid("ed1a9c1c-d95c-4dc1-8db8-e5a28707a864");
public static Guid Xaml = new Guid("c9164055-039b-4669-832d-f257bd5554d4");
public static Guid Xml = new Guid("f6819a78-a205-47b5-be1c-675b3c7f0b8e");
}
}
我创建了一个 IVsInvisibleEditor 实例。我使用以下代码来实现此目的:
public IWpfTextViewHost CreateEditor(string targetFile)
{
var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
var editorAdapter = componentModel.GetService<IVsEditorAdaptersFactoryService>();
var editorFactoryService = componentModel.GetService<ITextEditorFactoryService>();
var invisibleEditorManager = (IVsInvisibleEditorManager)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsInvisibleEditorManager));
IVsInvisibleEditor invisibleEditor;
ErrorHandler.ThrowOnFailure(invisibleEditorManager.RegisterInvisibleEditor(
targetFile,
pProject: null,
dwFlags: (uint)_EDITORREGFLAGS.RIEF_ENABLECACHING,
pFactory: null,
ppEditor: out invisibleEditor));
var docDataPointer = IntPtr.Zero;
Guid guidIVsTextLines = typeof(IVsTextLines).GUID;
ErrorHandler.ThrowOnFailure(invisibleEditor.GetDocData(
fEnsureWritable: 1,
riid: ref guidIVsTextLines,
ppDocData: out docDataPointer));
//Create a code window adapter
IVsTextLines docData = (IVsTextLines)Marshal.GetObjectForIUnknown(docDataPointer);
var codeWindow = editorAdapter.CreateVsCodeWindowAdapter(VisualStudioServices.OLEServiceProvider);
ErrorHandler.ThrowOnFailure(codeWindow.SetBuffer(docData));
IVsTextView textView;
ErrorHandler.ThrowOnFailure(codeWindow.GetPrimaryView(out textView));
var userData = (IVsUserData)codeWindow;
var uniqueMoniker = Guid.NewGuid().ToString();
Guid bufferMonikerGuid = typeof(IVsUserData).GUID;
userData.SetData(ref bufferMonikerGuid, uniqueMoniker);
var guid = VSConstants.VsTextBufferUserDataGuid.VsTextViewRoles_guid;
userData.SetData(ref guid, editorFactoryService.CreateTextViewRoleSet(editorFactoryService.DefaultRoles).ToString());
var host = editorAdapter.GetWpfTextViewHost(textView);
host.TextView.Options.SetOptionValue(DefaultTextViewHostOptions.ZoomControlId, false);
return host;
}
一切正常,除了没有语法突出显示,例如,如果我使用 C# (.cs) 文件在不可见的编辑器中显示。经过一些研究,我发现我还需要向 RDT 添加一个文档,这是我使用以下函数完成的:
uint RegisterDocument(string targetFile)
{
//Then when creating the IVsInvisibleEditor, find and lock the document
uint itemID;
IntPtr docData;
uint docCookie;
IVsHierarchy hierarchy;
var runningDocTable = (IVsRunningDocumentTable)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsRunningDocumentTable));
var result = runningDocTable.FindAndLockDocument(
dwRDTLockType: (uint)_VSRDTFLAGS.RDT_EditLock,
pszMkDocument: targetFile,
ppHier: out hierarchy,
pitemid: out itemID,
ppunkDocData: out docData,
pdwCookie: out docCookie);
return docCookie;
}
现在,如果我显示 C# 文件,则会显示高亮显示(智能感知也有效),但是如果我显示 sql 文件,那么我又一次没有语法高亮显示。现在,我进一步调查了一下,意识到也许我应该在文档上附加语言服务,所以我使用这段代码来实现:
Guid sqlGuid = LanguageServices.Guids.TSQL;
docData.SetLanguageServiceID(ref sqlGuid);
瞧,它起作用了,现在语法突出显示也适用于 sql 文件,但现在我有另一个问题,sql 文件上的多视图不起作用。例如,如果我有一个文件 MyQuery.sql 并且我用隐形编辑器打开它,它将被打开,语法将被显示并且一切都按预期工作,但是现在,如果我尝试打开同一个文件(虽然不可见编辑器仍然打开)然后我收到以下消息:
我认为使用 sql 文件时 RDT 的某些内容不正确,似乎当未附加语言服务时,添加到 RDT 会以某种方式被忽略,这很奇怪,因为相同的代码适用于C#文件。有没有其他方法可以使用隐形编辑器打开特定文件(可以是任何类型),我错过了什么吗?
在这个问题上花了几天时间,我终于找到了问题所在。所以,如果其他人也遇到麻烦,这里的解释是:
创建 InvisibleEditor 时,会发生很多事情 "underneath",应该设置的一件事也是特定 ITextBuffer 的 ContentType。当使用 sql 文件(作为名字参数传递给 RegisterInvisibleEditor 方法)时,ContentType 设置为纯文本(但对于 csharp 文件,它设置为 CSharp ContentType),这显然是错误的,但是,呼叫:
Guid sqlGuid = LanguageServices.Guids.TSQL;
docData.SetLanguageServiceID(ref sqlGuid);
应该可以解决这个问题,设置语言服务将设置正确的 ContentType,但出于某种原因,在我的情况下这不起作用。经过一些调试后,我发现当在解决方案资源管理器中通过 dbl 单击打开时,ContentType 与预期的不同。它是 "Sql Server Tools" ContentType 而不是 "T-SQL90",因此,我尝试使用 IVsTextBuffer 查找该类型的 guid:
Guid langId;
vsTextBuffer.GetLanguageServiceID(out langId);
这给了我正确的 guid,所以当替换为我的 tsql languange 服务时,它按预期工作。如果有人需要这些指南,可以在 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio.0\Languages (取决于 VS 安装)。
最后,这是我用来映射这些 guid 的助手 class:
public static class LanguageServices
{
public static class Guids
{
public static Guid VisualBasic = new Guid("E34ACDC0-BAAE-11D0-88BF-00A0C9110049");
public static Guid CSharp = new Guid("694DD9B6-B865-4C5B-AD85-86356E9C88DC");
public static Guid FSharp = new Guid("bc6dd5a5-d4d6-4dab-a00d-a51242dbaf1b");
public static Guid CPlusPlus = new Guid("B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9");
public static Guid Css = new Guid("A764E898-518D-11d2-9A89-00C04F79EFC3");
public static Guid Html = new Guid("58E975A0-F8FE-11D2-A6AE-00104BCC7269");
public static Guid JavaScript = new Guid("59E2F421-410A-4fc9-9803-1F4E79216BE8");
public static Guid TSQL = new Guid("43AF1158-FED5-432e-8E8F-23B6FD592857");
public static Guid SQL = new Guid("ed1a9c1c-d95c-4dc1-8db8-e5a28707a864");
public static Guid Xaml = new Guid("c9164055-039b-4669-832d-f257bd5554d4");
public static Guid Xml = new Guid("f6819a78-a205-47b5-be1c-675b3c7f0b8e");
}
}