Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=2.6.4
version=2.7.0
style = defaultWithAlign
maxColumn = 100

Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ lazy val `sbt-exercise` = (project in file("sbt-exercise"))
buildInfoPackage := "org.scalaexercises.plugin.sbtexercise",
buildInfoKeys := Seq(
version,
BuildInfoKey.map(compilerClasspath) {
case (_, classFiles) ⇒ ("compilerClasspath", classFiles.map(_.data))
BuildInfoKey.map(compilerClasspath) { case (_, classFiles) ⇒
("compilerClasspath", classFiles.map(_.data))
}
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ class SourceTextExtraction {
absolutePath.split(base).lift(1).getOrElse("")

def extractAll(sources: List[String], paths: List[String], baseDir: String): Extracted = {
new global.Run() compileSources (paths zip sources).map({
case (path, code) => new BatchSourceFile(path, code)
new global.Run() compileSources (paths zip sources).map({ case (path, code) =>
new BatchSourceFile(path, code)
})
val run = global.currentRun
val symbolPaths = Map(run.symSource.toList: _*).map({
case (symbol, file) => (symbol.toString, relativePath(file.path, baseDir))
val symbolPaths = Map(run.symSource.toList: _*).map({ case (symbol, file) =>
(symbol.toString, relativePath(file.path, baseDir))
})
val compilationUnits = run.units.toList // `units` is only only iterable once!
val extractions = compilationUnits.map(_.body).map(boundExtractRaw)
Expand All @@ -84,27 +84,25 @@ class SourceTextExtraction {
p flatMap (_.split('.').toList)

val (commentss, methodss) = extractions.map { extraction =>
val comments = extraction.comments.map(expandPath).map {
case (k, v) =>
splitPackage(k) -> new ExtractedComment(v._2.raw, commentFactory.parse(v._2))
val comments = extraction.comments.map(expandPath).map { case (k, v) =>
splitPackage(k) -> new ExtractedComment(v._2.raw, commentFactory.parse(v._2))
}

val rawImports = extraction.imports
val paths = rawImports.map(expandPath)

val imports = paths.groupBy(_._1).view.mapValues(_.map(_._2)).toMap

val methods = extraction.methods.map(expandPath).map {
case (k, v) =>
lazy val methodImports = k
.scanLeft(Nil: List[String])((a, c) => c :: a)
.map(_.reverse)
.flatMap(imports.get)
.flatten
.collect {
case (order, imp) if order < v._1 => showCode(imp)
}
splitPackage(k) -> new ExtractedMethod(boundReadCode(v._2), methodImports)
val methods = extraction.methods.map(expandPath).map { case (k, v) =>
lazy val methodImports = k
.scanLeft(Nil: List[String])((a, c) => c :: a)
.map(_.reverse)
.flatMap(imports.get)
.flatten
.collect {
case (order, imp) if order < v._1 => showCode(imp)
}
splitPackage(k) -> new ExtractedMethod(boundReadCode(v._2), methodImports)
}
(comments, methods)
}.unzip
Expand Down Expand Up @@ -159,8 +157,8 @@ object SourceTextExtraction {
case DocDef(comment, moduleDef @ ModuleDef(_, _, impl)) =>
val nextPath = moduleDef.name :: path
traversal(
impl.body.zipWithIndex.map {
case (body, index) => (nextPath, index, body)
impl.body.zipWithIndex.map { case (body, index) =>
(nextPath, index, body)
} ::: rs,
visitDocComment(nextPath.reverse, comment, acc)
)
Expand All @@ -169,8 +167,8 @@ object SourceTextExtraction {
case DocDef(comment, classDef @ ClassDef(_, _, Nil, impl)) =>
val nextPath = classDef.name :: path
traversal(
impl.body.zipWithIndex.map {
case (body, index) => (nextPath, index, body)
impl.body.zipWithIndex.map { case (body, index) =>
(nextPath, index, body)
} ::: rs,
visitDocComment(nextPath.reverse, comment, acc)
)
Expand All @@ -190,8 +188,8 @@ object SourceTextExtraction {
case moduleDef @ ModuleDef(_, _, impl) =>
val nextPath = moduleDef.name :: path
traversal(
impl.body.zipWithIndex.map {
case (body, index) => (nextPath, index, body)
impl.body.zipWithIndex.map { case (body, index) =>
(nextPath, index, body)
} ::: rs,
acc
)
Expand All @@ -200,8 +198,8 @@ object SourceTextExtraction {
case classDef @ ClassDef(_, _, Nil, impl) =>
val nextPath = classDef.name :: path
traversal(
impl.body.zipWithIndex.map {
case (body, index) => (nextPath, index, body)
impl.body.zipWithIndex.map { case (body, index) =>
(nextPath, index, body)
} ::: rs,
acc
)
Expand All @@ -211,8 +209,8 @@ object SourceTextExtraction {
if (ref.name == termNames.EMPTY_PACKAGE_NAME) path
else TermName(ref.toString) :: path
traversal(
topstats.zipWithIndex.map {
case (body, index) => (nextPath, index, body)
topstats.zipWithIndex.map { case (body, index) =>
(nextPath, index, body)
} ::: rs,
acc
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,31 +151,25 @@ class CommentParsingRenderingSpec extends AnyFunSpec with Matchers with Inside {
it("properly handles names") {

comments.withoutNames.foreach { comment =>
inside(CommentParsing.parse[Mode.Name[Id]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Name[Id]](comment)) { case Left(_) =>
}
inside(CommentParsing.parse[Mode.Name[Option]](comment)) {
case Right(parsed) =>
parsed.name shouldEqual None
inside(CommentParsing.parse[Mode.Name[Option]](comment)) { case Right(parsed) =>
parsed.name shouldEqual None
}
inside(CommentParsing.parse[Mode.Name[Empty]](comment)) {
case Right(parsed) =>
parsed.name shouldEqual Empty
inside(CommentParsing.parse[Mode.Name[Empty]](comment)) { case Right(parsed) =>
parsed.name shouldEqual Empty
}

}

comments.withNames.foreach { comment =>
inside(CommentParsing.parse[Mode.Name[Id]](comment)) {
case Right(parsed) =>
parsed.name shouldEqual comments.name
inside(CommentParsing.parse[Mode.Name[Id]](comment)) { case Right(parsed) =>
parsed.name shouldEqual comments.name
}
inside(CommentParsing.parse[Mode.Name[Option]](comment)) {
case Right(parsed) =>
parsed.name shouldEqual Some(comments.name)
inside(CommentParsing.parse[Mode.Name[Option]](comment)) { case Right(parsed) =>
parsed.name shouldEqual Some(comments.name)
}
inside(CommentParsing.parse[Mode.Name[Empty]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Name[Empty]](comment)) { case Left(_) =>
}

}
Expand All @@ -201,30 +195,24 @@ class CommentParsingRenderingSpec extends AnyFunSpec with Matchers with Inside {
it("properly handles descriptions") {

comments.withoutDescriptions.foreach { comment =>
inside(CommentParsing.parse[Mode.Description[Id]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Description[Id]](comment)) { case Left(_) =>
}
inside(CommentParsing.parse[Mode.Description[Option]](comment)) {
case Right(parsed) =>
parsed.description shouldEqual None
inside(CommentParsing.parse[Mode.Description[Option]](comment)) { case Right(parsed) =>
parsed.description shouldEqual None
}
inside(CommentParsing.parse[Mode.Description[Empty]](comment)) {
case Right(parsed) =>
parsed.description shouldEqual Empty
inside(CommentParsing.parse[Mode.Description[Empty]](comment)) { case Right(parsed) =>
parsed.description shouldEqual Empty
}

}

comments.withDescriptions.foreach { comment =>
inside(CommentParsing.parse[Mode.Description[Id]](comment)) {
case Right(parsed) =>
inside(CommentParsing.parse[Mode.Description[Id]](comment)) { case Right(parsed) =>
}
inside(CommentParsing.parse[Mode.Description[Option]](comment)) {
case Right(parsed) =>
parsed.description shouldBe defined
inside(CommentParsing.parse[Mode.Description[Option]](comment)) { case Right(parsed) =>
parsed.description shouldBe defined
}
inside(CommentParsing.parse[Mode.Description[Empty]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Description[Empty]](comment)) { case Left(_) =>
}
}

Expand All @@ -233,30 +221,24 @@ class CommentParsingRenderingSpec extends AnyFunSpec with Matchers with Inside {
it("properly handles explanations") {

comments.withoutExplanations.foreach { comment =>
inside(CommentParsing.parse[Mode.Explanation[Id]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Explanation[Id]](comment)) { case Left(_) =>
}
inside(CommentParsing.parse[Mode.Explanation[Option]](comment)) {
case Right(parsed) =>
parsed.explanation shouldEqual None
inside(CommentParsing.parse[Mode.Explanation[Option]](comment)) { case Right(parsed) =>
parsed.explanation shouldEqual None
}
inside(CommentParsing.parse[Mode.Explanation[Empty]](comment)) {
case Right(parsed) =>
parsed.explanation shouldEqual Empty
inside(CommentParsing.parse[Mode.Explanation[Empty]](comment)) { case Right(parsed) =>
parsed.explanation shouldEqual Empty
}

}

comments.withExplanations.foreach { comment =>
inside(CommentParsing.parse[Mode.Explanation[Id]](comment)) {
case Right(parsed) =>
inside(CommentParsing.parse[Mode.Explanation[Id]](comment)) { case Right(parsed) =>
}
inside(CommentParsing.parse[Mode.Explanation[Option]](comment)) {
case Right(parsed) =>
parsed.explanation shouldBe defined
inside(CommentParsing.parse[Mode.Explanation[Option]](comment)) { case Right(parsed) =>
parsed.explanation shouldBe defined
}
inside(CommentParsing.parse[Mode.Explanation[Empty]](comment)) {
case Left(_) =>
inside(CommentParsing.parse[Mode.Explanation[Empty]](comment)) { case Left(_) =>
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@ class CommentRenderingRegressions extends AnyFunSpec with Matchers with Inside {
* }}}
*/""")

inside(Comments.parseAndRender[Mode.Exercise](comment)) {
case Right(parsed) =>
// remove XML and check that there is code content
val description = parsed.description
.map(_.replaceAll("\\<.*?\\>", ""))
.getOrElse("")

assert(
description.trim.length > 50,
"Issue #309: code segment was not properly rendered"
)
inside(Comments.parseAndRender[Mode.Exercise](comment)) { case Right(parsed) =>
// remove XML and check that there is code content
val description = parsed.description
.map(_.replaceAll("\\<.*?\\>", ""))
.getOrElse("")

assert(
description.trim.length > 50,
"Issue #309: code segment was not properly rendered"
)
}

}
Expand All @@ -74,20 +73,19 @@ class CommentRenderingRegressions extends AnyFunSpec with Matchers with Inside {
* }}}
*/""")

inside(Comments.parseAndRender[Mode.Exercise](comment)) {
case Right(parsed) =>
val description = parsed.description
.map(_.replaceAll("\\<.*?\\>", ""))
.getOrElse("")
inside(Comments.parseAndRender[Mode.Exercise](comment)) { case Right(parsed) =>
val description = parsed.description
.map(_.replaceAll("\\<.*?\\>", ""))
.getOrElse("")

assert(
description.trim ==
"""abstract class Soldier(val firstName: String, val lastName: String) {}
assert(
description.trim ==
"""abstract class Soldier(val firstName: String, val lastName: String) {}
|
|// if you uncomment this line, it will fail compilation
|//val soldier = new Soldier""".stripMargin,
"Issue scala-exercises/exercises-stdlib#50: comment rendering problem"
)
"Issue scala-exercises/exercises-stdlib#50: comment rendering problem"
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,8 @@ class SourceTextExtractionSpec extends AnyFunSpec with Matchers with Inside {
it("should find all doc comments on classes and objects") {
val comments = res.comments
comments shouldNot be(empty)
comments foreach {
case (k, _) =>
multiLevelPackage.split('.') foreach (k should contain(_))
comments foreach { case (k, _) =>
multiLevelPackage.split('.') foreach (k should contain(_))
}
comments map { case (k, v) => k.mkString(".") -> v.raw } should equal(
Map(
Expand Down Expand Up @@ -133,15 +132,13 @@ class SourceTextExtractionSpec extends AnyFunSpec with Matchers with Inside {
val res = new SourceTextExtraction().extractAll(source1 :: source2 :: Nil, paths, "/")

// Should capture exactly 1 import for Object1.method
inside(res.methods.get("Object1" :: "method" :: Nil)) {
case Some(method) =>
method.imports shouldEqual List("import a._", "import b._")
inside(res.methods.get("Object1" :: "method" :: Nil)) { case Some(method) =>
method.imports shouldEqual List("import a._", "import b._")
}

// Should capture exactly 2 imports for Object2.method
inside(res.methods.get("Object2" :: "method" :: Nil)) {
case Some(method) =>
method.imports shouldEqual List("import c._", "import d._", "import obj2._")
inside(res.methods.get("Object2" :: "method" :: Nil)) { case Some(method) =>
method.imports shouldEqual List("import c._", "import d._", "import obj2._")
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,11 @@ object ExerciseCompilerPlugin extends AutoPlugin {
val generated = generateExercises.value

val dir = (sourceManaged in Compile).value
generated.map {
case (n, code) =>
val file = dir / (n.replace(".", "/") + ".scala")
IO.write(file, code)
log.info(s"Generated library at $file")
file
generated.map { case (n, code) =>
val file = dir / (n.replace(".", "/") + ".scala")
IO.write(file, code)
log.info(s"Generated library at $file")
file
}
}

Expand Down