Right now I have implemented my own custom editor and is configured so that when I open up any .cs file, VS will display the file using my editor. However, the text is bland and has no coloring to it. Therefore, I am trying to make the file appear as a .cs file in the traditional VS code editor. I believe the way to achieve this is by setting the language service for the text buffer. The result of the SetLanguageServiceID is 0 so it is called correctly but I am not sure why this is not working. Here is my implemented editor factory:
using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using System.IO;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TextManager.Interop;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.ComponentModelHost;
namespace CustomTextEditorFactory
{
[Guid("F86E3EAF-07DF-40CD-8E4A-6C01BA7E2BAF")]
internal class CustomEditorFactory : IVsEditorFactory
{
private ServiceProvider _serviceProvider;
private readonly Package _package;
public CustomEditorFactory(Package package)
{
_package = package ?? throw new ArgumentNullException(nameof(package));
}
public int SetSite(IOleServiceProvider psp)
{
_serviceProvider = new ServiceProvider(psp);
return VSConstants.S_OK;
}
public object GetService(Type serviceType)
{
return _serviceProvider.GetService(serviceType);
}
public int MapLogicalView(ref Guid rguidLogicalView, out string pbstrPhysicalView)
{
pbstrPhysicalView = null;
if (rguidLogicalView == VSConstants.LOGVIEWID_Primary ||
rguidLogicalView == VSConstants.LOGVIEWID_Code)
{
return VSConstants.S_OK;
}
return VSConstants.E_NOTIMPL;
}
public int Close()
{
_serviceProvider?.Dispose();
return VSConstants.S_OK;
}
public int CreateEditorInstance(
uint grfCreateDoc,
string pszMkDocument,
string pszPhysicalView,
IVsHierarchy pvHier,
uint itemid,
IntPtr punkDocDataExisting,
out IntPtr ppunkDocView,
out IntPtr ppunkDocData,
out string pbstrEditorCaption,
out Guid pguidCmdUI,
out int pgrfCDW)
{
ppunkDocView = IntPtr.Zero;
ppunkDocData = IntPtr.Zero;
pbstrEditorCaption = null;
pguidCmdUI = Guid.Empty;
pgrfCDW = 0;
// Found some sort of factory that is able to create a VsTextBuffer object
IComponentModel compMod = GetService(typeof(SComponentModel)) as IComponentModel;
IVsEditorAdaptersFactoryService adapterFactory = compMod.GetService<IVsEditorAdaptersFactoryService>();
IVsTextBuffer textBuffer = adapterFactory.CreateVsTextBufferAdapter(GetService(typeof(IOleServiceProvider)) as IOleServiceProvider);
// add file content to the text buffer
string fileContent = File.ReadAllText(pszMkDocument);
textBuffer.InitializeContent(fileContent, fileContent.Length);
// set the language service for the text buffer for syntax highlighting
Guid languageServiceGuid = new Guid("{694DD9B6-B865-4C5B-AD85-86356E9C88DC}");
int result = textBuffer.SetLanguageServiceID(ref languageServiceGuid);
// CodeWindow object contains IVsTextLines for its text buffer so cast the buffer as such
IVsTextLines textLines = (IVsTextLines)textBuffer;
Type codeWindowType = typeof(IVsCodeWindow);
Guid riid = codeWindowType.GUID;
Guid clsid = typeof(VsCodeWindowClass).GUID;
IVsCodeWindow codeWindow = (IVsCodeWindow)_package.CreateInstance(ref clsid, ref riid, codeWindowType);
codeWindow.SetBuffer(textLines);
// Obtain the primary view managed by the CodeWindow object (we set the buffer but not the text view)
IVsTextView primaryView;
codeWindow.GetPrimaryView(out primaryView);
// set output parameters for VS
ppunkDocView = Marshal.GetIUnknownForObject(codeWindow);
ppunkDocData = Marshal.GetIUnknownForObject(textLines);
pbstrEditorCaption = "Custom!!!";
pguidCmdUI = Guid.Empty;
pgrfCDW = 0;
return VSConstants.S_OK;
}
}
}
And here is my package file (this is a VSIX project)
using Microsoft.VisualStudio.Shell;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Task = System.Threading.Tasks.Task;
namespace CustomTextEditorFactory
{
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[ProvideEditorExtension(typeof(CustomEditorFactory), ".cs", 700)]
[Guid(RenderCustomTextEditorPackage.PackageGuidString)]
public sealed class RenderCustomTextEditorPackage : AsyncPackage
{
public const string PackageGuidString = "AF177B7B-8E7C-4F93-B0B6-AC5670B94080";
#region Package Members
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
// Register the editor factory
this.RegisterEditorFactory(new CustomEditorFactory(this));
}
#endregion
}
}
I have tried setting the language service of textLines itself but that did not change anything. I also have tried setting the language service before and after content initialization.