Skip to content
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

Enum 'object' rather than 'case object' fails silently #232

Closed
ALPSMAC opened this issue Jun 3, 2019 · 3 comments
Closed

Enum 'object' rather than 'case object' fails silently #232

ALPSMAC opened this issue Jun 3, 2019 · 3 comments

Comments

@ALPSMAC
Copy link

ALPSMAC commented Jun 3, 2019

Working on a large code base and trying to debug why withNameInsensitiveOption was always returning None, I finally determined that the enum was defined like:

sealed trait MyEnum extends EnumEntry
case object MyEnum extends Enum[MyEnum]{
  override val findValues = findValues 

  object ABC extends MyEnum
  object DEF extends MyEnum
  object GHI extends MyEnum
}

Notice it's missing the case for case object <whatever> extends MyEnum. This still compiles, and the objects are still perfectly reference-able from MyEnum - i.e. MyEnum.ABC works as expected, however things like withNameInsensitiveOption fail as described.

Now I know this is due to a misuse of the library, but it would be awfully nice if there was some way to detect and warn about this sort of mistake. It took me longer than I would have liked to realize the author of the code had missed the case keyword to make the macro magic work properly and it'd be nice if the library itself could help a bit in that regard.

I'm not sure what might be possible at compile time in terms of validating the enum... I wouldn't want ONLY case objects to be valid in an Enum - I suppose there could be a case where we actually want the behavior described (e.g. to "hide" a particular value of an enumeration from being directly "parsable" from string), but it would be nice if, knowing that is probably in the < 1% case, the compiler would emit a warning if it sees a plain old object declared within an Enum.

@lloydmeta
Copy link
Owner

I think it's definitely doable in the macro. In the simplest case, we could do something like that here

case md @ ModuleDef(_, _, _) => md

        case md @ ModuleDef(_, _, _) => md
          if (!md.mods.hasFlag(Flag.CASE)) {
            c.warning(c.enclosingPosition, "This enum member is an object but not a `case` object.")
          }

The only thing is, this might be a "backwards-breaking" change, given that often times people have fatal-errors enabled, and this could cause their code to trip up on legitimate non-case usage?

Some options include:

  • Ignore the fact that this could break legitimate non-case usage
  • Add a warnNonCase: Boolean/silentNonCase: Boolean param to the findValues macro
  • Add it as a separate method/macro findValueWarnOnNonCase

@akauppi
Copy link

akauppi commented Jun 17, 2019

Resembles #139

@lloydmeta
Copy link
Owner

Indeed, closing this as a dupe.

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

No branches or pull requests

3 participants