Skip to content

generated domain classes: add unapply to named tuples for easy pattern matching - #366

Merged
maltek merged 6 commits into
masterfrom
mkraus/named-tuple-unapply
Sep 15, 2026
Merged

maltek merged 6 commits into
masterfrom
mkraus/named-tuple-unapply

Conversation

@maltek

@maltek maltek commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

the new test file demonstrates how this unapply method returning a named tuple enables pattern matching on the domain classes with the familiar syntax from matching on case classes:

  "named tuple unapply" should {
    "destructure a Song node" in {
      val heyBoDiddley = NewSong().name("HEY BO DIDDLEY").songtype("cover").performances(5)
      val boDiddley    = NewArtist().name("Bo_Diddley")
      val gratefulDead = GratefulDead.from(_.addEdge(src = heyBoDiddley, dst = boDiddley, Writtenby.Label))

      inside(gratefulDead.song.toBuffer) { case mutable.Buffer(Song(name = name, songtype = Some("cover"), performances = Some(5))) =>
        name shouldBe "HEY BO DIDDLEY"
      }
      inside(gratefulDead.song.head) { case Song(name = name) =>
        name shouldBe "HEY BO DIDDLEY"
      }
    }

    "destructure an Artist node" in {
      val garcia                  = NewArtist().name("Garcia")
      val Artist(name = "Garcia") = garcia
    }
  }

Now, we have a DSL that for filtering and extracting values from iterators. I don't aim to replace it here, but to enhance it. I think this feature here will shine in e.g. places (e.g. lowering tests) where you want to check a whole lot of values of the same node at once, and when you're using pattern matching already to replace an if on some match arms with a pattern (i.e. turn case x: X if x.foo == ... into case X(foo = ...).


This PR is made a bit awkward because named tuples are a Scala 3 feature and flatgraph still supports Scala 2. My strategy here was to make this feature optional: by default the generated code works with both Scala 2 and 3. But the code generator can be told to to use Scala 3 features, and then you get these named tuples. (You could even run the generator for the same schema twice, once to put code into src/main/scala2 and once into src/main/scala3 if you wanted a project to be compatible with either version and still make use of this feature in code that's specific to Scala 3.)

The interesting diff of this PR is in domain-classes-generator/src/main/scala/flatgraph/codegen/DomainClassesGenerator.scala and tests-scala3/src/test/scala/flatgraph/traversal/NamedTupleUnapplyTests.scala

We could also completely drop Scala 2 - we don't use it anymore in joern. But I'd feel a little bad doing that just for this feature.

@maltek
maltek requested review from ml86 and mpollmeier September 14, 2026 13:00

@ml86 ml86 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my point of view we could drop Scala 2 support. This would also make our life easier to get a Bazel build for this repo going. Scala 3 is 5 years old by now. I dont think somebody could complain about not having enough time to switch and even if so Scala 3 code is supposedly callable from Scala 2 code...

@maltek
maltek merged commit e3a0cb1 into master Sep 15, 2026
1 check passed
@maltek
maltek deleted the mkraus/named-tuple-unapply branch September 15, 2026 09:34
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

Successfully merging this pull request may close these issues.

3 participants