语法高亮不适用于IVsInvisibleEditor

时间:2015-10-04 19:03:29

标签: c# visual-studio mef

我创建了一个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,我用不可见的编辑器打开它,它将被打开,语法将显示,一切都按预期工作,但现在,如果我尝试打开相同的文件(而隐形编辑器是仍然打开)然后我收到以下消息:

enter image description here

我相信在使用sql文件时RDT的某些东西是不行的,似乎当没有附加语言服务时,添加到RDT会被忽略,这很奇怪,因为相同的代码适用于C#文件。有没有其他方法可以使用隐形编辑器打开特定文件(可以是任何类型),我错过了什么?

1 个答案:

答案 0 :(得分:0)

在这个问题上花了好几天后,我终于找到了问题所在。所以,如果其他人也有问题,这里有解释:

在创建InvisibleEditor时,很多事情正在发生,而在#34;下面,应该设置的一件事也是特定ITextBuffer的ContentType。当使用sql文件(它作为moniker参数传递给RegisterInvisibleEditor方法)时,ContentType被设置为纯文本(但是在csharp文件的情况下,它被设置为CSharp ContentType),这显然是错误的,但是,调用:

    Guid sqlGuid = LanguageServices.Guids.TSQL;
    docData.SetLanguageServiceID(ref sqlGuid);

应该解决这个问题,设置语言服务会设置正确的ContentType,但出于某些原因,在我的情况下这没有用。经过一些调试后,我发现ContentType在解决方案资源管理器中由dbl click打开时,与预期的不同。它是&#34; Sql Server Tools&#34; ContentType not&#34; T-SQL90&#34;,所以,我尝试使用IVsTextBuffer找到该类型的guid:

        Guid langId;
        vsTextBuffer.GetLanguageServiceID(out langId);

这给了我正确的指导,所以当用我的tsql languange服务取代时,它按预期工作。如果有人需要这些指导,可以找到他们 HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \微软\ VisualStudio的\ 10.0 \语言 (取决于VS安装)。

最后,这是我用来映射这些guid的辅助类:

    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");
        }
    }