Skip to content

*** WIP: Update roslyn package references to a newer version.#11901

Closed
ToddGrun wants to merge 12 commits intodotnet:mainfrom
ToddGrun:dev/toddgrun/UpdateRoslynPackageReferences
Closed

*** WIP: Update roslyn package references to a newer version.#11901
ToddGrun wants to merge 12 commits intodotnet:mainfrom
ToddGrun:dev/toddgrun/UpdateRoslynPackageReferences

Conversation

@ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented May 30, 2025

This is in anticipation of un-reverting a change I made in roslyn (dotnet/roslyn#78165). That change will need a coordinated Roslyn/Razor insertion, thus this PR attempts to move razor forward to current tip of roslyn before attempting that change.

There were two recent changes to roslyn that required changes in razor as part of this update:

  1. The Uri => DocumentUri change. This is the vast majority of changes in this PR.
  2. The EditorFeatures.WPF removal.

Starting as a draft PR as I'd like to get ci test results (with something I want to try out in a later commit once tests pass)

This is in anticipation of a change I made (dotnet/roslyn#78165) that was reverted and will need a coordinated Roslyn/Razor insertion.

There were two recent changes to roslyn that required changes in razor as part of this update:

1) The Uri => DocumentUri change. This is the *vast* majority of changes in this PR.
2) The EditorFeatures.WPF removal.
if (initializeParams.WorkspaceFolders is [var firstFolder, ..])
{
return firstFolder.Uri.GetAbsoluteOrUNCPath();
return firstFolder.DocumentUri.GetRequiredParsedUri().GetAbsoluteOrUNCPath();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

GetAbsoluteOrUNCPath

Any place that required this now calls it via the result of DocumentUri.GetRequiredParsedUri

// ever changes, we'll need to update this code to account for it (i.e., take into account
// focus location URIs).
Debug.Assert(location.Uri == documentContext.Uri);
// TODO(toddgrun): switch back to == when roslyn implementation of DocumentUri.operator== is available on ci
Copy link
Contributor Author

@ToddGrun ToddGrun May 30, 2025

Choose a reason for hiding this comment

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

// TODO(toddgrun): switch back to == when roslyn implementation of DocumentUri.operator== is available on ci

There were five places I found where I put this comment and switched the code from using operator== to calling Equals. I just added the operator== implementation to the DocumentUri class in roslyn yesterday, so it can't be used until:

  1. Razor updates to a roslyn package that includes that
  2. (I think) The ci has a roslyn installed that has that.

I'd love clarity on 2) as it seems like that could be a while down the road.

Copy link
Member

Choose a reason for hiding this comment

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

Number 2 is correct. Since we don't ship the Razor EA, we have to wait for any changes to it to be inserted into VS main. That normally doesn't take too long though. This is different to Roslyn where if you sometimes have to wait for something to be in a public preview, we only need to wait for main because our integration tests run on main, and we assume all team members work on VS main/IntPreview.

{
[JsonPropertyName("uri")]
public required Uri Uri { get; set; }
[JsonConverter(typeof(DocumentUriConverter))]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

[JsonConverter(typeof(DocumentUriConverter))]

Matches how Roslyn marks serializable properties of this type.


protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SignatureHelpParams request)
=> new RazorTextDocumentIdentifier(request.TextDocument.Uri, (request.TextDocument as VSTextDocumentIdentifier)?.ProjectContext?.Id);
=> new RazorTextDocumentIdentifier(request.TextDocument.DocumentUri.GetRequiredParsedUri(), (request.TextDocument as VSTextDocumentIdentifier)?.ProjectContext?.Id);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

RazorTextDocumentIdentifier

This is defined in the roslyn ea layer, so not something that can be changed in this PR.

Make GetAbsoluteOrUNCPath callable off both Uri and DocumentUri
<VSIXSourceItem Include="$(OutputPath)Microsoft.CodeAnalysis.CSharp.Workspaces.dll" />
<VSIXSourceItem Include="$(OutputPath)Microsoft.CodeAnalysis.EditorFeatures.dll" />
<VSIXSourceItem Include="$(OutputPath)Microsoft.CodeAnalysis.EditorFeatures.Text.dll" />
<VSIXSourceItem Include="$(OutputPath)Microsoft.CodeAnalysis.EditorFeatures.Wpf.dll" />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This assembly no longer exists

2) Revert a test back to it's original behavior
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == '$(NetFxVS)'">
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.EditorFeatures" />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

EditorFeature packages are only published for netfx, not for net8 or net9

ImmutableHashSet<Type>.Empty,
ImmutableHashSet<Type>.Empty);

#if NETFRAMEWORK
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This catalog is only valid for netfx

