Skip to content

Commit 041d5ad

Browse files
authored
Merge pull request #1602 from eed3si9n/bport/jdk25-main
[1.x] Support JDK 25 JEP-512/JEP-445 Main class
2 parents fbd7091 + 904574a commit 041d5ad

File tree

8 files changed

+90
-12
lines changed

8 files changed

+90
-12
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,35 @@ jobs:
1212
include:
1313
- os: ubuntu-latest
1414
java: 8
15+
distribution: zulu
1516
jobtype: 1
1617
- os: ubuntu-latest
1718
java: 11
19+
distribution: temurin
1820
jobtype: 1
1921
- os: ubuntu-latest
2022
java: 21
23+
distribution: zulu
2124
jobtype: 1
2225
- os: windows-latest
2326
java: 8
27+
distribution: zulu
2428
jobtype: 2
2529
- os: ubuntu-latest
2630
java: 21
31+
distribution: temurin
2732
jobtype: 3
2833
- os: ubuntu-latest
2934
java: 21
35+
distribution: temurin
3036
jobtype: 4
3137
- os: ubuntu-latest
3238
java: 21
39+
distribution: temurin
3340
jobtype: 5
3441
- os: ubuntu-latest
3542
java: 21
43+
distribution: temurin
3644
jobtype: 6
3745
runs-on: ${{ matrix.os }}
3846
steps:

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ ThisBuild / version := {
4646
nightlyVersion match {
4747
case Some(v) => v
4848
case _ =>
49-
if ((ThisBuild / isSnapshot).value) "1.10.6-SNAPSHOT"
49+
if ((ThisBuild / isSnapshot).value) "1.11.0-SNAPSHOT"
5050
else old
5151
}
5252
}

internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ class ExtractAPI[GlobalType <: Global](
8080
private[this] val allNonLocalClassSymbols = perRunCaches.newSet[Symbol]()
8181
private[this] val allNonLocalClassesInSrc = perRunCaches.newSet[xsbti.api.ClassLike]()
8282
private[this] val _mainClasses = perRunCaches.newSet[String]()
83+
private[this] val javaVersion: Int =
84+
try {
85+
val version = sys.props("java.specification.version").split("\\.").toList.map(_.toInt)
86+
version match {
87+
case 1 :: minor :: _ => minor
88+
case major :: _ => major
89+
case _ => 0
90+
}
91+
} catch {
92+
case _: Throwable => 0
93+
}
94+
private[this] def isJava25Plus: Boolean = javaVersion >= 25
8395

8496
/**
8597
* Implements a work-around for https://github.com/sbt/sbt/issues/823
@@ -775,7 +787,13 @@ class ExtractAPI[GlobalType <: Global](
775787
allNonLocalClassesInSrc += classWithMembers
776788
allNonLocalClassSymbols += sym
777789

778-
if (sym.isStatic && defType == DefinitionType.Module && definitions.hasJavaMainMethod(sym)) {
790+
if (isJava25Plus) {
791+
if (hasJava25MainMethod(sym)) {
792+
_mainClasses += name
793+
}
794+
} else if (
795+
sym.isStatic && defType == DefinitionType.Module && definitions.hasJavaMainMethod(sym)
796+
) {
779797
_mainClasses += name
780798
}
781799

@@ -790,6 +808,18 @@ class ExtractAPI[GlobalType <: Global](
790808
classDef
791809
}
792810

811+
private[this] def hasJava25MainMethod(sym: Symbol): Boolean =
812+
!sym.isAbstract && sym.tpe.member(nme.main).alternatives.exists(isJava25MainMethod)
813+
814+
private[this] def isJava25MainMethod(sym: Symbol): Boolean =
815+
(sym.name == nme.main) && (sym.info match {
816+
case MethodType(Nil, restpe) => restpe.typeSymbol == definitions.UnitClass
817+
case MethodType(p :: Nil, restpe) =>
818+
definitions.isArrayOfSymbol(p.tpe, definitions.StringClass) && restpe
819+
.typeSymbol == definitions.UnitClass
820+
case _ => false
821+
})
822+
793823
// TODO: could we restrict ourselves to classes, ignoring the term symbol for modules,
794824
// since everything we need to track about a module is in the module's class (`moduleSym.moduleClass`)?
795825
private[this] def isClass(s: Symbol) = s.isClass || s.isModule

internal/compiler-bridge/src/main/scala_2.10/xsbt/Compat.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ abstract class Compat {
110110

111111
// unexpandedName replaces originalName in 2.11
112112
@inline final def unexpandedName: Name = sym.originalName
113+
114+
@inline final def isAbstract: Boolean = false
113115
}
114116

115117
val DummyValue = 0

internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ class IncHandler(directory: Path, cacheDir: Path, scriptedLog: ManagedLogger, co
241241
case (p, src :: products, i) => p.checkClasses(i, dropRightColon(src), products)
242242
},
243243
onArgs("checkMainClasses") {
244-
case (p, src :: products, i) => p.checkMainClasses(i, dropRightColon(src), products)
244+
case (p, javaV :: src :: products, i) =>
245+
p.checkMainClasses(i, javaV, dropRightColon(src), products)
245246
},
246247
onArgs("checkProducts") {
247248
case (p, src :: products, i) => p.checkProducts(i, dropRightColon(src), products)
@@ -455,16 +456,23 @@ case class ProjectStructure(
455456
()
456457
}
457458

458-
def checkMainClasses(i: IncState, src: String, expected: List[String]): Future[Unit] =
459+
def checkMainClasses(
460+
i: IncState,
461+
javaV: String,
462+
src: String,
463+
expected: List[String]
464+
): Future[Unit] =
459465
compile(i).map { analysis =>
466+
val is25Plus = scala.util.Properties.isJavaAtLeast("25")
460467
def mainClasses(src: String): Set[String] =
461468
analysis.infos.get(converter.toVirtualFile(baseDirectory / src)).getMainClasses.toSet
462469
def assertClasses(expected: Set[String], actual: Set[String]) = {
463470
val msg = s"Expected $expected classes, got $actual\n\n" + analysis.infos.allInfos
464471
assert(expected == actual, msg)
465472
}
466473

467-
assertClasses(expected.toSet, mainClasses(src))
474+
if (is25Plus == (javaV == "25")) assertClasses(expected.toSet, mainClasses(src))
475+
else ()
468476
()
469477
}
470478

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
11
package runscala
22

33
object MainScala {
4-
def main(args: Array[String]) {}
4+
def main(args: Array[String]): Unit = ()
55

66
object StaticInner {
7-
def main(args: Array[String]) {}
7+
def main(args: Array[String]): Unit = ()
88
}
99
}
1010

11-
class NoMainScala {
12-
def main(args: Array[String]) {}
11+
class NoStatic {
12+
def main(args: Array[String]): Unit = ()
13+
}
14+
15+
class NoArgs {
16+
def main(): Unit = ()
17+
}
18+
19+
class Protected {
20+
protected def main(): Unit = ()
21+
}
22+
23+
trait Tr {
24+
def main(): Unit = ()
25+
}
26+
27+
abstract class Abs {
28+
def main(): Unit = ()
29+
}
30+
31+
class InheritTrait extends Tr
32+
abstract class AbsInheritAbs extends Abs
33+
34+
class NonVoid {
35+
def main(): Int = 1
1336
}
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
> compile
2-
> checkMainClasses src/main/java/runjava/MainJava.java: runjava.MainJava runjava.MainJava.StaticInner
3-
> checkMainClasses src/main/java/runjava/oMainJava.java:
4-
> checkMainClasses src/main/scala/Hello.scala: runscala.MainScala runscala.MainScala.StaticInner
2+
3+
# before Java 25
4+
> checkMainClasses 24 src/main/java/runjava/MainJava.java: runjava.MainJava runjava.MainJava.StaticInner
5+
> checkMainClasses 24 src/main/java/runjava/oMainJava.java:
6+
> checkMainClasses 24 src/main/scala/Hello.scala: runscala.MainScala runscala.MainScala.StaticInner
7+
8+
# starting Java 25
9+
> checkMainClasses 25 src/main/java/runjava/MainJava.java: runjava.MainJava runjava.MainJava.StaticInner
10+
> checkMainClasses 25 src/main/java/runjava/oMainJava.java:
11+
> checkMainClasses 25 src/main/scala/Hello.scala: runscala.MainScala runscala.MainScala.StaticInner runscala.NoStatic runscala.NoArgs runscala.Protected runscala.InheritTrait

0 commit comments

Comments
 (0)