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

Add name instance property to enum values #1511

Closed
DartBot opened this issue Nov 25, 2014 · 18 comments
Closed

Add name instance property to enum values #1511

DartBot opened this issue Nov 25, 2014 · 18 comments

Comments

@DartBot
Copy link

DartBot commented Nov 25, 2014

This issue was originally filed by @seaneagan


With the current spec it's difficult to get the name of an enum value, since the toString() result is prefixed with EnumClass.:

enumName(enumValue) {
  var s = enumValue.toString();
  return s.substring(s.indexOf('.') + 1);
}

It would be nice to just be able to do:

enumValue.name

@lrhn
Copy link
Member

lrhn commented Nov 25, 2014

I agree that it would be convenient with a way to get the name, and it's a problem that the name exists, but is only available by parsing the toString (Bloch said something about that in Efficient Java).
However, an argument against it is that every member you add to all enums will also block that name for use as an enum item:

enum EnvelopeEntry { name, address, city }

would fail if "name" is a member of enum instances.


Added Area-Language, Triaged labels.

@DartBot
Copy link
Author

DartBot commented Nov 25, 2014

This comment was originally written by [email protected]


Also worth considering - what will enum.toString() print once minified? My guess is the minified name not a readable one.

So if you need to keep the name string unminified in js, then you should probably use a class with a const constructor and a name field.

@DartBot
Copy link
Author

DartBot commented Dec 2, 2014

This comment was originally written by @seaneagan


The spec seems to imply that the enum name is preserved for the toString() output, but not sure if the implementations honor that.

I guess the name conflict is due to dart's having a single namespace for instance and static members. To avoid that, could solve this via an EnumInstanceMirror in dart:mirrors, but of course that has drawbacks.

@gbracha
Copy link

gbracha commented Jan 2, 2015

Set owner to @gbracha.
Added Accepted label.

@kevmoo
Copy link
Member

kevmoo commented Feb 6, 2015

Added C11 label.

@jolleekin
Copy link

What about a getter simpleName or a method getName()?

@VictorCamargo
Copy link

No news about this?

@kevmoo
Copy link
Member

kevmoo commented Feb 4, 2019

I also want this badly. @leafpetersen @munificent @eernstg @lrhn – is this more a language thing or a library thing?

@lrhn
Copy link
Member

lrhn commented Feb 4, 2019

It can be either.
The language specification states how an enum class looks.
If we just add a static helper method, say Object.enumName, then it's just a library change (even if it has fundamental effect on how enums are compiled).
We probably wouldn't, it's more likely that we'd add a superclass for enum classes (called Enum perhaps), and then add the static helper on that class (say String name(Enum value)).

So, most likely a language issue in some way.

Adding simpleName on the enum object will prevent enums from having that identifier as a name. We don't want to add anything to enum classes.

I'm still fundamentally opposed to exposing the source name as a string. It's just bad style, and we should never do (well, have done) that. It's reflection.
Sadly, we have already exposed the name in the toString, and then we might as well make it directly accessible somehow. (I believe Josh Bloch said something about that once).

@munificent
Copy link
Member

I'm sure it's too late to change this, but a simple solution would have been to have toString() return the bare name instead of EnumClass.enumName. I can't think of any cases where including the class name in there was useful.

@kevmoo
Copy link
Member

kevmoo commented Feb 4, 2019 via email

@lrhn
Copy link
Member

lrhn commented Feb 7, 2019

We'd have to add an enum to add that to.

If we don't provide a superclass to enums, then you could just use:

String enumName(Object o) {
  var text = o.toString();
  return text.substring(text.indexOf(".") + 1);
}

@zoechi
Copy link

zoechi commented Feb 12, 2019

What about improving support for old-style enums in the language (switch) and the analyzer (auto completion), (and perhaps some specialized code generation support) instead of tweaking Dart enums which are too limited anyway for all scenarios except the most basic ones?

@priezz
Copy link

priezz commented Apr 8, 2019

The one-liner to get the name:

String enumName(Object o) => o.toString().split('.').last;

@rknell
Copy link

rknell commented May 24, 2019

Just made a package for this one, also handles optional camel case parsing for easy display to user:

https://pub.dev/packages/enum_to_string

@MatrixDev
Copy link

I'll just leave this here for Flutter devs - describeEnum. no need for any external packages.
PS: it is unbelievably sad that such a trivial bug is opened for almost 7 years :(

@mit-mit
Copy link
Member

mit-mit commented Mar 11, 2021

Moving to the main language repo.

@MatrixDev please consider being more mindful when commenting. This may seem like a trivial bug, but any language has a near infinite amount of requests, so it's not realistic to expect them all to be resolved, regardless of their size.

@mit-mit mit-mit transferred this issue from dart-lang/sdk Mar 11, 2021
copybara-service bot pushed a commit to dart-lang/sdk that referenced this issue Sep 22, 2021
We use an extension getter instead of an instance getter because
it doesn't conflict with any potential existing or future enums
which want an element named `name`.
Keeping the namespace for enum elements open is a priority.
We currently only reserve `index` and `values`.

BUG: dart-lang/language#1511

Fixes language issue #1511, which is a long-standing request,
and should replace a number of alternative implementations
which are based on parsing the `toString()`.


This version has two fields on the shared superclass, the index
and private name, and has a separate `toString` for each `enum` class
which hard-codes that enum's class name.

An earlier version had both `"name"` and `"ClassName.name"` as fields
to be able to reuse the same `toString` method on all enum classes,
but that cost too much for JS compiled code.
Even having just `ClassName.` as a field and then combining inside
`toString` requires more code to create the enum instances.
Instead this version hardcodes the `ClassName.` string once
in the `toString` method, which means each enum class has its own
toString (which can *potentially* be tree-shaken then.)

This still tree-shakes slightly worse than the previous implementation
where every enum class had its own `index` and `_name` fields
independent of each other, which could then be tree-shaken independently.
However, the `index` was already made an interface member with the
addition of the `Enum` interface, so code which accesses `.index`
on something of the `Enum` supertype could prevent tree-shaking of
all enum classes' `index` fields.
Likewise any general access to the "name" of an enum would necessarily
do the same for the name.
This CL makes up for some of that by sharing more implementation
between enum classes.

DartVM AOT CodeSize impact: ~0.15% regression on gallery (little less on big g3 app)

TEST= New tests added to enum_test.dart

Change-Id: Id25334e6c987f470f558de3c141d0e3ff542b020
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210480
Commit-Queue: Lasse R.H. Nielsen <[email protected]>
Reviewed-by: Stephen Adams <[email protected]>
Reviewed-by: Martin Kustermann <[email protected]>
@lrhn
Copy link
Member

lrhn commented Sep 22, 2021

Added extension name getter on the Enum class, now that we have it.

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