{"id":16195634,"url":"https://github.com/oleg-py/enumeratum-macro","last_synced_at":"2025-04-07T16:30:53.187Z","repository":{"id":109498106,"uuid":"126372600","full_name":"oleg-py/enumeratum-macro","owner":"oleg-py","description":"Macro syntax for enumeratum with good IDEA support","archived":false,"fork":false,"pushed_at":"2018-03-26T20:14:55.000Z","size":14,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-13T18:50:51.011Z","etag":null,"topics":["enumerations","enumeratum","enums","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oleg-py.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-22T17:34:11.000Z","updated_at":"2020-09-09T17:10:27.000Z","dependencies_parsed_at":"2023-04-06T06:38:27.209Z","dependency_job_id":null,"html_url":"https://github.com/oleg-py/enumeratum-macro","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleg-py%2Fenumeratum-macro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleg-py%2Fenumeratum-macro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleg-py%2Fenumeratum-macro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleg-py%2Fenumeratum-macro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oleg-py","download_url":"https://codeload.github.com/oleg-py/enumeratum-macro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247687683,"owners_count":20979518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["enumerations","enumeratum","enums","scala"],"created_at":"2024-10-10T08:44:30.269Z","updated_at":"2025-04-07T16:30:53.158Z","avatar_url":"https://github.com/oleg-py.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# enumeratum-macro\nA pleasant syntax for [enumeratum] with decent Intellij IDEA support\n\n## Quick start\nOnly Scala 2.12 is currently supported\n\nAdd this to your build definition:\n```sbt\nresolvers += \"JitPack\" at \"https://jitpack.io\"\n\nlibraryDependencies ++= Seq(\n  \"com.beachape\" %% \"enumeratum\" % \"1.5.13\",\n  \"org.scalameta\" %% \"scalameta\" % \"1.8.0\" % Provided,\n  \"com.github.olegpy\" % \"enumeratum-macro\" % \"0.0.1\"\n)\naddCompilerPlugin(\"org.scalameta\" % \"paradise\" % \"3.0.0-M10\" cross CrossVersion.patch)\n```\n\nDefine a enum:\n\n```scala\nimport com.olegpy.enumdsl._\n\n@enum trait Greeting {\n  val Hello, GoodBye, Hi, Bye = Value\n}\n```\n\nThat's it!\n\n## More Examples\n#### Manual name override / constructor parameters\nTranslated example from enumeratum readme:\n\n```scala\nimport com.olegpy.enumdsl._\n@enum class State(override val entryName: String) {\n    val Alabama = Value(\"AL\")\n    val Alaska = Value(\"AK\")\n   // and so on and so forth.\n}\n```\n\nNamed parameters are supported, but might produce spurous highlighting\nerrors in IDEA (see note below on IDEA support):\n\n```scala\nimport com.olegpy.enumdsl._\n@enum class State(override val entryName: String) {\n    val Alabama = Value(\"AL\")\n    val Alaska = Value(entryName = \"AK\")\n   // and so on and so forth.\n}\n```\n\n#### Value mixins (e.g. to override the name)\nTranslated example from enumeratum readme:\n```scala\nimport com.olegpy.enumdsl._\nimport enumeratum.EnumEntry._\n\n@enum trait Greeting extends Snakecase {\n  val Hello, GoodBye = Value\n  val ShoutGoodBye = Value.mix[Uppercase]\n}\n```\n\nAny `trait` can be a mixin. However, the resulting type must not\nhave unimplemented methods.\n\nMultiple mixins are supported using familiar `with` syntax:\n\n```scala\ntrait MyMixin {\n  def superMethod() = println() // suppose it does something awesome\n}\n\nimport com.olegpy.enumdsl._\nimport enumeratum.EnumEntry._\n\n@enum trait Greeting extends Snakecase {\n  val Hello, GoodBye = Value\n  val ShoutGoodBye = Value.mix[Camelcase with Uppercase with MyMixin]\n}\n```\n\n#### Companion mixins\nIf you're using `enumeratum-quill` and `enumeratum-circe`:\n\n```scala\nimport enumeratum._\n\n@enum(mix[QuillEnum, CirceEnum])\ntrait State {\n  val On, Off = Value\n}\n```\n\nCustom mixins are supported, so you can keep things DRY:\n\n```scala\nimport enumeratum._\n\ntrait EnumUtils[A \u003c: EnumEntry] extends QuillEnum[A] with CirceEnum[A] {\n  this: Enum[A] =\u003e\n\n  def withNameEither(name: String): Either[String, A] =\n    withNameOption(s).toRight(s\"Not found: $s\")\n}\n\n@enum(mix[EnumUtils])\ntrait State {\n  val On, Off = Value\n}\n\n```\n\n`mix` magic method supports up to 5 mixins. If you need more, either\ndefine a custom mixin or use `mix` multiple times (this will cause\nhighlighting errors in IDEA, so it's not recommended):\n\n```@enum(\n  mix[EnumUtils1, EnumUtils2, EnumUtils3, EnumUtils4, EnumUtils5],\n  mix[CirceEnum]\n) trait State {\n  val On, Off = Value\n}\n```\n\n## Goals\n#### Provide lightweight way to define a [enumeratum] Enum\nEnums from enumeratum are great. They provide a lot of integrations\n(Quill, Circe, pureconfig) and a lot of methods to perform a lookup\ndepending on your needs (e.g. `withNameInsensitiveOption`). The library\nhas been actively supported for a while already.\n\nHowever, there's one pain point with these which enumeratum does not\nsolve: syntax. A lot of boilerplate is involved in defining a simple\nenum. Syntactically, enumeratum is *way* inferior to\n`scala.Enumeration`, Java enums, or even defining a sealed trait / case\nobject manually (if all you want is pattern-matching with exhaustivity).\n\nOther libraries like [numerato] have emerged to solve syntax problems,\nyet they don't have that much support in the ecosystem, which might\npose some migration cost.\n\nThis problem is solved by only providing syntax for existing library.\nSyntax provided here aims to support most use-cases, allowing falling\nback to full-fledged manual `Enum` implementation where not supported\nor if there are any issues with `@enum` macro.\n\n#### Be easy to add to existing project\nIt should be easy to use for people who are using `enumeratum` already:\n\n- You can refactor existing code one enum at a time, or only use it for\n  new types.\n- It does not depend on a particular version of enumeratum, being\n  functional for older versions (starting at 1.3.2)\n\nSyntax also aims to be compatible with [numerato] and\n`scala.Enumeration`, and for simple use cases porting is supposed to be\nstraightforward (feel free to open a ticket if it's not for your\nuse-case).\n\n#### Be easy to remove from a project\nFor various reasons you might end up stopping using this library:\n\n- You find provided syntax too limited to your use case\n- You decide macro annotations is too much magic for you\n- This library becomes unmaintained in some unknown future\n\nBecause of such, falling back to [enumeratum] directly is as simple as:\n\n- use `@enum(debug = true)` to see printed trees and replace `@enum`\n  annotated class with code that will be printed by a compiler\n  - *or* (IDEA only) expand macro annotation using sidebar button\n- remove this library from dependencies\n\nIn doing so, you keep all benefits of enumeratum. All you lose is\nsome syntax sugar.\n\nIf you only want exhaustivity warnings on pattern matches, it is\npossible to remove enumeratum completely and use plain `sealed trait` /\n`case object`s. For that, just delete all enumeratum-specific\nsuperclasses (`Enum`, `EnumEntry`) and `val values = findValues` method.\n\nFor simple enums, it's possible to use `scala.Enumeration` or [numerato]\ninstead, because syntax of `@enum` macro aligns closely to these.\nAdvanced features such as mixins do not exist on those, however.\n\n#### Support Intellij IDEA\nEnum libraries built on scala macros tend to not play well with IDEA,\nwhich is the [most popular][jb-research] IDE for Scala.\n\n`enumeratum-macro` adresses this problem by using [scalameta], which is\nsupported quite well. All advanced features are designed with syntactic\ncompatibility in mind, so a lot of things like go to definition just\nwork.\n\nUnfortunately, it's not possible to support ALL syntactic features\nwithout spurous red squigglies. Where possible, `enumeratum-macro` does\nits best to localize such errors to the definition site of `@enum`\nclass, where they can be easily suppressed.\n\n**NOTE:** For best support, define `@enum`s in separate files from where\nyou access values.\n\n**NOTE 2:** For IDEA, some warnings can be suppressed using magic\ncomments (make a face at your IDE):\n\n```\n/*_*/\n// Type-aware highlighting is disabled below\n@enum class Foo(number: Int) {\n  val Bar = Value(number = 42) // named arguments won't appear red\n}\n/*_*/\n\n// Type-aware highlighting is enabled below\n```\n\nThis trick works with other cases where not-so-supported macros are\ninvolved, e.g. [shapeless]. Keep it in your arsenal, fellow Intellij\nuser.\n\n## What it does, actually\n\n```scala\n@enum(mix[Mixin1, Mixin2]) class Sample (number: Int = 0) {\n  val Foo, Bar = Value\n  val Baz = Value(number = 0)\n  val Qux = Value.mix[ValueMixin1 with ValueMixin2](11)\n\n  def method = println(number)\n}\n```\n\n- Class / trait is made sealed and abstract\n- Class is made to extend `enumeratum.EnumEntry`\n- All calls to `Value` and `Value.mix` are removed\n\n```scala\nsealed abstract class Sample (number: Int = 0)\n  extends enumeratum.EnumEntry\n{\n  def method = println(number)\n}\n```\n\n- Companion is made to extend `enumeratum.Enum[/*class name*/]` and\n  all type constructors passed to `mix`\n\n```scala\nobject Sample extends enumeratum.Enum[Sample]\n  with Mixin1[Sample]\n  with Mixin2[Sample]\n```\n\n- All previously removed calls to `Value` and `Value.mix` become newly\n  defined `case object`s\n  - All arguments are passed in as-is, including named ones\n  - All traits provided in `Value.mix` type parameters are mixed into\n    relevant object (again, as-is).\n\n- Field `val values = findValues` is defined\n\n```scala\n{\n    case object Foo extends Sample\n    case object Bar extends Sample(number = 0)\n    case object Qux extends Sample(11) with ValueMixin1 with ValueMixin2\n\n    val values = findValues\n}\n```\n\n## License\nMIT\n\n\n  [scalameta]: http://scalameta.org/\n  [shapeless]: https://github.com/milessabin/shapeless/\n  [enumeratum]: https://github.com/lloydmeta/enumeratum\n  [numerato]: https://github.com/maxaf/numerato\n  [jb-research]: https://www.jetbrains.com/research/devecosystem-2017/scala/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleg-py%2Fenumeratum-macro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foleg-py%2Fenumeratum-macro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleg-py%2Fenumeratum-macro/lists"}