Skip to content

Return a document symbol representing the "Render" method for a Razor file#12568

Merged
davidwengier merged 4 commits intodotnet:mainfrom
davidwengier:NeverReturnEmptySymbols
Dec 16, 2025
Merged

Return a document symbol representing the "Render" method for a Razor file#12568
davidwengier merged 4 commits intodotnet:mainfrom
davidwengier:NeverReturnEmptySymbols

Conversation

@davidwengier
Copy link
Member

Currently we don't return any document symbols in Razor files unless there are C# constructs that are mappable, which means either code in a @code or @functions block, or an @inject since that is emitted as a property.

While investigating an issue with document symbols not appearing on newly opened files, this made it really annoying to determine whether we were returning no symbols, or we were returning symbols but the editor wasn't displaying them. This PR fixes that by ensuring we always return at least one symbol, and also I think improves the look of things. Selfishly, it should make it easier to demonstrate to the editor team that they have a bug :)

Looks like this:

.razor file:
image

cshtml file:
image

VS Code:
image

@davidwengier davidwengier requested a review from a team as a code owner December 8, 2025 21:30
@davidwengier
Copy link
Member Author

davidwengier commented Dec 8, 2025

@danroth27 @sayedihashimi @DamianEdwards If anyone has any feedback on using <Component> and <Page> for these? Could be <html content> instead? Is <View> more appropriate for .cshtml files? Should these words be localized, or are they more like keywords?

@DamianEdwards
Copy link
Member

@davidwengier "Component" for *.razor files and "View" for *.cshtml files is probably the best generalization, although I'm wondering if the method name the code is emitted into would actually be more helpful?

@danroth27
Copy link
Member

danroth27 commented Dec 8, 2025

How about <Members>?

@sayedihashimi
Copy link
Member

sayedihashimi commented Dec 8, 2025

What about DocumentSymbols, but I'm not sure how the user would need to interact with this. I made this suggestion by reading your description.

@DamianEdwards
Copy link
Member

How about ?

Not sure what that means? IIUC the symbol is already correct for things like methods/properties in @code blocks and directives like @inject, this is about creating a symbol for the main part of the file, i.e. the bit that gets mapped to the ExecuteAsync (.cshtml) or BuildRenderTree (.razor) method.

@davidwengier
Copy link
Member Author

Correct, we already show members there, and its worth noting that its very possible for there to be nothing to show other than this one synthesized entry, so I don't think showing <Members> then no members underneath makes sense.

For comparison, this is what Roslyn does for the synthesized <Main>$ method in top level programs:
image

@davidwengier
Copy link
Member Author

Just checked and learn.microsoft.com doesn't seem to localize "Views", so I'm going to leave them hardcoded until someone complains
image

@danroth27
Copy link
Member

Ah, ok, that makes sense. The name of the actual rendering method sounds reasonable then.

@davidwengier
Copy link
Member Author

My concern with the actual render methods is that we hide __builder in other circumstances, and it can lead to issues if people use it when its not necessarily the right builder to use (eg, if you're in a nested scope it could be __builder2 etc.). But I can just strip that off and show just BuildRenderTree if the real method is the preference though

In a simple file, it's the only entry.
image

Everyone happy with that?

Copy link
Member

@chsienki chsienki left a comment

Choose a reason for hiding this comment

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

Code LGTM.

If you will allow me to bikeshed further, I much prefer <Component> and <View> to the underlying method names, as we're exposing a C# concept in a razor file where it doesn't directly exist. This is not blocking, just wanted to 'go on record' 😆

@davidwengier
Copy link
Member Author

This is not blocking, just wanted to 'go on record' 😆

Must be an engineer vs PM thing because I agree with you, but I feel better deferring to Dan and Damian on matters of taste

@DamianEdwards
Copy link
Member

I won't make a fuss either way. I'll leave to @danroth27 to make the final call between <Component> and <View>, vs. BuildRenderTree() and ExecuteAsync().

@danroth27
Copy link
Member

I think sticking with the method names is fine. The rendering logic in the Razor file is effectively defining the implementation of these methods. The methods aren't secret; they are part of the API surface area. In Blazor, for example, it's not uncommon to implement components without using a .razor file and the BuildRenderTree method is directly part of that development experience.

@davidwengier
Copy link
Member Author

Suits me, since I don't need to change the code again :)

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.

5 participants