Skip to content

Commit 39c332c

Browse files
ml86mpollmeier
andauthored
Enable Scala 3 cross build. (#118)
* Fix indentation induced warnings and errors. * Cross build for scala 3. * Make Main class scala 2 and 3 compatible. * split subproject definitions into separate build.sbt * WIP * wip - works for scala3 * fuzzy scala version detection * final dependencies Co-authored-by: Michael Pollmeier <[email protected]>
1 parent 87f7d84 commit 39c332c

File tree

15 files changed

+243
-173
lines changed

15 files changed

+243
-173
lines changed

Diff for: build.sbt

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ name := "overflowdb-codegen-root"
33
ThisBuild/organization := "io.shiftleft"
44

55
/** scala cross version settings for codegen:
6-
* we need scala 2.12 for the sbt plugin and 2.13 for everything else */
6+
* we need scala 2.12 for the sbt plugin, 2.13 and 3 for everything else */
77
lazy val codegen_2_12 = Projects.codegen_2_12
88
lazy val codegen_2_13 = Projects.codegen_2_13
9+
lazy val codegen_3 = Projects.codegen_3
10+
lazy val integrationTestSchemas_3 = Projects.integrationTestSchemas_3
11+
lazy val integrationTestSchemas_2_13 = Projects.integrationTestSchemas_2_13
12+
lazy val integrationTestDomainClasses_2_13 = Projects.integrationTestDomainClasses_2_13
13+
lazy val integrationTestDomainClasses_3 = Projects.integrationTestDomainClasses_3
14+
lazy val integrationTests_2_13 = Projects.integrationTests_2_13
15+
lazy val integrationTests_3 = Projects.integrationTests_3
916
lazy val sbtPlugin = Projects.sbtPlugin
10-
lazy val integrationTests = Projects.integrationTests
1117

1218
ThisBuild/resolvers += Resolver.mavenLocal
1319

@@ -16,8 +22,6 @@ ThisBuild/Compile/scalacOptions ++= Seq(
1622
"-feature",
1723
"-deprecation",
1824
"-language:implicitConversions",
19-
"-Ywarn-unused",
20-
// "-language:existentials",
2125
)
2226

2327
ThisBuild/licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0"))

Diff for: codegen/build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name := "overflowdb-codegen"
44

55
libraryDependencies ++= Seq(
66
"io.shiftleft" % "overflowdb-core" % Versions.overflowdb,
7-
"com.github.pathikrit" %% "better-files" % "3.8.0",
7+
("com.github.pathikrit" %% "better-files" % "3.8.0").cross(CrossVersion.for3Use2_13),
88
"com.github.scopt" %% "scopt" % "4.0.1",
99
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
1010
)

Diff for: codegen/src/main/scala/overflowdb/codegen/CodeGen.scala

+84-84
Large diffs are not rendered by default.

Diff for: codegen/src/main/scala/overflowdb/codegen/Helpers.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ object Helpers {
181181
| $propertyDefaultValueCases
182182
| case _ => super.propertyDefaultValue(propertyKey)
183183
| }
184-
|""".stripMargin
184+
|""".stripMargin.replaceAll("\n", "\n ")
185185
}
186186

187187
def propertyDefaultCases(properties: Seq[Property[_]]): String =

Diff for: codegen/src/main/scala/overflowdb/codegen/Main.scala

+32-31
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,42 @@ import java.io.File
44
import overflowdb.schema.Schema
55
import scopt.OParser
66

