Skip to content

Commit

Permalink
codegen: test that output compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
nafg committed Dec 7, 2023
1 parent 453837c commit f382e6e
Show file tree
Hide file tree
Showing 18 changed files with 213 additions and 123 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ jobs:
- name: Build project
run: sbt ++${{ matrix.scala }} test

- name: Check that codegen output compiles
run: sbt ++${{ matrix.scala }} 'slick-additions-codegen/Test/runMain slick.additions.codegen.CodeGen' test-codegen/compile

- name: Check that codegen output hasn't changed
run: git diff --exit-code --quiet HEAD slick-additions-codegen/src/test/resources

- name: Compress target directories
run: tar cf targets.tar target slick-additions-entity/.jvm/target slick-additions-entity/.js/target slick-additions-codegen/target project/target
run: tar cf targets.tar target slick-additions-codegen/src/test/resources/target slick-additions-entity/.jvm/target slick-additions-entity/.js/target slick-additions-codegen/target project/target

- name: Upload target directories
uses: actions/upload-artifact@v2
Expand Down
4 changes: 4 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
version = "3.7.17"
runner.dialect = scala213source3

project.excludePaths = [
"glob:**/slick-additions-codegen/src/test/resources/**.scala"
]

maxColumn = 120

preset = IntelliJ
Expand Down
15 changes: 15 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,18 @@ lazy val `slick-additions-codegen` =
"org.scalatest" %% "scalatest" % "3.2.17" % "test"
)
)

lazy val `test-codegen` =
project
.in(`slick-additions-codegen`.base / "src" / "test" / "resources")
.dependsOn(`slick-additions`)
.settings(
publish / skip := true,
Compile / unmanagedSourceDirectories := Seq(baseDirectory.value),
scalacOptions += "-Ymacro-annotations",
libraryDependencies ++= Seq(
"com.typesafe.slick" %% "slick" % slickVersion,
"io.circe" %% "circe-generic" % "0.14.5",
"dev.optics" %% "monocle-macro" % "3.2.0"
)
)
18 changes: 17 additions & 1 deletion ci.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _root_.io.github.nafg.mergify.dsl._
import _root_.io.github.nafg.mergify.dsl.*


