native icon indicating copy to clipboard operation
native copied to clipboard

Generated Dart code doesn't allow combining `NS_OPTIONS`

Open stuartmorgan-g opened this issue 1 year ago • 1 comments

I was attempting to migrate the following Obj-C code to Dart:

[item addObserver:observer
       forKeyPath:@"loadedTimeRanges"
          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
          context:NULL];

Where the options are defined by:

typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
    NSKeyValueObservingOptionNew = 0x01,
    NSKeyValueObservingOptionOld = 0x02,
    NSKeyValueObservingOptionInitial = 0x04,
    NSKeyValueObservingOptionPrior = 0x08

};

The generated code is:

enum NSKeyValueObservingOptions {
  NSKeyValueObservingOptionNew(1),
  NSKeyValueObservingOptionOld(2),
  NSKeyValueObservingOptionInitial(4),
  NSKeyValueObservingOptionPrior(8);

  final int value;
  const NSKeyValueObservingOptions(this.value);

  static NSKeyValueObservingOptions fromValue(int value) => switch (value) {
        1 => NSKeyValueObservingOptionNew,
        2 => NSKeyValueObservingOptionOld,
        4 => NSKeyValueObservingOptionInitial,
        8 => NSKeyValueObservingOptionPrior,
        _ => throw ArgumentError(
            "Unknown value for NSKeyValueObservingOptions: $value"),
      };
}

which is essentially unusable:

  • First, it doesn't define operator |, so they can't be directly combined.

  • Second, and worse, that can't be worked around. Before I looked at the full implementation when I just got the error about |, I tried:

    NSKeyValueObservingOptions.fromValue(
              NSKeyValueObservingOptions.NSKeyValueObservingOptionInitial.value |
                  NSKeyValueObservingOptions.NSKeyValueObservingOptionNew.value)
    

    but that throws the ArgumentError at runtime because, of course, the combination of two values is not one of the values.

Since the whole point of NS_OPTIONS as distinct from NS_ENUM is to allow combining values, the generator needs to make different code for NS_OPTIONS.

stuartmorgan-g avatar Sep 05 '24 19:09 stuartmorgan-g

Use the enums.as-int option to choose which enums to generate as int constants instead of Dart enums.

liamappelbe avatar Sep 06 '24 00:09 liamappelbe

Should be fixed by using enums.as-int. Please reopen if that doesn't work.

liamappelbe avatar Oct 24 '24 03:10 liamappelbe

I shouldn't have to do something different as a user when the source already indicates the correct behavior:

Since the whole point of NS_OPTIONS as distinct from NS_ENUM is to allow combining values, the generator needs to make different code for NS_OPTIONS.

stuartmorgan-g avatar Oct 24 '24 09:10 stuartmorgan-g

I don't have permission to re-open this, apparently?

stuartmorgan-g avatar Oct 24 '24 09:10 stuartmorgan-g