reactivemarbles / ObservableEvents

MIT License
120 stars 10 forks source link

Wrong observable event signature generated for events hidden in the inheriting class #209

Open Metadorius opened 4 months ago

Metadorius commented 4 months ago

Description

When using the source generator on newest DevExpress WinForms controls (using .NET Framework 4.8) the result can't be compiled because of some wrongly generated code. It seems that PaintEx signature differs from what the source generator assumes, so the result can't be compiled.

How to repro

  1. Install DevExpress WinForms components (23.2.4 as of time of writing) trial from here
  2. Clone https://github.com/kpCat/ObservableEventsDevexpressRepro
  3. Attempt to build the solution

Result

The following error pops up on compilation:

4>SourceClassDevExpress.XtraEditors.TextEdit-InstanceEvents.SourceGenerated.cs(440,13): Error CS0123 : No overloaded method for "Handler" that corresponds to the delegate "TextEditPaintExEventHandler".
glennawatson commented 4 months ago

Thanks,

Third party libraries are a bit hard for us to test against even with trials.

Is PaintEx a generic type?

Metadorius commented 4 months ago

Third party libraries are a bit hard for us to test against even with trials.

Let me help you then.

This is what gets generated:

        public global::System.IObservable<global::DevExpress.Utils.XtraPaintEventArgs> PaintEx=>global::System.Reactive.Linq.Observable.Create<global::DevExpress.Utils.XtraPaintEventArgs>(obs=>
        {
            void Handler( object sender, global::DevExpress.Utils.XtraPaintEventArgs e) =>obs.OnNext(e);
            _data.PaintEx+=Handler;
            return global::System.Reactive.Disposables.Disposable.Create(() => _data.PaintEx-=Handler);
        });

The analysis-reported error: image

I digged into decompile and figured out that the base XtraControl that is used by all DevExpress controls has PaintEx method which gets picked up by the source generator:

    public event XtraPaintEventHandler PaintEx
    {
      add => this.Events.AddHandler(XtraControl.paintEx, (Delegate) value);
      remove => this.Events.RemoveHandler(XtraControl.paintEx, (Delegate) value);
    }

The TextEdit and other controls define another event that hides the parent's event with another signature:

    public event TextEditPaintExEventHandler PaintEx
    {
      add => this.Events.AddHandler(TextEdit.paintEx, (Delegate) value);
      remove => this.Events.RemoveHandler(TextEdit.paintEx, (Delegate) value);
    }

So it seems to me that the source generator just incorrectly uses the hidden event instead of the new one.

Metadorius commented 4 months ago

Any news? Or perhaps there is some existing workaround for the time being to somehow disable some part of the codegen just to make it compile, apart from manually doing ye olde FromEventPattern?