Skip to content

Allow Razor files to be additional documents in a misc files project #78267

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

Merged
Merged
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 @@ -27,7 +27,11 @@ internal static ProjectInfo CreateMiscellaneousProjectInfoForDocument(
var fileExtension = PathUtilities.GetExtension(filePath);
var fileName = PathUtilities.GetFileName(filePath);

var languageServices = services.GetLanguageServices(languageInformation.LanguageName);
// For Razor files we need to override the language name to C# as thats what code is generated
var isRazor = languageInformation.LanguageName == "Razor";
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 not have a constant for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not one accessible in this layer.

var languageName = isRazor ? LanguageNames.CSharp : languageInformation.LanguageName;

var languageServices = services.GetLanguageServices(languageName);
var compilationOptions = languageServices.GetService<ICompilationFactoryService>()?.GetDefaultCompilationOptions();

// Use latest language version which is more permissive, as we cannot find out language version of the project which the file belongs to
Expand Down Expand Up @@ -63,15 +67,16 @@ internal static ProjectInfo CreateMiscellaneousProjectInfoForDocument(
version: VersionStamp.Create(),
name: FeaturesResources.Miscellaneous_Files,
assemblyName: assemblyName,
language: languageInformation.LanguageName,
language: languageName,
compilationOutputInfo: default,
checksumAlgorithm: checksumAlgorithm,
// Miscellaneous files projects are never fully loaded since, by definition, it won't know
// what the full set of information is except when the file is script code.
hasAllInformation: sourceCodeKind == SourceCodeKind.Script),
compilationOptions: compilationOptions,
parseOptions: parseOptions,
documents: [documentInfo],
documents: isRazor ? null : [documentInfo],
additionalDocuments: isRazor ? [documentInfo] : null,
metadataReferences: metadataReferences);

return projectInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal sealed class LspMiscellaneousFilesWorkspace(ILspServices lspServices, I
/// Calls to this method and <see cref="TryRemoveMiscellaneousDocument(Uri, bool)"/> are made
/// from LSP text sync request handling which do not run concurrently.
/// </summary>
public Document? AddMiscellaneousDocument(Uri uri, SourceText documentText, string languageId, ILspLogger logger)
public TextDocument? AddMiscellaneousDocument(Uri uri, SourceText documentText, string languageId, ILspLogger logger)
{
var documentFilePath = ProtocolConversions.GetDocumentFilePathFromUri(uri);

Expand All @@ -63,6 +63,12 @@ internal sealed class LspMiscellaneousFilesWorkspace(ILspServices lspServices, I
this, documentFilePath, sourceTextLoader, languageInformation, documentText.ChecksumAlgorithm, Services.SolutionServices, []);
OnProjectAdded(projectInfo);

if (languageInformation.LanguageName == "Razor")
{
var docId = projectInfo.AdditionalDocuments.Single().Id;
return CurrentSolution.GetRequiredAdditionalDocument(docId);
}

var id = projectInfo.Documents.Single().Id;
return CurrentSolution.GetRequiredDocument(id);
Comment on lines 72 to 73
Copy link
Member

Choose a reason for hiding this comment

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

I kinda wish this was an else block so it was more visually clear it's the same logic, but don't touch it unless you have to touch the PR for some other reason.

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,34 @@ void M()
Assert.Null(GetMiscellaneousDocument(testLspServer));
}

[Theory, CombinatorialData]
public async Task TestLooseFile_RazorFile(bool mutatingLspWorkspace)
{
var source = "<div></div>";

// Create a server that supports LSP misc files and verify no misc files present.
await using var testLspServer = await CreateTestLspServerAsync(string.Empty, mutatingLspWorkspace, new InitializationOptions { ServerKind = WellKnownLspServerKinds.CSharpVisualBasicLspServer });
Assert.Null(GetMiscellaneousDocument(testLspServer));
Assert.Null(GetMiscellaneousAdditionalDocument(testLspServer));

// Open an empty loose file and make a request to verify it gets added to the misc workspace.
var looseFileUri = ProtocolConversions.CreateAbsoluteUri(@"C:\SomeFile.razor");
await testLspServer.OpenDocumentAsync(looseFileUri, source).ConfigureAwait(false);

// Trigger a request and assert we got a file in the misc workspace.
await AssertFileInMiscWorkspaceAsync(testLspServer, looseFileUri).ConfigureAwait(false);
Assert.Null(GetMiscellaneousDocument(testLspServer));
Assert.NotNull(GetMiscellaneousAdditionalDocument(testLspServer));

// Trigger another request and assert we got a file in the misc workspace.
await AssertFileInMiscWorkspaceAsync(testLspServer, looseFileUri).ConfigureAwait(false);
Assert.NotNull(GetMiscellaneousAdditionalDocument(testLspServer));

await testLspServer.CloseDocumentAsync(looseFileUri).ConfigureAwait(false);
Assert.Null(GetMiscellaneousDocument(testLspServer));
Assert.Null(GetMiscellaneousAdditionalDocument(testLspServer));
}

[Theory, CombinatorialData]
public async Task TestLooseFile_RequestedTwiceAndClosed(bool mutatingLspWorkspace)
{
Expand Down Expand Up @@ -306,7 +334,12 @@ private static async Task AssertFileInMainWorkspaceAsync(TestLspServer testLspSe

private static Document? GetMiscellaneousDocument(TestLspServer testLspServer)
{
return testLspServer.GetManagerAccessor().GetLspMiscellaneousFilesWorkspace()!.CurrentSolution.Projects.SingleOrDefault()?.Documents.Single();
return testLspServer.GetManagerAccessor().GetLspMiscellaneousFilesWorkspace()!.CurrentSolution.Projects.SingleOrDefault()?.Documents.SingleOrDefault();
}

private static TextDocument? GetMiscellaneousAdditionalDocument(TestLspServer testLspServer)
{
return testLspServer.GetManagerAccessor().GetLspMiscellaneousFilesWorkspace()!.CurrentSolution.Projects.SingleOrDefault()?.AdditionalDocuments.SingleOrDefault();
}

private static async Task<LSP.Hover> RunGetHoverAsync(TestLspServer testLspServer, LSP.Location caret)
Expand Down
Loading