【问题标题】:Syntax Highlight doesn't work for IVsInvisibleEditor语法高亮不适用于 IVsInvisibleEditor
【发布时间】:2015-10-04 19:03:28
【问题描述】:

我创建了一个 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# 文件,则会显示高亮显示(并且 intelisense 也有效),但如果我显示一个 sql 文件,那么我再一次没有语法高亮显示。现在,我进一步调查并意识到也许我应该在文档上附加一个语言服务,所以我使用以下代码来实现:

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

瞧,它有效,现在语法高亮也适用于 sql 文件,但现在我有另一个问题,sql 文件的多视图不起作用。例如,如果我有一个文件 MyQuery.sql 并且我用隐形编辑器打开它,它将被打开,语法将显示并且一切都按预期工作,但是现在,如果我尝试打开同一个文件(而隐形编辑器是仍然打开)然后我收到以下消息:

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

【问题讨论】:

    标签: c# visual-studio mef


    【解决方案1】:

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

    在创建 InvisibleEditor 时,很多事情都发生在“下面”,应该设置的一件事也是特定 ITextBuffer 的 ContentType。当使用sql文件(作为名字参数传递给RegisterInvisibleEditor方法)时,ContentType设置为纯文本(但对于csharp文件,它设置为CSharp ContentType),这显然是错误的,但是,调用:

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

    应该解决这个问题,设置语言服务将设置正确的 ContentType,但由于某种原因,在我的情况下这不起作用。经过一些调试,我发现 ContentType 在解决方案资源管理器中通过 dbl click 打开时,与预期的不同。它是“Sql Server Tools”ContentType 而不是“T-SQL90”,所以我尝试使用 IVsTextBuffer 查找该类型的 guid:

            Guid langId;
            vsTextBuffer.GetLanguageServiceID(out langId);
    

    这给了我正确的 guid,所以当替换为我的 tsql 语言服务时,它按预期工作。如果有人需要这些指南,可以在以下位置找到它们 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Languages (取决于 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");
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 2019-02-22
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多