-
Hello! I am VSIXer. In my VSIX, I have In this document, I see the path to the file, but this path is relative. I don't know exactly, but I susprect it is the reason why I cannot open this document in VS editor. How to open this file in Visual Studio from VSIX code? A I understand that this repo is not the best place to ask VS-related questions, but there is no place better at all. Any tips would be appreciated a lot. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 2 replies
-
I would start by reviewing #58363, specifically the part where it opens source generated files in the editor. It might reveal an API or pattern which could be used by another tool. |
Beta Was this translation helpful? Give feedback.
-
@sharwell Thanks! Your PR helped me to have a progress. Could I ask you few questions please? First questionI almost replicate (in primitive way) the logic of opening generated files. But, I cannot (and don't understand where to go) how to attach that file to the project to have reference analysis etc etc. "my frame" is at the right. Please notice between Could you guide me where am I wrong? My code is var logicalView = VSConstants.LOGVIEWID_Code;
if (!OpenDocument(logicalView, out IVsWindowFrame? frame))
{
return;
}
// We'll override the window frame and never show it as dirty, even if there's an underlying edit
frame!.SetProperty((int)__VSFPROPID2.VSFPROPID_OverrideDirtyState, false);
frame!.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideCaption, "[qq generated caption]");
frame!.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideToolTip, "[qq generated tooltip]");
//add an info bar (gold bar) to the opened document
if (ErrorHandler.Succeeded(
frame.GetProperty((int)__VSFPROPID7.VSFPROPID_InfoBarHost, out var infoBarHostObject)
)
&& infoBarHostObject is IVsInfoBarHost infoBarHost
)
{
var infoBar = new InfoBarModel(
$"This file is auto-generated by the source generator and cannot be edited.",
default,
isCloseButtonVisible: false
);
var infoBarUI = _infoBarFactory.CreateInfoBar(infoBar);
infoBarHost.AddInfoBar(infoBarUI);
}
frame!.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out object docData);
if (!GetVsTextBuffer(docData, out VsTextBuffer? vsTextBuffer2))
{
return;
}
var vsTextBuffer = vsTextBuffer2 as IVsTextBuffer;
var editorAdapterFactoryService = _componentModel.GetService<IVsEditorAdaptersFactoryService>();
var textBuffer = editorAdapterFactoryService.GetDataBuffer(vsTextBuffer);
using (var edit = textBuffer.CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null))
{
// TODO: make the edit in some nicer way than creating a massive string
edit.Replace(startPosition: 0, textBuffer.CurrentSnapshot.Length, "a some source text (a text from screenshot)");
edit.Apply();
}
//make the document read only
vsTextBuffer.SetStateFlags(1); Second questionAs I was progressing I had a felling that copypasting is the wrong way to deal with it. May be it is possible to reuse some components from Roslyn dlls? May be Anyway, thank you for your tip, it was helpful! |
Beta Was this translation helpful? Give feedback.
-
additonal piece of code which is relevant: private bool OpenDocument(
Guid logicalView,
out IVsWindowFrame? frame
)
{
if (_openDoc is null)
{
frame = null;
return false;
}
if (ErrorHandler.Failed(
_openDoc.OpenDocumentViaProject(
_documentFullPath,
ref logicalView,
out IServiceProvider _,
out IVsUIHierarchy hier,
out var itemId,
out frame)
) ||
frame == null)
{
return false;
}
return true;
} |
Beta Was this translation helpful? Give feedback.
-
@sharwell Thank you again. I found a way to reuse Roslyn functionality via reflection. Looks like it works. I understand that this approach is fragile, and I will file an issue to "opening" navigation logic for Roslyn-users. For those who find this topic later, here is the code which able to open source generated files as Roslyn does it: public async Task<bool> OpenNavigateViewRoslynInternalsAsync(
DocumentId documentId,
int position,
int length
)
{
var workspace = (Workspace)_componentModel.GetService<VisualStudioWorkspace>();
var r = await workspace.CurrentSolution.GetSourceGeneratedDocumentAsync(documentId, CancellationToken.None);
var project = workspace.CurrentSolution.GetProject(documentId.ProjectId);
var sgDocument = (await project.GetSourceGeneratedDocumentsAsync(CancellationToken.None)).First(d => d.Id.Equals(documentId));
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(CancellationToken.None);
var extensions = _componentModel.GetExtensions<Microsoft.CodeAnalysis.Host.IWorkspaceService>().ToList();
var visualStudioDocumentNavigationService = extensions.Find(s => s.GetType().Name == "VisualStudioDocumentNavigationService");
var visualStudioDocumentNavigationServiceType = visualStudioDocumentNavigationService.GetType();
var getLocationForSpanAsyncMethod = visualStudioDocumentNavigationServiceType.GetMethod("GetLocationForSpanAsync");
var getLocationForSpanAsyncTask = (Task)getLocationForSpanAsyncMethod.Invoke(
visualStudioDocumentNavigationService,
new object[]
{
workspace,
sgDocument.Id,
new Microsoft.CodeAnalysis.Text.TextSpan(
position,
0 //length
),
true, //allowInvalidSpan
CancellationToken.None
}
);
await getLocationForSpanAsyncTask;
var navigableLocation = getLocationForSpanAsyncTask.GetType().GetProperty("Result").GetValue(getLocationForSpanAsyncTask);
var navigateOptionsType = navigableLocation.GetType().Assembly.GetType("Microsoft.CodeAnalysis.Navigation.NavigationOptions");
var navigateOptions = navigateOptionsType.GetConstructor(new Type[0]).Invoke(new object[0]);
var navigateToAsyncMethod = navigableLocation.GetType().GetMethod("NavigateToAsync");
var navigateToAsyncMethodTask = (Task)navigateToAsyncMethod.Invoke(
navigableLocation,
new object[]
{
navigateOptions,
CancellationToken.None
});
await navigateToAsyncMethodTask;
var navigateToAsyncMethodSuccess = (bool)navigateToAsyncMethodTask.GetType().GetProperty("Result").GetValue(navigateToAsyncMethodTask);
return navigateToAsyncMethodSuccess;
} |
Beta Was this translation helpful? Give feedback.
I would start by reviewing #58363, specifically the part where it opens source generated files in the editor. It might reveal an API or pattern which could be used by another tool.