Skip to content

Allow cohosting quick info to show html tag information even when on a taghelper or component tag.#12415

Merged
ToddGrun merged 3 commits intodotnet:mainfrom
ToddGrun:dev/toddgrun/QuickInfoIncludesHtmlDescription
Oct 30, 2025
Merged

Allow cohosting quick info to show html tag information even when on a taghelper or component tag.#12415
ToddGrun merged 3 commits intodotnet:mainfrom
ToddGrun:dev/toddgrun/QuickInfoIncludesHtmlDescription

Conversation

@ToddGrun
Copy link
Contributor

Fixes https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/2556384

This change allows cohosting quick info to call into the html LSP after getting a result from the razor GetHoverAsync call. If both razor and html returned items, then the code merges the results with html items shown above the razor items (as the legacy editor does).

image

…a taghelper or component tag.

Fixes https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/2556384

This change allows cohosting quick info to call into the html LSP after getting a result from the razor GetHoverAsync call. If both razor and html returned items, then the code merges the results with html items shown above the razor items (as the legacy editor does).
@ToddGrun ToddGrun requested a review from a team as a code owner October 30, 2025 02:59
}

return await _requestInvoker.MakeHtmlLspRequestAsync<TextDocumentPositionParams, LspHover>(
var htmlHover = await _requestInvoker.MakeHtmlLspRequestAsync<TextDocumentPositionParams, LspHover>(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

MakeHtmlLspRequestAsync

I'd love some guidance on changing this to not make the html call if we aren't in an html context. It looks like this information isn't at my fingertips, and I noticed some other cohosting calls across to the remote service end up returning a flag indicating the language that is being operated in. Is that the general mechanism suggested to filter work done at this level by language?

Copy link
Member

@davidwengier davidwengier Oct 30, 2025

Choose a reason for hiding this comment

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

Yes, the endpoints run in devenv, and we have no knowledge of the Razor syntax tree or anything that lets us determine what language is at a position there, so we have to jump to OOP to get that info. In this case, I would imagine the OOP call above would change to return a custom type that carries the hover info, and whether or not to call Html and merge the results.

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 what I thought when I asked for guidance. I think the small change I made in commit 2 to the stopHandling determination in the remote process prevents most of the unnecessary html lsp requests.

if (htmlHover != null
&& htmlHover.Range == razorHover.Range
&& razorHover is VSInternalHover razorVsInternalHover
&& razorVsInternalHover.RawContent is ContainerElement razorContainerElement)
Copy link
Member

Choose a reason for hiding this comment

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

This will only be true in VS. In VS Code, We'd have Content that contains markdown. Though since it seems the Html server is returning markdown too, it should be easy enough to combine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Modified VS code path to merge html/razor results with horizontal rule between:

image

Copy link
Member

Choose a reason for hiding this comment

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

What does the full markdown content of this look like? Or what did this look like before your change? That first tag helper line is quite chonky.

Looks like this for me right now:
image

Could just be a bug when we have two tag helpers (in which case, can just log a follow up issue), or perhaps VS Code's markdown is poisoning ours with an unclosed or trailing symbol. Might need to log a bug there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a chunker for me without my changes too:

image

Copy link
Member

Choose a reason for hiding this comment

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

Awesome


await VerifyHoverAsync(code, async (hover, document) =>
// This verifies Hover calls into both csharp and HTML and aggregates their results
const string htmlDescription = "html description";
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 this is worth reviewing after you're made the changes to the OOP service. I would have thought we'd only query html when its likely to be a real html tag, and given all Razor components must start with a capital letter, and no html elements do, I would think that's only in .cshtml files (FileKind.Legacy). So this verification code looks right, but should be in a different test. Realistically the <body> example in your screenshot is the perfect case to validate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for this comment. I could not figure out why my attempts to use taghelpers were not working and the FileKind.Legacy was just the trick I was missing.

@davidwengier
Copy link
Member

Sorry, I guess I broke this when I added mapping for tag helper start tags

2) Have remote service indicate stop handling in C# hovers
3) Make separate test for verifying merged html/razor hovers
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.

My feedback is mostly nits, but I do think this probably makes a few unnecessary LSP requests to Html, in .razor files, which would be nice to remove if you agree.


return Results(csharpHover);
// As there is a C# hover, stop further handling.
return new RemoteResponse<Hover?>(StopHandling: true, Result: csharpHover);
Copy link
Member

Choose a reason for hiding this comment

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

I might be missing it, but I was expecting StopHandling to be used when we product a Razor response at times too. eg, when hovering over <PageTitle> in a .razor file, we don't need to make a Html request. In fact, I can't think of any scenario where we'd want to call the Html server if we're in a .razor file and we were able to produce a hover response ourselves. It's really only MVC that has Razor concepts apply to regular Html elements or attributes.

That check could even be done in the endpoint, by checking the file type in the endpoint (there is a FileTypes.GetFromExtension method or something) and if its a .razor, then any response from OOP means don't call Html.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm probably missing something, but I see the if condition on line 65 hit when hovering over PageTitle, due to the remapping code in GetPositionInfo. Or is there another case you are concerned about that isn't true for line 65?

Copy link
Member

Choose a reason for hiding this comment

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

Ohh of course, because thats actually a C# hover. Okay, cool. You lost the fight over who missed something :P

if (htmlHover != null
&& htmlHover.Range == razorHover.Range
&& razorHover is VSInternalHover razorVsInternalHover
&& razorVsInternalHover.RawContent is ContainerElement razorContainerElement)
Copy link
Member

Choose a reason for hiding this comment

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

What does the full markdown content of this look like? Or what did this look like before your change? That first tag helper line is quite chonky.

Looks like this for me right now:
image

Could just be a bug when we have two tag helpers (in which case, can just log a follow up issue), or perhaps VS Code's markdown is poisoning ours with an unclosed or trailing symbol. Might need to log a bug there.

@ToddGrun
Copy link
Contributor Author

@davidwengier -- I think I did most of your suggestions, let me know if I missed something or there is something else that could be changed.

@davidwengier
Copy link
Member

@ToddGrun Merge at will

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.

2 participants