-
Notifications
You must be signed in to change notification settings - Fork 10.4k
[Blazor] Add analyzer to detect ElementReference usage outside OnAfterRender with helper method analysis #63248
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
base: main
Are you sure you want to change the base?
Conversation
Greetings human! You've submitted a PR that modifies code that is shared with https://github.com/dotnet/runtime . Please make sure you synchronize this code with the changes in that repo! |
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
…hensive tests Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
@copilot When an element is accessed outside of OnAfterRender or OnAfterRender async, could we check if those methods are only ever called within OnAfterRender or OnAfterRender async? That should still be safe isn't it? So,
will warn today but it is totally safe to do as long as Helper() isn't called outside OnAfterRender/OnAfterRender async. We could do a different diagnostic here that says something along the lines of "Helper" accesses or uses ElementReference myReference and is being invoked outside of OnAfterRender or OnAfterRenderAsync. (Those are the message contents, but you figure out the proper language and tone following the pattern of existing diagnostics). We want to limit our analysis to the current class (if Helper is on a base class and its used on a derived class we won't detect and catch the issues, that's fine). A question that you need to solve is:
Finally, hooking to CompilationStart is a bit broad, could we instead hook into https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.diagnostics.analysiscontext.registersymbolstartaction?view=roslyn-dotnet-4.13.0#microsoft-codeanalysis-diagnostics-analysiscontext-registersymbolstartaction(system-action((microsoft-codeanalysis-diagnostics-symbolstartanalysiscontext))-microsoft-codeanalysis-symbolkind) For reference, here are all the options. The goal is to minimize the times we run or the lookups we have to perform. Ideally we only want to run when accessing ElementReference inside an IComponent implementation. RegisterAdditionalFileAction(Action) | Register an action to be executed for each non-code document. An additional file action reports Diagnostics about the AdditionalText of a document. -- | -- RegisterCodeBlockAction(Action) | Register an action to be executed after semantic analysis of a method body or an expression appearing outside a method body. A code block action reports Diagnostics about code blocks. RegisterCodeBlockStartAction(Action>) | Register an action to be executed at the start of semantic analysis of a method body or an expression appearing outside a method body. A code block start action can register other actions and/or collect state information to be used in diagnostic analysis, but cannot itself report any Diagnostics. RegisterCompilationAction(Action) | Register an action to be executed for a complete compilation. A compilation action reports Diagnostics about the Compilation. RegisterCompilationStartAction(Action) | Register an action to be executed at compilation start. A compilation start action can register other actions and/or collect state information to be used in diagnostic analysis, but cannot itself report any Diagnostics. RegisterOperationAction(Action, ImmutableArray) | Register an action to be executed at completion of semantic analysis of an IOperation with an appropriate Kind. An operation action can report Diagnostics about IOperations, and can also collect state information to be used by other operation actions or code block end actions. RegisterOperationAction(Action, OperationKind[]) | Register an action to be executed at completion of semantic analysis of an IOperation with an appropriate Kind. An operation action can report Diagnostics about IOperations, and can also collect state information to be used by other operation actions or code block end actions. RegisterOperationBlockAction(Action) | Register an action to be executed after semantic analysis of a method body or an expression appearing outside a method body. An operation block action reports Diagnostics about operation blocks. RegisterOperationBlockStartAction(Action) | Register an action to be executed at the start of semantic analysis of a method body or an expression appearing outside a method body. An operation block start action can register other actions and/or collect state information to be used in diagnostic analysis, but cannot itself report any Diagnostics. RegisterSemanticModelAction(Action) | Register an action to be executed at completion of semantic analysis of a document, which will operate on the SemanticModel of the document. A semantic model action reports Diagnostics about the model. RegisterSymbolAction(Action, ImmutableArray) | Register an action to be executed at completion of semantic analysis of an ISymbol with an appropriate Kind. A symbol action reports Diagnostics about ISymbols. RegisterSymbolAction(Action, SymbolKind[]) | Register an action to be executed at completion of semantic analysis of an ISymbol with an appropriate Kind. A symbol action reports Diagnostics about ISymbols. RegisterSymbolStartAction(Action, SymbolKind) | Register an action to be executed at start of semantic analysis of an ISymbol and its members with an appropriate Kind. RegisterSyntaxNodeAction(Action, ImmutableArray) | Register an action to be executed at completion of semantic analysis of a SyntaxNode with an appropriate Kind. A syntax node action can report Diagnostics about SyntaxNodes, and can also collect state information to be used by other syntax node actions or code block end actions. RegisterSyntaxNodeAction(Action, TLanguageKindEnum[]) | Register an action to be executed at completion of semantic analysis of a SyntaxNode with an appropriate Kind. A syntax node action can report Diagnostics about SyntaxNodes, and can also collect state information to be used by other syntax node actions or code block end actions. RegisterSyntaxTreeAction(Action) | Register an action to be executed at completion of parsing of a code document. A syntax tree action reports Diagnostics about the SyntaxTree of a document. [RegisterAdditionalFileAction(Action)](https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.diagnostics.analysiscontext.registeradditionalfileaction?view=roslyn-dotnet-4.13.0#microsoft-codeanalysis-diagnostics-analysiscontext-registeradditionalfileaction(system-action((microsoft-codeanalysis-diagnostics-additionalfileanalysiscontext)))) Register an action to be executed for each non-code document. An additional file action reports [Diagnostic](https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.diagnostic?view=roslyn-dotnet-4.13.0)s about the [AdditionalText](https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.additionaltext?view=roslyn-dotnet-4.13.0) of a document.RegisterCodeBlockAction(Action) RegisterCodeBlockStartAction(Action<CodeBlockStartAnalysisContext>) RegisterCompilationAction(Action) RegisterCompilationStartAction(Action) RegisterOperationAction(Action, ImmutableArray) RegisterOperationAction(Action, OperationKind[]) RegisterOperationBlockAction(Action) RegisterOperationBlockStartAction(Action) RegisterSemanticModelAction(Action) RegisterSymbolAction(Action, ImmutableArray) RegisterSymbolAction(Action, SymbolKind[]) RegisterSymbolStartAction(Action, SymbolKind) RegisterSyntaxNodeAction(Action, ImmutableArray) RegisterSyntaxNodeAction(Action, TLanguageKindEnum[]) RegisterSyntaxTreeAction(Action) |
…sis and more efficient registration Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
I've implemented all the requested improvements in commit 9b53c3e: ✅ Helper method analysis: The analyzer now detects when methods accessing ElementReference are called from unsafe contexts and provides a specific diagnostic (BL0010) with the message format you suggested. ✅ Safe helper calls: Methods called only from OnAfterRender/OnAfterRenderAsync don't trigger warnings, supporting the pattern you described. ✅ CaptureElementReference protection: Added ✅ Efficient registration: Switched from ✅ Class scope limitation: Analysis is restricted to method calls within the same type using The analyzer now provides two distinct diagnostics:
All scenarios are covered with comprehensive tests including chained helper methods and mixed safe/unsafe call patterns. |
This PR adds a new Blazor analyzer that detects when
ElementReference
instances are accessed outside of theOnAfterRenderAsync
orOnAfterRender
lifecycle methods, which can lead to runtime errors due to accessing stale or non-existent element references.Problem
Developers often try to access
ElementReference
fields or properties in other component lifecycle methods likeOnInitialized
,OnParametersSet
, or in event handlers. This practice is problematic because:Solution
The new
ElementReferenceUsageAnalyzer
provides intelligent analysis with two distinct diagnostics:BL0009 - Direct ElementReference Access
Reports when
ElementReference
fields or properties are directly accessed outside ofOnAfterRenderAsync
orOnAfterRender
methods.BL0010 - Helper Method Called from Unsafe Context
Reports when helper methods that access
ElementReference
are called from methods outside the safe render lifecycle, with the message: "Method '{MethodName}' accesses ElementReference '{ElementName}' and is being invoked outside of OnAfterRenderAsync or OnAfterRender"Key Features
RegisterSymbolStartAction
limited toIComponent
types instead of broad compilation analysisAddElementReferenceCapture
calls in render tree buildingExamples
This approach allows developers to safely extract ElementReference logic into helper methods as long as those helpers are only called from
OnAfterRender
orOnAfterRenderAsync
, while still catching unsafe usage patterns.Fixes #63247.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.