@@ -11,112 +11,115 @@ import scala.util.matching.Regex
11
11
import munit .Assertions .assert
12
12
import java .io .File
13
13
14
-
15
14
val ScalaCodeBlock = """ *```scala name\:([\w\.]+)+""" .r
16
- val CodeBlockEnds = """ *```""" .r
17
- val ScalaCliBlock = """ *```scala-cli""" .r
18
- val CheckBlock = """ *\<\!\-\- Expected(-regex):""" .r
19
- val CheckBlockEnd = """ *\-\-\>""" .r
15
+ val CodeBlockEnds = """ *```""" .r
16
+ val ScalaCliBlock = """ *```scala-cli""" .r
17
+ val CheckBlock = """ *\<\!\-\- Expected(-regex):""" .r
18
+ val CheckBlockEnd = """ *\-\-\>""" .r
20
19
21
20
enum Commands :
22
- def context : Context
21
+ def context : Context
23
22
24
- case Snippet (name : String , lines : Seq [String ], context : Context )
25
- case Run (cmd : Seq [String ], context : Context )
26
- case Check (patterns : Seq [String ], regex : Boolean , context : Context )
23
+ case Snippet (name : String , lines : Seq [String ], context : Context )
24
+ case Run (cmd : Seq [String ], context : Context )
25
+ case Check (patterns : Seq [String ], regex : Boolean , context : Context )
27
26
28
27
case class Context (file : String , line : Int )
29
28
30
29
def msg (txt : String )(using c : Context ): String = s " From ${c.file}: ${c.line}: $txt"
31
30
32
31
def untilEndOfSnippet [T ](
33
- lines : Seq [String ],
34
- regex : Regex = CodeBlockEnds )(using c : Context ): (Seq [String ], Seq [String ], Context ) =
35
- val codeLines = lines.takeWhile(l => ! regex.matches(l))
36
- assert(codeLines.size > 0 , msg(" Block cannot be empty!" ))
37
- assert(codeLines.size < lines.size, msg(" Block should end!" ))
38
- (codeLines, lines.drop(codeLines.size + 1 ), c.copy(line = c.line + codeLines.size + 2 ))
32
+ lines : Seq [String ],
33
+ regex : Regex = CodeBlockEnds
34
+ )(using c : Context ): (Seq [String ], Seq [String ], Context ) =
35
+ val codeLines = lines.takeWhile(l => ! regex.matches(l))
36
+ assert(codeLines.size > 0 , msg(" Block cannot be empty!" ))
37
+ assert(codeLines.size < lines.size, msg(" Block should end!" ))
38
+ (codeLines, lines.drop(codeLines.size + 1 ), c.copy(line = c.line + codeLines.size + 2 ))
39
39
40
40
def parse (content : Seq [String ], currentCommands : Seq [Commands ], context : Context ): Seq [Commands ] =
41
- given Context = context
42
- content match
43
- case Nil => currentCommands
44
- case ScalaCodeBlock (name) :: tail =>
45
- val (codeLines, rest, newContext) = untilEndOfSnippet(tail)(using context)
46
-
47
- parse(rest, currentCommands :+ Commands .Snippet (name, codeLines, context), newContext)
48
- case ScalaCliBlock () :: tail =>
49
- val (codeLines, rest, newContext) = untilEndOfSnippet(tail)
50
- assert(codeLines.size != 0 )
51
- val runCmd = Commands .Run (codeLines.head.split(" " ).toList, newContext)
52
- parse(rest, currentCommands :+ runCmd, newContext)
53
- case CheckBlock (regexOpt) :: tail =>
54
- val isRegex = regexOpt == " -regex"
55
- val (patterns, rest, newContext) = untilEndOfSnippet(tail, CheckBlockEnd )
56
- parse(rest, currentCommands :+ Commands .Check (patterns, isRegex, context), newContext)
57
- case _ :: tail => parse(tail, currentCommands, context.copy(line = context.line + 1 ))
41
+ given Context = context
42
+ content match
43
+ case Nil => currentCommands
44
+ case ScalaCodeBlock (name) :: tail =>
45
+ val (codeLines, rest, newContext) = untilEndOfSnippet(tail)(using context)
46
+
47
+ parse(rest, currentCommands :+ Commands .Snippet (name, codeLines, context), newContext)
48
+ case ScalaCliBlock () :: tail =>
49
+ val (codeLines, rest, newContext) = untilEndOfSnippet(tail)
50
+ assert(codeLines.size != 0 )
51
+ val runCmd = Commands .Run (codeLines.head.split(" " ).toList, newContext)
52
+ parse(rest, currentCommands :+ runCmd, newContext)
53
+ case CheckBlock (regexOpt) :: tail =>
54
+ val isRegex = regexOpt == " -regex"
55
+ val (patterns, rest, newContext) = untilEndOfSnippet(tail, CheckBlockEnd )
56
+ parse(rest, currentCommands :+ Commands .Check (patterns, isRegex, context), newContext)
57
+ case _ :: tail => parse(tail, currentCommands, context.copy(line = context.line + 1 ))
58
58
59
59
case class TestCase (path : Path , failure : Option [Throwable ])
60
60
61
- def checkPath (path : Path ): Seq [TestCase ] =
62
- try
63
- if ! Files .isDirectory(path) then
64
- if path.getFileName.toString.endsWith(" .md" ) then
65
- checkFile(path)
66
- Seq (TestCase (path, None ))
67
- else Nil
68
- else
69
- val toCheck = Files .list(path).iterator.asScala.filterNot(_.getFileName.toString.startsWith(" ." ))
70
- toCheck.toList.flatMap(checkPath)
71
- catch
72
- case e : Throwable =>
73
- e.printStackTrace()
74
- Seq (TestCase (path, Some (e)))
75
-
76
- def checkFile (file : Path ) =
77
- val content = Files .lines(file).iterator.asScala.toList
78
- val commands = parse(content, Vector (), Context (file.toString, 1 ))
79
- val out = Files .createTempDirectory(" scala-cli-tests" )
80
- println(s " Using $out as output to process $file" )
81
- var lastOutput = " "
82
- commands.foreach { cmd =>
83
- given Context = cmd.context
84
- cmd match
85
- case Commands .Run (cmd, _) =>
86
- println(s " ### Running: ${cmd.mkString(" " )}" )
87
- try lastOutput = Process (cmd, Some (out.toFile)).!!
88
- catch
89
- case e : Throwable =>
90
- throw new RuntimeException (msg(s " Error running ${cmd.mkString(" " )}" ), e)
91
- case Commands .Snippet (name, code, c) =>
92
- println(s " ### Writting $name with: \n ${code.mkString(" \n " )}\n --- " )
93
- val prefix = " \n " * c.line
94
- Files .write(out.resolve(name), code.mkString(prefix, " \n " , " " ).getBytes)
95
- case Commands .Check (patterns, regex, line) =>
96
- assert(lastOutput != " " )
97
- val lines = lastOutput.linesIterator.toList
98
-
99
- if regex then
100
- patterns.foreach { pattern =>
101
- val regex = pattern.r
102
- assert(
103
- lines.exists(regex.matches),
104
- msg(s " Regex: $pattern, does not matches any line in: \n $lastOutput" ))
105
- }
106
- else
107
- patterns.foreach { pattern => assert(
108
- lines.exists(_.contains(pattern)),
109
- msg(s " Pattern: $pattern does not exisits in any line in: \n $lastOutput" )
110
- )}
111
-
112
- }
61
+ def checkPath (path : Path ): Seq [TestCase ] =
62
+ try
63
+ if ! Files .isDirectory(path) then
64
+ if path.getFileName.toString.endsWith(" .md" ) then
65
+ checkFile(path)
66
+ Seq (TestCase (path, None ))
67
+ else Nil
68
+ else
69
+ val toCheck =
70
+ Files .list(path).iterator.asScala.filterNot(_.getFileName.toString.startsWith(" ." ))
71
+ toCheck.toList.flatMap(checkPath)
72
+ catch
73
+ case e : Throwable =>
74
+ e.printStackTrace()
75
+ Seq (TestCase (path, Some (e)))
76
+
77
+ def checkFile (file : Path ) =
78
+ val content = Files .lines(file).iterator.asScala.toList
79
+ val commands = parse(content, Vector (), Context (file.toString, 1 ))
80
+ val out = Files .createTempDirectory(" scala-cli-tests" )
81
+ println(s " Using $out as output to process $file" )
82
+ var lastOutput = " "
83
+ commands.foreach { cmd =>
84
+ given Context = cmd.context
85
+ cmd match
86
+ case Commands .Run (cmd, _) =>
87
+ println(s " ### Running: ${cmd.mkString(" " )}" )
88
+ try lastOutput = Process (cmd, Some (out.toFile)).!!
89
+ catch
90
+ case e : Throwable =>
91
+ throw new RuntimeException (msg(s " Error running ${cmd.mkString(" " )}" ), e)
92
+ case Commands .Snippet (name, code, c) =>
93
+ println(s " ### Writting $name with: \n ${code.mkString(" \n " )}\n --- " )
94
+ val prefix = " \n " * c.line
95
+ Files .write(out.resolve(name), code.mkString(prefix, " \n " , " " ).getBytes)
96
+ case Commands .Check (patterns, regex, line) =>
97
+ assert(lastOutput != " " )
98
+ val lines = lastOutput.linesIterator.toList
99
+
100
+ if regex then
101
+ patterns.foreach { pattern =>
102
+ val regex = pattern.r
103
+ assert(
104
+ lines.exists(regex.matches),
105
+ msg(s " Regex: $pattern, does not matches any line in: \n $lastOutput" )
106
+ )
107
+ }
108
+ else
109
+ patterns.foreach { pattern =>
110
+ assert(
111
+ lines.exists(_.contains(pattern)),
112
+ msg(s " Pattern: $pattern does not exisits in any line in: \n $lastOutput" )
113
+ )
114
+ }
115
+
116
+ }
113
117
114
118
@ main def check (args : String * ) =
115
- val testCases = args.flatMap(a => checkPath(Paths .get(a)))
116
- val (failed, ok) = testCases.partition(_.failure.nonEmpty)
117
- println(s " Completed: \n\t ${ok.map(_.path).mkString(" \n\t " )}" )
118
- if failed.nonEmpty then
119
- println(s " Failed: \n\t ${failed.map(_.path).mkString(" \n\t " )}" )
120
- sys.exit(1 )
121
- println(" ---" )
122
-
119
+ val testCases = args.flatMap(a => checkPath(Paths .get(a)))
120
+ val (failed, ok) = testCases.partition(_.failure.nonEmpty)
121
+ println(s " Completed: \n\t ${ok.map(_.path).mkString(" \n\t " )}" )
122
+ if failed.nonEmpty then
123
+ println(s " Failed: \n\t ${failed.map(_.path).mkString(" \n\t " )}" )
124
+ sys.exit(1 )
125
+ println(" ---" )
0 commit comments