7-
object Main extends App {
7+
object Main {
88
case class Config(classWithSchema: String, fieldName: String, outputDir: File)
9+
def main(args: Array[String]) = {
10+
val builder = OParser.builder[Config]
11+
val parser1 = {
12+
import builder._
13+
OParser.sequence(
14+
programName("codegen"),
15+
opt[String]('c', "classWithSchema")
16+
.required()
17+
.action((x, c) => c.copy(classWithSchema = x))
18+
.text("class with schema field, e.g. `org.example.MyDomain$`"),
19+
opt[String]('f', "field")
20+
.required()
21+
.action((x, c) => c.copy(fieldName = x))
22+
.text("(static) field name for schema within the specified `classWithSchema` with schema field, e.g. `org.example.MyDomain$`"),
23+
opt[File]('o', "out")
24+
.required()
25+
.action((x, c) => c.copy(outputDir = x))
26+
.text("output directory"),
27+
)
28+
}
929

10-
val builder = OParser.builder[Config]
11-
val parser1 = {
12-
import builder._
13-
OParser.sequence(
14-
programName("codegen"),
15-
opt[String]('c', "classWithSchema")
16-
.required()
17-
.action((x, c) => c.copy(classWithSchema = x))
18-
.text("class with schema field, e.g. `org.example.MyDomain$`"),
19-
opt[String]('f', "field")
20-
.required()
21-
.action((x, c) => c.copy(fieldName = x))
22-
.text("(static) field name for schema within the specified `classWithSchema` with schema field, e.g. `org.example.MyDomain$`"),
23-
opt[File]('o', "out")
24-
.required()
25-
.action((x, c) => c.copy(outputDir = x))
26-
.text("output directory"),
27-
)
28-
}
29-
30-
OParser.parse(parser1, args, Config("", "", null)).foreach(execute)
30+
OParser.parse(parser1, args, Config("", "", null)).foreach(execute)
3131

32-
def execute(config: Config): Seq[File] = config match {
33-
case Config(classWithSchema, fieldName, outputDir) =>
34-
val classLoader = getClass.getClassLoader
35-
val clazz = classLoader.loadClass(classWithSchema)
36-
val field = clazz.getDeclaredField(fieldName)
37-
assert(field.getType == classOf[Schema], s"field $fieldName in class `$classWithSchema` must be of type `overflowdb.schema.Schema`, but actually is of type `${field.getType}`")
38-
field.setAccessible(true)
39-
val schema = field.get(clazz).asInstanceOf[Schema]
32+
def execute(config: Config): Seq[File] = config match {
33+
case Config(classWithSchema, fieldName, outputDir) =>
34+
val classLoader = getClass.getClassLoader
35+
val clazz = classLoader.loadClass(classWithSchema)
36+
val field = clazz.getDeclaredField(fieldName)
37+
assert(field.getType == classOf[Schema], s"field $fieldName in class `$classWithSchema` must be of type `overflowdb.schema.Schema`, but actually is of type `${field.getType}`")
38+
field.setAccessible(true)
39+
val schema = field.get(clazz).asInstanceOf[Schema]
4040

41-
new CodeGen(schema).run(outputDir)
41+
new CodeGen(schema).run(outputDir)
42+
}
4243
}
4344
}
4445

Diff for: codegen/src/main/scala/overflowdb/schema/testschema1/TestSchema1.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import overflowdb.storage.ValueTypes
1010
object TestSchema1 extends App {
1111
val builder = new SchemaBuilder("Cpg", "io.shiftleft.codepropertygraph.generated")
1212

13-
implicit val schemaInfo = SchemaInfo.forClass(getClass)
13+
implicit val schemaInfo: SchemaInfo = SchemaInfo.forClass(getClass)
1414

1515
// properties
1616
val name = builder

Diff for: codegen/src/main/scala/overflowdb/schema/testschema4/TestSchema4.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import java.io.File
99
object TestSchema4 extends App {
1010
val builder = new SchemaBuilder("Cpg","io.shiftleft.codepropertygraph.generated")
1111

12-
implicit val schemaInfo = SchemaInfo.forClass(getClass)
12+
implicit val schemaInfo: SchemaInfo = SchemaInfo.forClass(getClass)
1313

1414
val edge1 = builder.addEdgeType("EDGE_1")
1515
val rootNode1 = builder.addNodeBaseType("ROOT_NODE_1")

Diff for: integration-tests/build.sbt

-30
This file was deleted.

Diff for: integration-tests/domain-classes_2_13/build.sbt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name := "integration-test-domain-classes-2_13"
2+
3+
scalaVersion := Versions.scala_2_13
4+
5+
val generateDomainClasses = taskKey[Seq[File]]("generate overflowdb domain classes for all test schemas")
6+
7+
libraryDependencies ++= Seq(
8+
"io.shiftleft" %% "overflowdb-traversal" % Versions.overflowdb,
9+
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
10+
"org.slf4j" % "slf4j-simple" % "1.7.28" % Test,
11+
)
12+
13+
Compile/sourceGenerators += Projects.integrationTestSchemas_2_13 / generateDomainClasses
14+
scalacOptions -= "-Xfatal-warnings"
15+
16+
publish/skip := true
17+

Diff for: integration-tests/domain-classes_3/build.sbt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name := "integration-test-domain-classes-3"
2+
3+
scalaVersion := Versions.scala_3
4+
5+
val generateDomainClasses = taskKey[Seq[File]]("generate overflowdb domain classes for all test schemas")
6+
7+
libraryDependencies ++= Seq(
8+
"io.shiftleft" %% "overflowdb-traversal" % Versions.overflowdb,
9+
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
10+
"org.slf4j" % "slf4j-simple" % "1.7.28" % Test,
11+
)
12+
13+
Compile/sourceGenerators += Projects.integrationTestSchemas_3 / generateDomainClasses
14+
scalacOptions -= "-Xfatal-warnings"
15+
16+
publish/skip := true
17+

Diff for: integration-tests/schemas/build.sbt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name := "integration-tests-schemas"
2+
3+
val generateDomainClasses = taskKey[Seq[File]]("generate overflowdb domain classes for all test schemas")
4+
5+
// cross scalaVersion is defined in project/Build.scala
6+
7+
generateDomainClasses := Def.task {
8+
val outputRoot = target.value / "odb-codegen"
9+
FileUtils.deleteRecursively(outputRoot)
10+
(Compile/runMain).toTask(s" CodegenForAllSchemas").value
11+
FileUtils.listFilesRecursively(outputRoot)
12+
}.value
13+
14+
publish/skip := true

Diff for: integration-tests/schemas/src/main/scala/CodegenForAllSchemas.scala

+28-13
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,34 @@ import overflowdb.codegen.CodeGen
22

33
import java.io.File
44

5-
object CodegenForAllSchemas extends App {
6-
val outputDir =
7-
args.headOption.map(new File(_)).getOrElse(throw new AssertionError("please pass outputDir as first parameter"))
5+
object CodegenForAllSchemas {
86

9-
Seq(
10-
new TestSchema01,
11-
new TestSchema02,
12-
new TestSchema03a,
13-
new TestSchema03b,
14-
new TestSchema03c,
15-
new TestSchema04,
16-
new TestSchema05,
17-
).foreach { schema =>
18-
new CodeGen(schema.instance).run(outputDir)
7+
def main(args: Array[String]) = {
8+
val scalaVersion =
9+
if (isScala3) "scala-3"
10+
else "scala-2.13"
11+
12+
val outputDir = new File(s"integration-tests/schemas/target/$scalaVersion/odb-codegen")
13+
14+
Seq(
15+
new TestSchema01,
16+
new TestSchema02,
17+
new TestSchema03a,
18+
new TestSchema03b,
19+
new TestSchema03c,
20+
new TestSchema04,
21+
new TestSchema05,
22+
).foreach { schema =>
23+
new CodeGen(schema.instance).run(outputDir)
24+
}
25+
}
26+
27+
lazy val isScala3: Boolean =
28+
classpathUrls(getClass.getClassLoader)
29+
.exists(_.toString.contains("scala3-library_3"))
30+
31+
def classpathUrls(cl: ClassLoader): Array[java.net.URL] = cl match {
32+
case u: java.net.URLClassLoader => u.getURLs() ++ classpathUrls(cl.getParent)
33+
case _ => Array.empty
1934
}
2035
}

Diff for: integration-tests/tests/build.sbt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name := "integration-tests"
2+
3+
// val generateDomainClasses = taskKey[Seq[File]]("generate overflowdb domain classes for all test schemas")
4+
5+
// cross scalaVersion is defined in project/Build.scala
6+
7+
libraryDependencies ++= Seq(
8+
"io.shiftleft" %% "overflowdb-traversal" % Versions.overflowdb,
9+
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
10+
"org.slf4j" % "slf4j-simple" % "1.7.28" % Test,
11+
)
12+
13+
// Compile/sourceGenerators += Projects.integrationTestSchemas / generateDomainClasses
14+
// Compile/sourceGenerators += schemas / generateDomainClasses
15+
scalacOptions -= "-Xfatal-warnings"
16+
17+
publish/skip := true
18+

Diff for: integration-tests/tests/src/test/scala/Schema01Test.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ class Schema01Test extends AnyWordSpec with Matchers {
3939

4040
"lookup and traverse nodes/edges/properties" in {
4141
// generic traversal
42-
graph.nodes.property(Properties.NAME).toSet shouldBe Set("node 1a", "node 1b", "node 2a", "node 2b")
43-
graph.edges.property(Properties.NAME).toSet shouldBe Set("edge 2")
42+
graph.nodes.property(Properties.NAME).toSetMutable shouldBe Set("node 1a", "node 1b", "node 2a", "node 2b")
43+
graph.edges.property(Properties.NAME).toSetMutable shouldBe Set("edge 2")
4444
// TODO generate node type starters
4545
def node1Traversal = graph.nodes(Node1.Label).cast[Node1]
4646
def node2Traversal = graph.nodes(Node2.Label).cast[Node2]
4747
node1Traversal.out.toList shouldBe Seq(node2a)
48-
node1Traversal.name.toSet shouldBe Set("node 1a", "node 1b")
48+
node1Traversal.name.toSetMutable shouldBe Set("node 1a", "node 1b")
4949
node1Traversal.order.l shouldBe Seq(2)
5050
node2Traversal.options.l shouldBe Seq("opt1", "opt2")
5151
node2Traversal.placements.l shouldBe Seq(5, 1, 7)
@@ -58,10 +58,10 @@ class Schema01Test extends AnyWordSpec with Matchers {
5858
val edge2Specific = edge2.asInstanceOf[Edge2]
5959
val name: String = node1aSpecific.name
6060
name shouldBe "node 1a"
61-
val _: Option[Integer] = node1aSpecific.order
61+
val o1: Option[Integer] = node1aSpecific.order
6262
node1aSpecific.order shouldBe Some(2)
6363
node1bSpecific.order shouldBe None
64-
val _: Seq[String] = node2aSpecific.options
64+
val o2: Seq[String] = node2aSpecific.options
6565
node2aSpecific.options shouldBe Seq("opt1", "opt2")
6666
node2bSpecific.options shouldBe Seq.empty
6767
node2bSpecific.placements shouldBe IndexedSeq(5, 1, 7)

Diff for: project/Build.scala

+16-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import sbt._
22
import com.lucidchart.sbtcross.BaseProject
33

44
object Versions {
5-
val overflowdb = "1.76"
5+
val overflowdb = "1.83"
66
val scala_2_12 = "2.12.15"
77
val scala_2_13 = "2.13.7"
8+
val scala_3 = "3.1.0"
89
}
910

1011
object Projects {
@@ -13,7 +14,20 @@ object Projects {
1314
lazy val codegen = BaseProject(project.in(file("codegen"))).cross
1415
lazy val codegen_2_12 = codegen(Versions.scala_2_12)
1516
lazy val codegen_2_13 = codegen(Versions.scala_2_13)
17+
lazy val codegen_3 = codegen(Versions.scala_3)
18+
19+
lazy val integrationTestSchemas = BaseProject(project.in(file("integration-tests/schemas"))).cross.dependsOn(codegen)
20+
lazy val integrationTestSchemas_2_13 = integrationTestSchemas(Versions.scala_2_13)
21+
lazy val integrationTestSchemas_3 = integrationTestSchemas(Versions.scala_3)
22+
lazy val integrationTestDomainClasses_2_13 = project.in(file("integration-tests/domain-classes_2_13"))
23+
lazy val integrationTestDomainClasses_3 = project.in(file("integration-tests/domain-classes_3"))
24+
25+
lazy val integrationTests = BaseProject(project.in(file("integration-tests/tests"))).cross
26+
lazy val integrationTests_2_13 = integrationTests(Versions.scala_2_13).dependsOn(integrationTestDomainClasses_2_13)
27+
lazy val integrationTests_3 = integrationTests(Versions.scala_3).dependsOn(integrationTestDomainClasses_3)
28+
29+
val generateDomainClasses = taskKey[Seq[File]]("generate overflowdb domain classes for all test schemas")
30+
val sourceGenerators = sbt.Keys.sourceGenerators
1631

1732
lazy val sbtPlugin = project.in(file("sbt-overflowdb"))
18-
lazy val integrationTests = project.in(file("integration-tests"))
1933
}

0 commit comments

Comments
 (0)