mergifyExtraConditions := Seq(
Expand All @@ -19,6 +19,22 @@ inThisBuild(List(
dynverGitDescribeOutput ~= (_.map(o => o.copy(dirtySuffix = sbtdynver.GitDirtySuffix("")))),
dynverSonatypeSnapshots := true,
githubWorkflowTargetTags ++= Seq("v*"),
githubWorkflowBuildPostamble ++=
Seq(
WorkflowStep.Sbt(
commands = List(
"slick-additions-codegen/Test/runMain slick.additions.codegen.CodeGen",
"test-codegen/compile"
),
name = Some("Check that codegen output compiles")
),
WorkflowStep.Run(
commands = List(
"git diff --exit-code --quiet HEAD slick-additions-codegen/src/test/resources"
),
name = Some("Check that codegen output hasn't changed")
)
),
githubWorkflowPublishTargetBranches := Seq(RefPredicate.StartsWith(Ref.Tag("v"))),
githubWorkflowPublish := Seq(
WorkflowStep.Sbt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class EntityTableModulesCodeGenerator extends TablesCodeGenerator {
""".stats
}

override def mappingType(rowClassType: Type.Name) = t"slick.lifted.MappedProjection[$rowClassType]"

override def tableStats = {
case tableConfig @ TableConfig(tableMetadata, tableClassName, modelClassName, columns) =>
columns.partition(c => tableMetadata.primaryKeys.exists(_.column == c.column.name)) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class TablesCodeGenerator extends BaseCodeGenerator {
// noinspection ScalaWeakerAccess
def isDefaultSchema(schema: String) = schema == "public"

def mappingType(rowClassType: Type.Name) = t"slick.lifted.ProvenShape[$rowClassType]"

def mkMapping(rowClassName: String, mappingName: Term.Name, columns: List[ColumnConfig]) = {
val companion = Term.Name(rowClassName)
val rowClassType = Type.Name(rowClassName)
Expand Down Expand Up @@ -53,7 +55,7 @@ class TablesCodeGenerator extends BaseCodeGenerator {
(group22[Term](terms)(Term.Tuple(_)), fac, extractor)
}

q"def $mappingName: MappedProjection[$rowClassType] = $tuple.<>({$factory}, $extractor)"
q"def $mappingName: ${mappingType(rowClassType)} = $tuple.<>({$factory}, $extractor)"
}

def columnField: ColumnConfig => Stat = {
Expand Down
3 changes: 3 additions & 0 deletions slick-additions-codegen/src/test/resources/config.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
profile = "slick.jdbc.H2Profile$"
driver = "org.h2.Driver"
url = "jdbc:h2:mem:test2;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM 'classpath:init.sql'"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.acme.models
package entity
import slick.additions.entity.Lookup, io.circe.generic.JsonCodec,
monocle.macros.Lenses
@JsonCodec @Lenses case class ColorsRow(name: String)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.acme.tablemodules
package entity
import slick.additions.AdditionsProfile
import slick.lifted.MappedProjection
trait SlickProfile extends slick.jdbc.H2Profile with AdditionsProfile {
Expand All @@ -13,7 +13,7 @@ object TableModules {
class Row(tag: Tag) extends BaseEntRow(tag) {
override def keyColumnName = "id"
val name = column[String]("name")
def mapping: MappedProjection[ColorsRow] = name.<>(
def mapping: slick.lifted.MappedProjection[ColorsRow] = name.<>(
{
ColorsRow.apply
},
Expand Down Expand Up @@ -47,7 +47,7 @@ object TableModules {
val col22 = column[Option[Int]]("col22")
val col23 = column[Option[Int]]("col23")
val col24 = column[Option[Int]]("col24")
def mapping: MappedProjection[PeopleRow] = (
def mapping: slick.lifted.MappedProjection[PeopleRow] = (
(
first,
last,
Expand Down
10 changes: 10 additions & 0 deletions slick-additions-codegen/src/test/resources/entity/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import slick.additions.entity.{EntityKey, Lookup}

import cats.implicits.toInvariantOps
import io.circe.{Codec, Decoder, Encoder}


package object entity {
implicit def codecLookup[K : Encoder: Decoder,A]: Codec[Lookup[K, A]] =
Codec.from(Decoder[K], Encoder[K]).imap[Lookup[K, A]](EntityKey[K, A])(_.key)
}
30 changes: 30 additions & 0 deletions slick-additions-codegen/src/test/resources/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
CREATE TABLE IF NOT EXISTS "colors" (
"id" BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
"name" VARCHAR NOT NULL
);
CREATE TABLE IF NOT EXISTS "people" (
"id" BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
"first" VARCHAR NOT NULL,
"last" VARCHAR NOT NULL,
"city" VARCHAR NOT NULL DEFAULT 'New York',
"date_joined" DATE NOT NULL DEFAULT now(),
"balance" NUMERIC NOT NULL DEFAULT 0.0,
"best_friend" BIGINT NULL REFERENCES "people"("id") ON DELETE SET NULL,
"col8" FLOAT8 NULL,
"col9" BOOL NULL,
"col10" INT NULL,
"col11" INT NULL,
"col12" INT NULL,
"col13" INT NULL,
"col14" INT NULL,
"col15" INT NULL,
"col16" INT NULL,
"col17" INT NULL,
"col18" INT NULL,
"col19" INT NULL,
"col20" INT NULL,
"col21" INT NULL,
"col22" INT NULL,
"col23" INT NULL,
"col24" INT NULL
);
28 changes: 28 additions & 0 deletions slick-additions-codegen/src/test/resources/plain/Models.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package plain
case class ColorsRow(id: Long, name: String)
case class PeopleRow(
id: Long,
first: String,
last: String,
city: String = "New York",
dateJoined: java.time.LocalDate = java.time.LocalDate.now(),
balance: BigDecimal = BigDecimal("0.0"),
bestFriend: Option[Long] = None,
col8: Option[Double] = None,
col9: Option[Boolean] = None,
col10: Option[Int] = None,
col11: Option[Int] = None,
col12: Option[Int] = None,
col13: Option[Int] = None,
col14: Option[Int] = None,
col15: Option[Int] = None,
col16: Option[Int] = None,
col17: Option[Int] = None,
col18: Option[Int] = None,
col19: Option[Int] = None,
col20: Option[Int] = None,
col21: Option[Int] = None,
col22: Option[Int] = None,
col23: Option[Int] = None,
col24: Option[Int] = None
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.acme.tables
package plain
import slick.jdbc.H2Profile.api._
import slick.additions.entity.Lookup
object Tables {
class Colors(_tableTag: Tag)
extends Table[ColorsRow](_tableTag, Some("PUBLIC"), "colors") {
val id = column[Long]("id")
val name = column[String]("name")
def * : MappedProjection[ColorsRow] = (id, name).<>(
def * : slick.lifted.ProvenShape[ColorsRow] = (id, name).<>(
{
(ColorsRow.apply _).tupled
},
Expand All @@ -22,7 +21,7 @@ object Tables {
val city = column[String]("city")
val dateJoined = column[java.time.LocalDate]("date_joined")
val balance = column[BigDecimal]("balance")
val bestFriend = column[Option[Lookup[Long, PeopleRow]]]("best_friend")
val bestFriend = column[Option[Long]]("best_friend")
val col8 = column[Option[Double]]("col8")
val col9 = column[Option[Boolean]]("col9")
val col10 = column[Option[Int]]("col10")
Expand All @@ -40,7 +39,7 @@ object Tables {
val col22 = column[Option[Int]]("col22")
val col23 = column[Option[Int]]("col23")
val col24 = column[Option[Int]]("col24")
def * : MappedProjection[PeopleRow] = (
def * : slick.lifted.ProvenShape[PeopleRow] = (
(
id,
first,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package slick.additions.codegen

import scala.concurrent.ExecutionContext.Implicits.global


object CodeGen extends App {
for (codeGeneration <- CodeGeneration.all)
Util.writeToFile(codeGeneration)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package slick.additions.codegen

import scala.io.Source

import org.scalatest.funsuite.AsyncFunSuite


class CodeGenTests extends AsyncFunSuite {
for (codeGeneration <- CodeGeneration.all)
test(codeGeneration.filename) {
Util.codeString(codeGeneration)
.map(assertResult(Source.fromResource(codeGeneration.filename).mkString)(_))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package slick.additions.codegen

import slick.additions.codegen.extra.circe.CirceJsonCodecModelsCodeGenerator
import slick.additions.codegen.extra.monocle.MonocleLensesModelsCodeGenerator


case class CodeGeneration(generator: BaseCodeGenerator, rules: GenerationRules) {
def pkgName = rules.packageName
val filename: String = s"${pkgName}/${rules.container}.scala"
}
object CodeGeneration {
class TestGenerationRules(override val container: String, override val packageName: String)
extends GenerationRules
val all = Seq(
CodeGeneration(new TablesCodeGenerator, new TestGenerationRules("Tables", "plain")),
CodeGeneration(new ModelsCodeGenerator, new TestGenerationRules("Models", "plain")),
CodeGeneration(
new EntityTableModulesCodeGenerator,
new TestGenerationRules("TableModules", "entity") with EntityGenerationRules
),
CodeGeneration(
new KeylessModelsCodeGenerator with MonocleLensesModelsCodeGenerator with CirceJsonCodecModelsCodeGenerator,
new TestGenerationRules("Models", "entity") with EntityGenerationRules
)
)
}
Loading

0 comments on commit f382e6e

Please sign in to comment.