Skip to content

Conversation

@RikkiGibson
Copy link
Member

Closes #81252 (second half of the change)

@dibarbet for review

@RikkiGibson RikkiGibson requested a review from a team as a code owner November 19, 2025 04:45
await _workspaceFactory.MiscellaneousFilesWorkspaceProjectFactory.ApplyChangeToWorkspaceAsync(workspace =>
{
workspace.OnProjectAdded(forkedProjectInfo);
}, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

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

What are the semantics of cancellation here? I definitely don't know what the intent is, or if it is ok that workspace mutation ops may not happen. @dibarbet what the general intuition here?

Copy link
Member

Choose a reason for hiding this comment

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

This cancellation token here would be cancelled if the request gets cancelled by the client. Assuming that cancelling the ApplyChangeToWorkspaceAsync doesn't leave the workspace in an intermediate state, a cancellation here is fine. We won't add the project to the workspace, and that is totally fine. If another call comes in later asking about this document, we'll get here again and try and add it to the workspace.

That applies to AddDocumentToPrimordialProject_NoLockAsync as well. For CreatePrimordialProjectAndAddDocument_NoLock, that is not passed a token as it initiates a project loading operation behind the scenes which should not be cancelled even if the request itself is cancelled, as we'll re-use it for other requests.

await _workspaceFactory.MiscellaneousFilesWorkspaceProjectFactory.ApplyChangeToWorkspaceAsync(workspace =>
{
workspace.OnProjectAdded(forkedProjectInfo);
}, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

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

This cancellation token here would be cancelled if the request gets cancelled by the client. Assuming that cancelling the ApplyChangeToWorkspaceAsync doesn't leave the workspace in an intermediate state, a cancellation here is fine. We won't add the project to the workspace, and that is totally fine. If another call comes in later asking about this document, we'll get here again and try and add it to the workspace.

That applies to AddDocumentToPrimordialProject_NoLockAsync as well. For CreatePrimordialProjectAndAddDocument_NoLock, that is not passed a token as it initiates a project loading operation behind the scenes which should not be cancelled even if the request itself is cancelled, as we'll re-use it for other requests.

assemblyName: canonicalProject.AssemblyName,
language: canonicalProject.Language,
compilationOutputInfo: default,
checksumAlgorithm: SourceHashAlgorithm.Sha1,
Copy link
Member

Choose a reason for hiding this comment

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

should we default to something other than sha1 here? or are we restricted to sha1

Copy link
Member Author

Choose a reason for hiding this comment

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

This was extracted from the helper CreateMiscellaneousProjectInfoForDocument. I think this is likely used as part of the ecma-335 carveout.

DocumentInfo.Create(
DocumentId.CreateNewId(forkedProjectId),
name: Path.GetFileName(documentPath) ?? "",
loader: TextLoader.From(TextAndVersion.Create(await document.GetTextAsync(cancellationToken).ConfigureAwait(false), VersionStamp.Create())),
Copy link
Member

Choose a reason for hiding this comment

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

is there a way to avoid realizing the text here? e.g. can we take the loader from the existing document?

Copy link
Member Author

Choose a reason for hiding this comment

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

Possibly, but I didn't see the API for doing that on the document.

{
// TODO: replace this method and the call site in LspWorkspaceManager,
// with a mechanism for "updating workspace state if needed" based on changes to a document.
// Perhaps this could be based on actually listening for changes to particular documents, rather than whenever an LSP request related to a document comes in.
Copy link
Member

Choose a reason for hiding this comment

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

will have to think about this. We don't want to handle it inside the lsp text change notification itself as that intentionally does as little work as possible. It could be done as an async handling triggered by lsp text changes - but would have to handle LSP requests only being eventually consistent in terms of which project its in.

but definitely space to refactor this to make it more clear how transitions happen.

Copy link
Member Author

Choose a reason for hiding this comment

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

Eventually consistent seems consistent, no pun intended, with how document state works in general. DTBs take time and we will give you a different answer if you ask again later.

Here, we could theoretically see a change and fire off some async request to check the syntax and update project HasAllInformation state accordingly. And a future request will see the new value of that. I think that's ok.

Copy link
Member Author

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

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

Currently working on addressing a test failure.

@RikkiGibson
Copy link
Member Author

Going to extract out the impl change related to <Features>FileBasedProgram</Features> and #: errors, and record the current state in the test.

@RikkiGibson RikkiGibson requested a review from dibarbet November 19, 2025 23:04
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.

Do not restore loose files which lack file-based app directives

3 participants