Skip to content

Conversation

@linkdotnet
Copy link
Collaborator

What we talked about today.

Moved a lot of the code to source code generators, with some changes to the current version:

  • Dropped the overloads with all the optional parameters
  • Added the this Task<IElement> overload for the async versions
  • Aligned (hopefully all) convenient functions to work with sync and async (for example KeyPress('c') and KeyPressAsync('c')).

@linkdotnet linkdotnet requested a review from egil September 19, 2025 21:39
@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch from b9ffb2c to dc2a16a Compare September 19, 2025 21:51
@egil
Copy link
Member

egil commented Sep 28, 2025

Cool. Think this is heading in a good direction.

Would it make sense to read EventHandlers.cs from the generator and get all the html event names (e.g., onclick) from there, as well as getting code doc parts from codedocs on properties on the event types themselves, e.g., MouseEventArgs.cs, such that it is not hardcoded in the generator.

Obviously, there needs to be the special-cases explicitly in the generator, or just in a partial handcoded type.

Looking at the Blazor sources, they actually have "reader" types that explicitly show what types of parameters can be passed in, e.g., we can see that ChangeEventArgsReader.cs supports, null, string, true, false, and string[]. It would be neat to have explicit overloads for Change() that takes these types explicitly, instead of using object?.

@egil
Copy link
Member

egil commented Sep 29, 2025

Also, want to add, that if this works as is correctly, we can always add my suggestions as an issue for future improvements, and get this merged in.

@egil egil requested a review from Copilot September 29, 2025 19:21
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a source generator to replace manually written event dispatch extension methods. The changes move from hand-coded event dispatch extensions to source-generated ones, which improves maintainability and consistency across the codebase.

  • Introduces a new source generator for event dispatch extensions
  • Removes manually written event dispatch extension files
  • Updates existing extensions to use partial classes to work with the generated code
  • Fixes style inconsistencies and adds Task overloads for async operations

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/bunit.tests/EventDispatchExtensions/WheelEventDispatchExtensionsTest.cs Fixed type reference from MouseEventDispatchExtensions to WheelEventDispatchExtensions
src/bunit/EventDispatchExtensions/TouchEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/ProgressEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/PointerEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/MouseEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/MediaEventDispatchExtensions.cs Updated to fix style and add Task overloads
src/bunit/EventDispatchExtensions/KeyboardEventDispatchExtensions.cs Changed to partial class and simplified methods to work with generator
src/bunit/EventDispatchExtensions/InputEventDispatchExtensions.cs Changed to partial class and added Task overloads
src/bunit/EventDispatchExtensions/FocusEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/DragEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/DialogEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit/EventDispatchExtensions/ClipboardEventDispatchExtensions.cs Removed entire file - functionality moved to source generator
src/bunit.generators.internal/bunit.generators.internal.csproj Added packaging configuration for the analyzer
src/bunit.generators.internal/Blazor/EventDispatcherExtensionGenerator.cs New source generator that creates event dispatch extension methods

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 118 to 119
var methodName = eventArgsType.Replace("EventArgs", "");
var eventName = $"on{methodName.ToLowerInvariant()}";
Copy link

Copilot AI Sep 29, 2025

Choose a reason for hiding this comment

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

The event name generation using ToLowerInvariant() may not work correctly for all event types. For example, ClipboardEventArgs would generate onclipboard instead of the correct event names like oncopy, oncut, onpaste. This could lead to incorrect event binding.

Copilot uses AI. Check for mistakes.
Comment on lines 116 to 121
private static void GenerateGenericEventExtension(StringBuilder sourceBuilder, string eventArgsType)
{
var methodName = eventArgsType.Replace("EventArgs", "");
var eventName = $"on{methodName.ToLowerInvariant()}";
GenerateAsyncEventMethod(sourceBuilder, methodName, eventName, eventArgsType);
}
Copy link

Copilot AI Sep 29, 2025