ToddGrun added 2 commits May 30, 2025 17:00
2) Changed tests back to using RootPath
3) Cleanup / spelling
@ToddGrun ToddGrun requested a review from dibarbet May 31, 2025 01:27
Copy link
Member

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

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

This mostly LGTM, though see my comment about whether it perhaps makes changes a little too deeply. Wasn't clear from your comments whether you're planning another Roslyn change before opening this properly, but let me know if/when you want a proper review with a green tick.

<Dependency Name="Microsoft.CodeAnalysis.Analyzers" Version="3.12.0-beta1.25230.6">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>ded867328249b5a9b9e6e29e3f07abc19111f5d1</Sha>
<Sha>392fbb66a16ca3d34abdfa93cc5a3717f447d25e</Sha>
Copy link
Member

Choose a reason for hiding this comment

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

This one always trips me up too, it builds from the same commit, but as a different version, so its easy to accidentally update the sha without bumping the package if you just find-and-replace (which, to be clear, is exactly what I do too 😁)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Argh, find and replace got me again!

Comment on lines +23 to +26
if (uri is null)
{
throw new ArgumentNullException(nameof(uri));
}
Copy link
Member

Choose a reason for hiding this comment

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

Is this necessary in a nullable annotated file? If so, we have an ArgHelper.ThrowIfNull helper method

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching to ArgHelper. Lots of callers, didn't want to verify that they all are coming from nullable annotated contexts, so I kept it the same as the other method's check.

public static bool TryGetGeneratedDocument(
this RazorCodeDocument codeDocument,
Uri generatedDocumentUri,
DocumentUri generatedDocumentUri,
Copy link
Member

Choose a reason for hiding this comment

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

It's not necessarily a huge problem, but this is a good example of a thought I'd had a few times looking at the changes: Are we going a little bit too far with them?

The idea is to get Uri parsing out of LSP message deserialization, so moving away from Uri to DocumentUri for everything that is at the boundary makes sense. This feels like a step further, where we're essentially saying that we'll be able to possibly produce a RazorCodeDocument even if a Uri is not valid, and that doesn't feel right. It feels like for this API, and for others at a similar level, we are probably fine to just expect the LSP message handlers to pass in the parsed Uri, so that if there is invalid data coming in it's validated relatively early (just not as early as deserialization).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a very fair point, this did expand to be a lot more than I had originally thought it would. I'll take a look to see where it can be reigned in a bit, but if you can point out the locations where you think it's gone a bit too far, that would be helpful.

Copy link
Member

@dibarbet dibarbet Jun 2, 2025

Choose a reason for hiding this comment

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

even if a Uri is not valid

Wanted to make a clarification that issues here are most often caused by actual valid URIs that System.Uri barfs on. So ultimately that means these URIs are not parse-able (unless we write our own parser).

Generally it is up to you if parsing the URI is a requirement for running your handlers. For Roslyn it isn't a hard requirement (they'll become misc files)

Copy link
Member

Choose a reason for hiding this comment

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

Oooh thats a good distinction I missed/forgot. We definitely use the filename of the Uri to find/create various documents, so I think technically we do need things to be parsable. Probably a good rule to use though (ie, IFilePathService is the thing that does that work, so it should take Uri and let that inform the changes). Seems like we could go either way though really, and things would be pretty viral either way. Doesn't feel like something to nail down in this PR, but we can pivot later as we work out what works best.

}

if (!_documentContextFactory.TryCreate(mapping.TextDocument.Uri, out var documentContext))
if (!_documentContextFactory.TryCreate(mapping.TextDocument.DocumentUri.GetRequiredParsedUri(), out var documentContext))
Copy link
Member

Choose a reason for hiding this comment

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

I wasn't expecting the DocumentUri change to be so viral, but this appears to be one of the reasons why - directly passing in just the URI type to helpers such as these.

Would it be reasonable to have helpers like this take in for example a TextDocumentIdentifier instead? I think that is one reason the Roslyn side changes were a bit easier

(to be clear, not suggesting it happens in this PR, but as a general improvement).

@ToddGrun
Copy link
Contributor Author

ToddGrun commented Jun 3, 2025

Unit tests seem to be a bit flaky now, they seem to pass on my dev machine, so not sure what's going on and the test logs aren't pointing me to the culprit. Will take a look again tomorrow with fresh eyes.

@davidwengier
Copy link
Member

I had some flakiness on one of my PRs tonight, with complement unrelated changes. Probably can just re-run.

@ToddGrun
Copy link
Contributor Author

David was able to get this to work in #11949. Closing this one out.

@ToddGrun ToddGrun closed this Jun 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants