Skip to content

Commit 707f9cb

Browse files
Merge pull request #14841 from dotty-staging/implement-new-main
Implement new main annotation
2 parents 3ddb21c + 8386911 commit 707f9cb

File tree

75 files changed

+2119
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2119
-0
lines changed

library/src/scala/annotation/newMain.scala

Lines changed: 388 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
object myProgram:
2+
3+
/** Adds two numbers */
4+
@main def add(num: Int, inc: => Int): Unit = // error
5+
println(s"$num + $inc = ${num + inc}")
6+
7+
end myProgram
8+
9+
object Test:
10+
def callMain(args: Array[String]): Unit =
11+
val clazz = Class.forName("add")
12+
val method = clazz.getMethod("main", classOf[Array[String]])
13+
method.invoke(null, args)
14+
15+
def main(args: Array[String]): Unit =
16+
callMain(Array("2", "3"))
17+
end Test
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
5+
@newMain def add(num: Int)(inc: Int): Unit = // error
6+
println(s"$num + $inc = ${num + inc}")
7+
8+
end myProgram
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
5+
@newMain def nop[T](t: T): T = // error
6+
t
7+
8+
end myProgram
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
implicit val x: Int = 2
5+
given Int = 3
6+
7+
@newMain def showImplicit(implicit num: Int): Unit = // error
8+
println(num)
9+
10+
@newMain def showUsing(using num: Int): Unit = // error
11+
println(num)
12+
13+
end myProgram
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
5+
@newMain @newMain def add1(num: Int, inc: Int): Unit = // error
6+
println(s"$num + $inc = ${num + inc}")
7+
8+
end myProgram
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
5+
@newMain val n = 2 // error
6+
7+
@newMain class A // error
8+
9+
@newMain val f = ((s: String) => println(s)) // error
10+
11+
end myProgram
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import scala.annotation.newMain
2+
3+
class A:
4+
@newMain def foo(bar: Int) = () // error
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.annotation.newMain
2+
3+
class MyNumber(val value: Int) {
4+
def +(other: MyNumber): MyNumber = MyNumber(value + other.value)
5+
}
6+
7+
object myProgram:
8+
9+
@newMain def add(num: MyNumber, inc: MyNumber): Unit = // error
10+
println(s"$num + $inc = ${num + inc}")
11+
12+
end myProgram
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.annotation.newMain
2+
import scala.util.CommandLineParser.FromString
3+
4+
object myProgram:
5+
6+
@newMain def add(num: Test.MyNumber, inc: Test.MyNumber): Unit = // error
7+
val numV = Test.value(num)
8+
val incV = Test.value(inc)
9+
println(s"$numV + $incV = ${numV + incV}")
10+
11+
end myProgram
12+
13+
14+
object Test:
15+
opaque type MyNumber = Int
16+
17+
def create(n: Int): MyNumber = n
18+
def value(n: MyNumber): Int = n
19+
20+
def callMain(args: Array[String]): Unit =
21+
val clazz = Class.forName("add")
22+
val method = clazz.getMethod("main", classOf[Array[String]])
23+
method.invoke(null, args)
24+
25+
def main(args: Array[String]): Unit =
26+
callMain(Array("2", "3"))
27+
end Test

tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ val experimentalDefinitionInLibrary = Set(
3232
"scala.annotation.MainAnnotation",
3333
"scala.annotation.MainAnnotation$",
3434

35+
//// New feature: prototype of new version of @main
36+
// This will never be stabilized. When it is ready it should replace the old @main annotation (requires scala.annotation.MainAnnotation).
37+
// Needs user feedback.
38+
"scala.annotation.newMain",
39+
"scala.annotation.newMain$",
40+
"scala.annotation.newMain$.alias",
41+
3542
//// New APIs: Mirror
3643
// Can be stabilized in 3.3.0 or later.
3744
"scala.deriving.Mirror$.fromProductTyped", // This API is a bit convoluted. We may need some more feedback before we can stabilize it.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Happy 23rd birthday, Lisa and Peter
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import scala.annotation.newMain
2+
3+
/**
4+
* Wishes a happy birthday to lucky people!
5+
*
6+
* @param age the age of the people whose birthday it is
7+
* @param name the name of the luckiest person!
8+
* @param others all the other lucky people
9+
*/
10+
@newMain def happyBirthday(age: Int, name: String, others: String*) =
11+
val suffix =
12+
age % 100 match
13+
case 11 | 12 | 13 => "th"
14+
case _ =>
15+
age % 10 match
16+
case 1 => "st"
17+
case 2 => "nd"
18+
case 3 => "rd"
19+
case _ => "th"
20+
val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name")
21+
for other <- others do bldr.append(" and ").append(other)
22+
println(bldr)
23+
24+
object Test:
25+
def callMain(args: Array[String]): Unit =
26+
val clazz = Class.forName("happyBirthday")
27+
val method = clazz.getMethod("main", classOf[Array[String]])
28+
method.invoke(null, args)
29+
30+
def main(args: Array[String]): Unit =
31+
callMain(Array("23", "Lisa", "Peter"))
32+
end Test
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
str = x
2+
rest = y,z
3+
4+
str = x
5+
rest = y,z
6+
7+
str = -a
8+
rest = x,y,z
9+
10+
str = x
11+
rest = y,z
12+
13+
str = y
14+
rest = z
15+
16+
Error: missing argument for --str
17+
Usage: foo [--str] <String> [<String> [<String> [...]]]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import scala.annotation.newMain
2+
3+
object myProgram:
4+
5+
@newMain def foo(str: String, rest: String*): Unit =
6+
println(s"str = $str")
7+
println(s"rest = ${rest.mkString(",")}")
8+
println()
9+
10+
end myProgram
11+
12+
object Test:
13+
def callMain(args: Array[String]): Unit =
14+
val clazz = Class.forName("foo")
15+
val method = clazz.getMethod("main", classOf[Array[String]])
16+
method.invoke(null, args)
17+
18+
def main(args: Array[String]): Unit =
19+
callMain(Array("x", "y", "z"))
20+
callMain(Array("--", "x", "y", "z"))
21+
callMain(Array("--", "-a", "x", "y", "z"))
22+
callMain(Array("x", "--", "y", "z"))
23+
callMain(Array("--str", "y", "--", "z"))
24+
callMain(Array("--str", "--", "y", "z")) // missing argument for `--str`
25+
end Test
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2 + 3 = 5
2+
2 + 1 = 3
3+
0 + 1 = 1
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import scala.annotation.newMain
2+
3+
// Sample main method
4+
object myProgram:
5+
6+
/** Adds two numbers */
7+
@newMain def add(num: Int = 0, inc: Int = 1): Unit =
8+
println(s"$num + $inc = ${num + inc}")
9+
10+
end myProgram
11+
12+
object Test:
13+
def callMain(args: Array[String]): Unit =
14+
val clazz = Class.forName("add")
15+
val method = clazz.getMethod("main", classOf[Array[String]])
16+
method.invoke(null, args)
17+
18+
def main(args: Array[String]): Unit =
19+
callMain(Array("2", "3"))
20+
callMain(Array("2"))
21+
callMain(Array())
22+
end Test
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
42
2+
OK
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import scala.annotation.newMain
2+
3+
// Sample main method
4+
object myProgram:
5+
6+
@newMain def alwaysPassParam(forbiddenParam: Int = throw new IllegalStateException("This should not be evaluated!")): Unit =
7+
println(forbiddenParam)
8+
9+
end myProgram
10+
11+
object Test:
12+
def hasCauseIllegalStateException(e: Throwable): Boolean =
13+
e.getCause match {
14+
case null => false
15+
case _: IllegalStateException => true
16+
case e: Throwable => hasCauseIllegalStateException(e)
17+
}
18+
19+
def callMain(args: Array[String]): Unit =
20+
val clazz = Class.forName("alwaysPassParam")
21+
val method = clazz.getMethod("main", classOf[Array[String]])
22+
method.invoke(null, args)
23+
24+
def main(args: Array[String]): Unit =
25+
callMain(Array("42"))
26+
try {
27+
callMain(Array())
28+
println("This should not be printed")
29+
}
30+
catch {
31+
case e: Exception if hasCauseIllegalStateException(e) => println("OK")
32+
}
33+
end Test

tests/run/main-annotation-flags.check

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
shortFlags: a = false, b = false
2+
shortFlags: a = true, b = false
3+
shortFlags: a = true, b = true
4+
Error: unused argument: true
5+
Error: unused argument: false
6+
Usage: shortFlags [-a] [-b]
7+
Error: unused argument: true
8+
Usage: shortFlags [-a] [-b]
9+
Error: unused argument: true
10+
Usage: shortFlags [-a] [-b]
11+
longFlags: flag1 = false, flag2 = false
12+
longFlags: flag1 = true, flag2 = false
13+
longFlags: flag1 = true, flag2 = true
14+
mixedFlags: a = false, flag = false
15+
mixedFlags: a = true, flag = false
16+
mixedFlags: a = true, flag = true

tests/run/main-annotation-flags.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import scala.annotation.newMain
2+
3+
// Sample main method
4+
object myProgram:
5+
6+
@newMain def shortFlags(a: Boolean, b: Boolean): Unit =
7+
println(s"shortFlags: a = $a, b = $b")
8+
9+
@newMain def longFlags(flag1: Boolean, flag2: Boolean): Unit =
10+
println(s"longFlags: flag1 = $flag1, flag2 = $flag2")
11+
12+
@newMain def mixedFlags(a: Boolean, flag: Boolean): Unit =
13+
println(s"mixedFlags: a = $a, flag = $flag")
14+
15+
end myProgram
16+
17+
object Test:
18+
def callMain(name: String, args: String*): Unit =
19+
val clazz = Class.forName(name)
20+
val method = clazz.getMethod("main", classOf[Array[String]])
21+
method.invoke(null, args.toArray)
22+
23+
def main(args: Array[String]): Unit =
24+
callMain("shortFlags")
25+
callMain("shortFlags", "-a")
26+
callMain("shortFlags", "-a", "-b")
27+
callMain("shortFlags", "true", "false")
28+
callMain("shortFlags", "-a", "true")
29+
callMain("shortFlags", "-b", "true")
30+
31+
32+
callMain("longFlags")
33+
callMain("longFlags", "--flag1")
34+
callMain("longFlags", "--flag1", "--flag2")
35+
36+
callMain("mixedFlags")
37+
callMain("mixedFlags", "-a")
38+
callMain("mixedFlags", "-a", "--flag")
39+
40+
41+
end Test

0 commit comments

Comments
 (0)