Choose a reason for hiding this comment

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

The generic event extension generation is overly simplistic and doesn't handle complex event types properly. EventArgs types like ClipboardEventArgs, DragEventArgs, and FocusEventArgs have multiple specific events (copy/cut/paste, drag/dragend/drop, focus/blur) that can't be mapped with this simple string replacement approach.

Copilot uses AI. Check for mistakes.
@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch 2 times, most recently from 0d457ae to 1e8cbfd Compare October 4, 2025 09:40
@egil egil requested a review from Copilot October 4, 2025 10:37
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 1 comment.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


return helperClassType.GetMethods()
.Where(x => x.GetParameters().FirstOrDefault()?.ParameterType == typeof(IElement))
.Where(x => x.GetParameters().Skip(1).FirstOrDefault()?.ParameterType == typeof(TEventArgs))
Copy link

Copilot AI Oct 4, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider extracting the magic number 1 into a named constant to improve readability and make the intent clearer (e.g., SKIP_FIRST_PARAMETER = 1).

Copilot uses AI. Check for mistakes.
@egil
Copy link
Member

egil commented Oct 4, 2025

@linkdotnet I trust you let me know when I should do a proper review.

@linkdotnet
Copy link
Collaborator Author

@linkdotnet I trust you let me know when I should do a proper review.

Yeah will notify you. Have some more local stuff and the in-laws over ;) have to balance that out a bit :)

@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch 2 times, most recently from b6462f4 to 9762345 Compare October 5, 2025 09:24
@linkdotnet
Copy link
Collaborator Author

@egil I do feel that thing is in a good state.

@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch from 9762345 to 7aa3753 Compare October 5, 2025 09:29
@linkdotnet
Copy link
Collaborator Author

linkdotnet commented Oct 5, 2025

image

<3 <3

@linkdotnet linkdotnet requested a review from Copilot October 5, 2025 09:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +163 to +168
var qualifiedEventArgsType = eventArgsType == "ErrorEventArgs"
? "Microsoft.AspNetCore.Components.Web.ErrorEventArgs"
: eventArgsType;
Copy link

Copilot AI Oct 5, 2025

Choose a reason for hiding this comment

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

Hard-coding the special case for ErrorEventArgs makes the code brittle. Consider creating a mapping dictionary or using reflection to determine the fully qualified type name for better maintainability.

Copilot uses AI. Check for mistakes.
@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch 4 times, most recently from b1667f2 to a5e5934 Compare October 5, 2025 12:35
foreach (var word in WordBoundaries.OrderByDescending(w => w.Length))
{
if (i + word.Length <= eventName.Length &&
eventName.AsSpan(i, word.Length).Equals(word.AsSpan(), StringComparison.OrdinalIgnoreCase))
Copy link
Member

Choose a reason for hiding this comment

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

I know CoPilot recommended this, but it seems super redundant. string comparison will do this for you if it makes any sense at all in terms of performance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will revert htat, and maybe move this into a variable. Have anyway some doc changes coming up

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well before we had a SubString which for sure does incur a new object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That said, the change itself does make sense but it is convoluted and i will refactor it

egil
egil previously approved these changes Oct 5, 2025
Copy link
Member

@egil egil left a comment

Choose a reason for hiding this comment

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

Assuming all tests pass, this looks great.

@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch 3 times, most recently from 809e357 to 5ca8821 Compare October 5, 2025 13:10
@linkdotnet linkdotnet force-pushed the dispatch-extensions-as-scg branch from 5ca8821 to 894f15a Compare October 5, 2025 13:15
@linkdotnet
Copy link
Collaborator Author

@egil Updated the docs and made a small refactoring. I would merge that bad boy in

@linkdotnet linkdotnet merged commit 5bda93c into main Oct 5, 2025
9 of 10 checks passed
@linkdotnet linkdotnet deleted the dispatch-extensions-as-scg branch October 5, 2025 15:25
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