Skip to content

Extract out an interface for our LSP miscellaneous files workspace #78401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

jasonmalinowski
Copy link
Member

This will allow us to substitute in a different implementation in our real server.

This will allow us to substitute in a different implementation in our
real server.
@jasonmalinowski jasonmalinowski self-assigned this May 1, 2025
@jasonmalinowski jasonmalinowski requested a review from a team as a code owner May 1, 2025 20:01
@ghost ghost added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels May 1, 2025
{
TextDocument? AddMiscellaneousDocument(Uri uri, SourceText documentText, string languageId, ILspLogger logger);
void TryRemoveMiscellaneousDocument(Uri uri, bool removeFromMetadataWorkspace);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

up to you, but i wouldn't mind docs.

Also, being an ILspWorkspace and an ILspService seems odd. I don't really understand the role this plays as both those types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, as an interface, do we expect multiple impls of this? i'd love an explanation of that. thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the misc workspace is an ILspService currently, that's why LspWorkspaceManagerFactory can call GetService<LspMiscellaneousFilesWorkspace>().

The plan is for FileBasedProgramWorkspace to also implement the new interface. Most likely we are going to have an opt-out switch for file-based programs support, which simply makes it so the "existing" misc files workspace gets used instead of the "new" FileBasedProgramWorkspace.


internal interface ILspMiscellaneousFilesWorkspaceProvider : ILspService
{
ILspMiscellaneousFilesWorkspace CreateLspMiscellaneousFilesWorkspace(ILspServices lspServices, HostServices hostServices);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i understand this 'provider' being an ILspService. but if it makes ILspXXXWorkspaces, is the ILspXXXWorkspace an ILspService itself? Seems confusing to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would make more sense for the LspWorkspaceManagerFactory to simply ask for a ILspMiscellaneousFilesWorkspaceProvider, rather than having to register the workspace as its own service and have the ManagerFactory ask for that.

@CyrusNajmabadi
Copy link
Member

in a different implementation in our real server.

Wouldn't mind explanation (either in PR, in docs, or offline) of what the different impl woudl be. And what constitutes "our real server" :)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signing off as the code seems fine (albeit off with the duality of workspace/service). Would love a brief convo to better understand what's going on here short/medium/long term.

@dotnet dotnet deleted a comment from azure-pipelines bot May 2, 2025
@dotnet dotnet deleted a comment from azure-pipelines bot May 2, 2025
@dotnet dotnet deleted a comment from azure-pipelines bot May 2, 2025
@jasonmalinowski jasonmalinowski enabled auto-merge May 2, 2025 23:42
@jasonmalinowski jasonmalinowski removed the untriaged Issues and PRs which have not yet been triaged by a lead label May 3, 2025
This coupling can cause challenges, so the easy change is to add a
Workspace property which provides the workspace. This renames the
ILspMiscellaneousFilesWorkspace interface to add a Provider suffix,
and the existing Provider now becomes a ProviderFactory.
@jasonmalinowski jasonmalinowski force-pushed the extract-lsp-miscellaneous-files-interface branch from 125efcc to aa6439d Compare May 5, 2025 18:27
@jasonmalinowski jasonmalinowski merged commit 9cce728 into dotnet:main May 5, 2025
24 of 25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone May 5, 2025
/// </summary>
Workspace Workspace { get; }
TextDocument? AddMiscellaneousDocument(Uri uri, SourceText documentText, string languageId, ILspLogger logger);
void TryRemoveMiscellaneousDocument(Uri uri, bool removeFromMetadataWorkspace);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc'ing both of the above methods would be good. for example, why does AddMiscDoc return nullable?

Why is it TryRemoveMiscDoc? Odd that it doesn't return a boolean.

[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class LspMiscellaneousFilesWorkspaceProvider(IMetadataAsSourceFileService metadataAsSourceFileService) : ILspService
internal sealed class LspMiscellaneousFilesWorkspaceProvider(ILspServices lspServices, IMetadataAsSourceFileService metadataAsSourceFileService, HostServices hostServices)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. when PC is this long, consider wrapping.

[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class LspMiscellaneousFilesWorkspaceProvider(IMetadataAsSourceFileService metadataAsSourceFileService) : ILspService
internal sealed class LspMiscellaneousFilesWorkspaceProvider(ILspServices lspServices, IMetadataAsSourceFileService metadataAsSourceFileService, HostServices hostServices)
: Workspace(hostServices, WorkspaceKind.MiscellaneousFiles), ILspMiscellaneousFilesWorkspaceProvider, ILspWorkspace
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

being a misc workspace provider and a workspace at the same time is breaking my brain.

public bool SupportsMutation => true;

// For this implementation, it's easiest to just have it inherit from Workspace, so we'll just return this.
public Workspace Workspace => this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still broken :)

var container = new StaticSourceTextContainer(documentText);
if (metadataAsSourceFileService.TryAddDocumentToWorkspace(documentFilePath, container, out var documentId))
{
var metadataWorkspace = metadataAsSourceFileService.TryGetWorkspace();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe have the TryAddDocToWorkspace return the worskpace as well? to avoid this?


var projectInfo = MiscellaneousFileUtilities.CreateMiscellaneousProjectInfoForDocument(
this, documentFilePath, sourceTextLoader, languageInformation, documentText.ChecksumAlgorithm, Services.SolutionServices, []);
OnProjectAdded(projectInfo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never very clear on locking around all of this work.

var documentFilePath = ProtocolConversions.GetDocumentFilePathFromUri(uri);
if (removeFromMetadataWorkspace && metadataAsSourceFileService.TryRemoveDocumentFromWorkspace(documentFilePath))
{
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like i want to return a value from TryRemoveMiscDoc and have the callers contract call on it.

}

// Also remove the project - we always create a new project for each misc file we add
// so it should never have other documents in it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could assert this.


// We'll only ever have a single document matching this URI in the misc solution.
var matchingDocument = CurrentSolution.GetDocumentIds(uri).SingleOrDefault();
if (matchingDocument != null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious when this is null. i don't feel like i ahve a good sense of the invariants we have in this space. feels loosey goosey.

Comment on lines +25 to +27
public ILspMiscellaneousFilesWorkspaceProvider CreateLspMiscellaneousFilesWorkspaceProvider(ILspServices lspServices, HostServices hostServices)
{
return new LspMiscellaneousFilesWorkspaceProvider(lspServices, metadataAsSourceFileService, hostServices);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we expect to have other impls of ILspMiscellaneousFilesWorkspaceProviderFactory?

@CyrusNajmabadi
Copy link
Member

Added a few more comments. But still ok with this going in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants