Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ public async ValueTask TryRemoveMiscellaneousDocumentAsync(DocumentUri uri, bool
var content = await _projectXmlProvider.GetVirtualProjectContentAsync(documentPath, _logger, cancellationToken);
if (content is not var (virtualProjectContent, diagnostics))
{
// https://github.com/dotnet/roslyn/issues/78618: falling back to this until dotnet run-api is more widely available
_logger.LogInformation($"Failed to obtain virtual project for '{documentPath}' using dotnet run-api. Falling back to directly creating the virtual project.");
_logger.LogError($"Failed to obtain virtual project for '{documentPath}' using dotnet run-api. Falling back to directly creating the virtual project.");
Copy link
Member

Choose a reason for hiding this comment

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

this is still only available in .net10 right, which hasn't fully released? Should this still be a warning?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes...actually, this is kinda annoying, because we probably still want to distinguish "SDK too old" cases, from "run-api is present, but its results were completely messed up". No need to report anything in the "SDK too old" case.

I will have to take a look at how to make that distinction.

virtualProjectContent = VirtualProjectXmlProvider.MakeVirtualProjectContent_DirectFallback(documentPath);
diagnostics = [];
}
Expand Down Expand Up @@ -168,6 +167,7 @@ public async ValueTask TryRemoveMiscellaneousDocumentAsync(DocumentUri uri, bool
ProjectFactory: isFileBasedProgram ? _workspaceFactory.HostProjectFactory : _workspaceFactory.MiscellaneousFilesWorkspaceProjectFactory,
IsMiscellaneousFile: !isFileBasedProgram,
Preferred: buildHostKind,
Actual: buildHostKind);
Actual: buildHostKind,
HasLoadErrors: content is null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,12 @@ private async ValueTask ReloadProjectsAsync(ImmutableSegmentedList<ProjectToLoad
}
}

protected sealed record RemoteProjectLoadResult(RemoteProjectFile ProjectFile, ProjectSystemProjectFactory ProjectFactory, bool IsMiscellaneousFile, BuildHostProcessKind Preferred, BuildHostProcessKind Actual);
/// <param name="HasLoadErrors">
/// Whether there were errors in the process of loading the project file itself.
/// When this is true, we may still want to proceed with design-time build in order to provide partial information about the project.
Copy link
Member

Choose a reason for hiding this comment

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

The semantics described here are a bit reversed of what I'd imagine we would do -- I would have expected 'true' means 'we know there are already errors, no reason to go further'.

Is the easier approach here just to return a set of diagnostics that are concatenated onto the existing things that get reported?

/// When this is false, <see cref="RemoteProjectFile.GetDiagnosticLogItemsAsync"/> also needs to be separately checked, to decide if evaluation was successful.
Copy link
Member

Choose a reason for hiding this comment

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

A couple things

  1. Is it not possible to have GetDiagnosticLogItemsAsync handle this internally?
  2. If we call GetDiagnosticLogItemsAsync when true, will it throw, or will it just no-op if the project failed to load?

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. It may be possible but cumbersome. RemoteProjectFile today just contains an RpcClient and an int handle. It lives in a layer which is downstream from / oblivious to the "virtual project" concept.
  2. GetDiagnosticLogItems is not expected to throw regardless of the value of HasLoadErrors. Which is kinda confusing. But basically I am trying to propagate out the fact that run-api can fail, and even if things "appear to be working" with the fallback virtual project, we may still want to signal to user that something is wrong.

/// </param>
protected sealed record RemoteProjectLoadResult(RemoteProjectFile ProjectFile, ProjectSystemProjectFactory ProjectFactory, bool IsMiscellaneousFile, BuildHostProcessKind Preferred, BuildHostProcessKind Actual, bool HasLoadErrors);

/// <summary>Loads a project in the MSBuild host.</summary>
/// <remarks>Caller needs to catch exceptions to avoid bringing down the project loader queue.</remarks>
Expand Down Expand Up @@ -209,7 +214,7 @@ private async Task<bool> ReloadProjectAsync(ProjectToLoad projectToLoad, ToastEr
return false;
}

(RemoteProjectFile remoteProjectFile, ProjectSystemProjectFactory projectFactory, bool isMiscellaneousFile, BuildHostProcessKind preferredBuildHostKind, BuildHostProcessKind actualBuildHostKind) = remoteProjectLoadResult;
(RemoteProjectFile remoteProjectFile, ProjectSystemProjectFactory projectFactory, bool isMiscellaneousFile, BuildHostProcessKind preferredBuildHostKind, BuildHostProcessKind actualBuildHostKind, bool hasLoadErrors) = remoteProjectLoadResult;
if (preferredBuildHostKind != actualBuildHostKind)
preferredBuildHostKindThatWeDidNotGet = preferredBuildHostKind;

Expand Down Expand Up @@ -289,7 +294,7 @@ private async Task<bool> ReloadProjectAsync(ProjectToLoad projectToLoad, ToastEr
}

diagnosticLogItems = await remoteProjectFile.GetDiagnosticLogItemsAsync(cancellationToken);
if (diagnosticLogItems.Any())
if (hasLoadErrors || diagnosticLogItems.Any())
{
await LogDiagnosticsAsync(diagnosticLogItems);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,6 @@ public async Task OpenProjectsAsync(ImmutableArray<string> projectFilePaths)
var (buildHost, actualBuildHostKind) = await buildHostProcessManager.GetBuildHostWithFallbackAsync(preferredBuildHostKind, projectPath, cancellationToken);

var loadedFile = await buildHost.LoadProjectFileAsync(projectPath, languageName, cancellationToken);
return new RemoteProjectLoadResult(loadedFile, _hostProjectFactory, IsMiscellaneousFile: false, preferredBuildHostKind, actualBuildHostKind);
return new RemoteProjectLoadResult(loadedFile, _hostProjectFactory, IsMiscellaneousFile: false, preferredBuildHostKind, actualBuildHostKind, HasLoadErrors: false);
}
}
Loading