diff --git a/main/src/main/scala/sbt/EvaluateConfigurations.scala b/main/src/main/scala/sbt/EvaluateConfigurations.scala
index 54531c5bd..621a20d8f 100644
--- a/main/src/main/scala/sbt/EvaluateConfigurations.scala
+++ b/main/src/main/scala/sbt/EvaluateConfigurations.scala
@@ -63,9 +63,9 @@ object EvaluateConfigurations {
*
* @param buildinImports The set of import statements to add to those parsed in the .sbt file.
*/
- private[this] def parseConfiguration(lines: Seq[String], builtinImports: Seq[String], offset: Int): ParsedFile =
+ private[this] def parseConfiguration(file: File, lines: Seq[String], builtinImports: Seq[String], offset: Int): ParsedFile =
{
- val (importStatements, settingsAndDefinitions) = splitExpressions(lines)
+ val (importStatements, settingsAndDefinitions) = splitExpressions(file, lines)
val allImports = builtinImports.map(s => (s, -1)) ++ addOffset(offset, importStatements)
val (definitions, settings) = splitSettingsDefinitions(addOffsetToRange(offset, settingsAndDefinitions))
new ParsedFile(allImports, definitions, settings)
@@ -103,7 +103,7 @@ object EvaluateConfigurations {
// TODO - Store the file on the LoadedSbtFile (or the parent dir) so we can accurately do
// detection for which project project manipulations should be applied.
val name = file.getPath
- val parsed = parseConfiguration(lines, imports, offset)
+ val parsed = parseConfiguration(file, lines, imports, offset)
val (importDefs, definitions) =
if (parsed.definitions.isEmpty) (Nil, DefinedSbtValues.empty) else {
val definitions = evaluateDefinitions(eval, name, parsed.imports, parsed.definitions, Some(file))
@@ -208,37 +208,18 @@ object EvaluateConfigurations {
}
}
private[this] def isSpace = (c: Char) => Character isWhitespace c
- private[this] def fstS(f: String => Boolean): ((String, Int)) => Boolean = { case (s, i) => f(s) }
private[this] def firstNonSpaceIs(lit: String) = (_: String).view.dropWhile(isSpace).startsWith(lit)
private[this] def or[A](a: A => Boolean, b: A => Boolean): A => Boolean = in => a(in) || b(in)
/**
* Splits a set of lines into (imports, expressions). That is,
* anything on the right of the tuple is a scala expression (definition or setting).
*/
- def splitExpressions(lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) =
+ def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) =
{
- val blank = (_: String).forall(isSpace)
- val isImport = firstNonSpaceIs("import ")
- val comment = firstNonSpaceIs("//")
- val blankOrComment = or(blank, comment)
- val importOrBlank = fstS(or(blankOrComment, isImport))
+ val split = SplitExpressionsNoBlankies(null, lines)
+ (split.imports, split.settings)
+ }
- val (imports, settings) = lines.zipWithIndex span importOrBlank
- (imports filterNot fstS(blankOrComment), groupedLines(settings, blank, blankOrComment))
- }
- def groupedLines(lines: Seq[(String, Int)], delimiter: String => Boolean, skipInitial: String => Boolean): Seq[(String, LineRange)] =
- {
- val fdelim = fstS(delimiter)
- @tailrec def group0(lines: Seq[(String, Int)], accum: Seq[(String, LineRange)]): Seq[(String, LineRange)] =
- if (lines.isEmpty) accum.reverse
- else {
- val start = lines dropWhile fstS(skipInitial)
- val (next, tail) = start.span { case (s, _) => !delimiter(s) }
- val grouped = if (next.isEmpty) accum else (next.map(_._1).mkString("\n"), LineRange(next.head._2, next.last._2 + 1)) +: accum
- group0(tail, grouped)
- }
- group0(lines, Nil)
- }
private[this] def splitSettingsDefinitions(lines: Seq[(String, LineRange)]): (Seq[(String, LineRange)], Seq[(String, LineRange)]) =
lines partition { case (line, range) => isDefinition(line) }
private[this] def isDefinition(line: String): Boolean =
diff --git a/main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala b/main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala
new file mode 100644
index 000000000..02ed24419
--- /dev/null
+++ b/main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala
@@ -0,0 +1,385 @@
+package sbt
+
+import java.io.File
+
+import scala.annotation.tailrec
+import SplitExpressionsNoBlankies._
+
+object SplitExpressionsNoBlankies {
+ val END_OF_LINE = "\n"
+}
+
+case class SplitExpressionsNoBlankies(file: File, lines: Seq[String]) {
+ val (imports, settings) = splitExpressions(file, lines)
+
+ private def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) = {
+ import scala.reflect.runtime._
+ import scala.reflect.runtime.universe._
+ import scala.tools.reflect.ToolBoxError
+ import scala.tools.reflect.ToolBox
+ import scala.compat.Platform.EOL
+ import BugInParser._
+ import XmlContent._
+
+ val mirror = universe.runtimeMirror(this.getClass.getClassLoader)
+ val toolbox = mirror.mkToolBox(options = "-Yrangepos")
+ val indexedLines = lines.toIndexedSeq
+ val original = indexedLines.mkString(END_OF_LINE)
+ val merged = handleXmlContent(original)
+ val fileName = if (file == null) "Here should be file name" else file.getAbsolutePath
+
+ val parsed =
+ try {
+ toolbox.parse(merged)
+ } catch {
+ case e: ToolBoxError =>
+ val seq = toolbox.frontEnd.infos.map { i =>
+ s"""[$fileName]:${i.pos.line}: ${i.msg}"""
+ }
+ throw new MessageOnlyException(
+ s"""${seq.mkString(EOL)}""".stripMargin)
+ }
+ val parsedTrees = parsed match {
+ case Block(stmt, expr) =>
+ stmt :+ expr
+ case t: Tree =>
+ Seq(t)
+ }
+
+ val (imports, statements) = parsedTrees partition {
+ case _: Import => true
+ case _ => false
+ }
+
+ def convertImport(t: Tree): (String, Int) =
+ (merged.substring(t.pos.start, t.pos.end), t.pos.line - 1)
+
+ def convertStatement(t: Tree): Option[(String, LineRange)] =
+ if (t.pos.isDefined) {
+ val originalStatement = merged.substring(t.pos.start, t.pos.end)
+ val statement = util.Try(toolbox.parse(originalStatement)) match {
+ case util.Failure(th) =>
+ val missingText = tryWithNextStatement(merged, t.pos.end, t.pos.line, fileName, th)
+ originalStatement + missingText
+ case _ =>
+ originalStatement
+ }
+ val numberLines = statement.count(c => c == '\n')
+ Some((statement, LineRange(t.pos.line - 1, t.pos.line + numberLines)))
+ } else {
+ None
+ }
+
+ (imports map convertImport, statements flatMap convertStatement)
+ }
+
+}
+
+/**
+ * Scala parser cuts last bracket -
+ * @see http://stackoverflow.com/questions/25547149/scala-parser-cuts-last-bracket
+ */
+private[sbt] object BugInParser {
+ /**
+ *
+ * @param content - parsed file
+ * @param positionEnd - from index
+ * @param positionLine - number of start position line
+ * @param fileName -
+ * @param th - original exception
+ * @return
+ */
+ private[sbt] def tryWithNextStatement(content: String, positionEnd: Int, positionLine: Int, fileName: String, th: Throwable): String = {
+ findFirstNotBlankNotCommentedIndex(content, positionEnd) match {
+ case Some(index) =>
+ content.substring(positionEnd, index + 1)
+ case _ =>
+ throw new MessageOnlyException(s"""[$fileName]:$positionLine: ${th.getMessage}""".stripMargin)
+ }
+ }
+
+ /**
+ *
+ * @param content - parsed file
+ * @param from - start index
+ * @return first not commented index or None
+ */
+ private def findFirstNotBlankNotCommentedIndex(content: String, from: Int): Option[Int] = {
+ val index = content.indexWhere(c => !c.isWhitespace, from)
+ if (index == -1) {
+ None
+ } else {
+ val c = content.charAt(index)
+ if (c == '/' && content.size > index + 1) {
+ val nextChar = content.charAt(index + 1)
+ if (nextChar == '/') {
+ val endOfLine = content.indexOf('\n', index)
+ findFirstNotBlankNotCommentedIndex(content, endOfLine)
+ } else {
+ //if (nextChar == '*')
+ val endOfCommented = content.indexOf("*/", index + 1)
+ findFirstNotBlankNotCommentedIndex(content, endOfCommented + 2)
+ }
+ } else {
+ Some(index)
+ }
+ }
+ }
+}
+
+/**
+ * #ToolBox#parse(String) will fail for xml sequence:
+ *
+ * val xml = txt
+ * rr
+ *
+ * At least brackets have to be added
+ *
+ * val xml = (txt
+ * rr)
+ *
+ */
+private object XmlContent {
+ /**
+ *
+ * @param original - file content
+ * @return original content or content with brackets added to xml parts
+ */
+ private[sbt] def handleXmlContent(original: String): String = {
+ val xmlParts = findXmlParts(original)
+ if (xmlParts.isEmpty) {
+ original
+ } else {
+ addExplicitXmlContent(original, xmlParts)
+ }
+ }
+
+ /**
+ * Cut file for normal text - xml - normal text - xml ....
+ * @param content -
+ * @param ts - import/statements
+ * @return (text,true) - is xml (text,false) - if normal text
+ */
+ private def splitFile(content: String, ts: Seq[(String, Int, Int)]): Seq[(String, Boolean)] = {
+ val (statements, index) = ts.foldLeft((Seq.empty[(String, Boolean)], 0)) {
+ (accSeqIndex, el) =>
+ val (statement, startIndex, endIndex) = el
+ val (accSeq, index) = accSeqIndex
+ val textStatementOption = if (index >= startIndex) {
+ None
+ } else {
+ val s = content.substring(index, startIndex)
+ Some((s, false))
+ }
+ val newAccSeq = (statement, true) +: addOptionToCollection(accSeq, textStatementOption)
+ (newAccSeq, endIndex)
+ }
+ val endOfFile = content.substring(index, content.length)
+ val withEndOfFile = (endOfFile, false) +: statements
+ withEndOfFile.reverse
+ }
+
+ /**
+ * Cut potential xmls from content
+ * @param content -
+ * @return sorted by openIndex xml parts
+ */
+ private def findXmlParts(content: String): Seq[(String, Int, Int)] = {
+ val xmlParts = findModifiedOpeningTags(content, 0, Seq.empty) ++ findNotModifiedOpeningTags(content, 0, Seq.empty)
+ val rootXmlParts = removeEmbeddedXmlParts(xmlParts)
+ rootXmlParts.sortBy(z => z._2)
+
+ }
+
+ private def searchForTagName(text: String, startIndex: Int, endIndex: Int) = {
+ val subs = text.substring(startIndex, endIndex)
+ val spaceIndex = subs.indexWhere(c => c.isWhitespace, 1)
+ if (spaceIndex == -1) {
+ subs
+ } else {
+ subs.substring(0, spaceIndex)
+ }
+ }
+
+ /**
+ * Modified Opening Tag -
+ * @param offsetIndex - index
+ * @param acc - result
+ * @return Set with tags and positions
+ */
+ @tailrec
+ private def findModifiedOpeningTags(content: String, offsetIndex: Int, acc: Seq[(String, Int, Int)]): Seq[(String, Int, Int)] = {
+ val endIndex = content.indexOf("/>", offsetIndex)
+ if (endIndex == -1) {
+ acc
+ } else {
+ val xmlFragment = findModifiedOpeningTag(content, offsetIndex, endIndex)
+ val newAcc = addOptionToCollection(acc, xmlFragment)
+ findModifiedOpeningTags(content, endIndex + 2, newAcc)
+ }
+ }
+
+ private def findModifiedOpeningTag(content: String, offsetIndex: Int, endIndex: Int): Option[(String, Int, Int)] = {
+ val startIndex = content.substring(offsetIndex, endIndex).lastIndexOf("<")
+ if (startIndex == -1) {
+ None
+ } else {
+ val tagName = searchForTagName(content, startIndex + 1 + offsetIndex, endIndex)
+ if (xml.Utility.isName(tagName)) {
+ xmlFragmentOption(content, startIndex + offsetIndex, endIndex + 2)
+ } else {
+ None
+ }
+ }
+
+ }
+
+ private def searchForOpeningIndex(text: String, closeTagStartIndex: Int, tagName: String) = {
+ val subs = text.substring(0, closeTagStartIndex)
+ val index = subs.lastIndexOf(s"<$tagName>")
+ if (index == -1) {
+ subs.lastIndexOf(s"<$tagName ")
+ } else {
+ index
+ }
+ }
+
+ /**
+ * Xml like - ...
+ * @param current - index
+ * @param acc - result
+ * @return Set with tags and positions
+ */
+ @tailrec
+ private def findNotModifiedOpeningTags(content: String, current: Int, acc: Seq[(String, Int, Int)]): Seq[(String, Int, Int)] = {
+ val closeTagStartIndex = content.indexOf("", current)
+ if (closeTagStartIndex == -1) {
+ acc
+ } else {
+ val closeTagEndIndex = content.indexOf(">", closeTagStartIndex)
+ if (closeTagEndIndex == -1) {
+ findNotModifiedOpeningTags(content, closeTagStartIndex + 2, acc)
+ } else {
+ val xmlFragment = findNotModifiedOpeningTag(content, closeTagStartIndex, closeTagEndIndex)
+ val newAcc = addOptionToCollection(acc, xmlFragment)
+ findNotModifiedOpeningTags(content, closeTagEndIndex + 1, newAcc)
+ }
+ }
+ }
+
+ private def removeEmbeddedXmlParts(xmlParts: Seq[(String, Int, Int)]) = {
+ def isElementBetween(el: (String, Int, Int), open: Int, close: Int): Boolean = {
+ xmlParts.exists {
+ element =>
+ val (_, openIndex, closeIndex) = element
+ el != element && (open > openIndex) && (close < closeIndex)
+ }
+ }
+ xmlParts.filterNot { el =>
+ val (_, open, close) = el
+ isElementBetween(el, open, close)
+ }
+ }
+
+ /**
+ *
+ * @param content -
+ * @param xmlParts -
+ * @return
+ */
+ private def addExplicitXmlContent(content: String, xmlParts: Seq[(String, Int, Int)]): String = {
+ val statements: Seq[(String, Boolean)] = splitFile(content, xmlParts)
+ val (builder, wasPreviousXml, wasXml, _) = statements.foldLeft((Seq.empty[String], false, false, "")) {
+ (acc, el) =>
+ val (bAcc, wasXml, _, previous) = acc
+ val (content, isXml) = el
+ val contentEmpty = content.trim.isEmpty
+ val (isNotCommentedXml, newAcc) = if (isXml) {
+ if (!wasXml) {
+ if (areBracketsNecessary(previous)) {
+ (true, " ( " +: bAcc)
+ } else {
+ (false, bAcc)
+ }
+ } else {
+ (true, bAcc)
+ }
+ } else if (wasXml && !contentEmpty) {
+ (false, " ) " +: bAcc)
+ } else {
+ (false, bAcc)
+ }
+
+ (content +: newAcc, isNotCommentedXml || (wasXml && contentEmpty), isXml, content)
+ }
+ val closeIfNecessaryBuilder =
+ if (wasPreviousXml && !wasXml) {
+ builder.head +: " ) " +: builder.tail
+ } else {
+ builder
+ }
+ closeIfNecessaryBuilder.reverse.mkString
+ }
+
+ /**
+ * Add to head if option is not empty
+ * @param acc - seq
+ * @param option -
+ * @tparam T - type
+ * @return original seq for None, add to head for Some[T]
+ */
+ private def addOptionToCollection[T](acc: Seq[T], option: Option[T]) = option.fold(acc)(el => el +: acc)
+
+ private def findNotModifiedOpeningTag(content: String, closeTagStartIndex: Int, closeTagEndIndex: Int): Option[(String, Int, Int)] = {
+
+ val tagName = content.substring(closeTagStartIndex + 2, closeTagEndIndex)
+ if (xml.Utility.isName(tagName)) {
+ val openTagIndex = searchForOpeningIndex(content, closeTagStartIndex, tagName)
+ if (openTagIndex == -1) {
+ None
+ } else {
+ xmlFragmentOption(content, openTagIndex, closeTagEndIndex + 1)
+ }
+ } else {
+ None
+ }
+ }
+
+ /**
+ * Check, if xmlPart is valid xml. If not - None is returned
+ * @param content - file content
+ * @param openIndex -
+ * @param closeIndex -
+ * @return Some((String,Int,Int))
+ */
+ private def xmlFragmentOption(content: String, openIndex: Int, closeIndex: Int): Option[(String, Int, Int)] = {
+ val xmlPart = content.substring(openIndex, closeIndex)
+ util.Try(xml.XML.loadString(xmlPart)) match {
+ case util.Success(_) => Some((xmlPart, openIndex, closeIndex))
+ case util.Failure(th) => None
+ }
+ }
+
+ /**
+ * If xml is in brackets - we do not need to add them
+ * @param statement -
+ * @return are brackets necessary?
+ */
+ private def areBracketsNecessary(statement: String): Boolean = {
+ val doubleSlash = statement.indexOf("//")
+ val endOfLine = statement.indexOf(END_OF_LINE)
+ if (doubleSlash == -1 || (doubleSlash < endOfLine)) {
+ val roundBrackets = statement.lastIndexOf("(")
+ val braces = statement.lastIndexOf("{")
+ val max = roundBrackets.max(braces)
+ if (max == -1) {
+ true
+ } else {
+ val trimmed = statement.substring(max + 1).trim
+ trimmed.nonEmpty
+ }
+ } else {
+ false
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/src/test/resources/error-format/1.sbt.txt b/main/src/test/resources/error-format/1.sbt.txt
new file mode 100644
index 000000000..c03539261
--- /dev/null
+++ b/main/src/test/resources/error-format/1.sbt.txt
@@ -0,0 +1 @@
+val a = "ss
\ No newline at end of file
diff --git a/main/src/test/resources/error-format/2.sbt.txt b/main/src/test/resources/error-format/2.sbt.txt
new file mode 100644
index 000000000..aab5484bb
--- /dev/null
+++ b/main/src/test/resources/error-format/2.sbt.txt
@@ -0,0 +1,13 @@
+import sbt._
+import aaa._
+
+import scala._
+
+scalaVersion in Global := "2.11.2"
+
+ala
+
+libraryDependencies in Global ++= Seq(
+ errorText
+ "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
+ "ch.qos.logback" % "logback-classic" % "1.1.2")
diff --git a/main/src/test/resources/error-format/3.sbt.txt b/main/src/test/resources/error-format/3.sbt.txt
new file mode 100644
index 000000000..1b027e254
--- /dev/null
+++ b/main/src/test/resources/error-format/3.sbt.txt
@@ -0,0 +1,3 @@
+import sbt._
+
+val s =
\ No newline at end of file
diff --git a/main/src/test/resources/new-format/1.sbt.txt b/main/src/test/resources/new-format/1.sbt.txt
new file mode 100644
index 000000000..c7aacc410
--- /dev/null
+++ b/main/src/test/resources/new-format/1.sbt.txt
@@ -0,0 +1,19 @@
+scalaVersion := "2.10.2"; libraryDependencies += "org.scala-sbt" %% "sbinary" % "0.4.1" withSources() withJavadoc()
+lazy val checkPom = taskKey[Unit]("check pom to ensure no sections are generated")
+checkPom := {
+ val pomFile = makePom.value
+
+ val pom = xml.XML.loadFile(pomFile)
+ val tpe = pom \\ "type"
+
+ if(!tpe.isEmpty)
+ error("Expected no sections, got: " + tpe + " in \n\n" + pom)
+}
+val b = ( )
+val a =
+
+
+
+
+
diff --git a/main/src/test/resources/new-format/2.sbt.txt b/main/src/test/resources/new-format/2.sbt.txt
new file mode 100644
index 000000000..899c65995
--- /dev/null
+++ b/main/src/test/resources/new-format/2.sbt.txt
@@ -0,0 +1,18 @@
+scalaVersion := "2.10.2"; name := "test"
+libraryDependencies += "org.scala-sbt" %% "sbinary" % "0.4.1" withSources() withJavadoc()
+
+lazy val checkPom = taskKey[Unit]("check pom to ensure no sections are generated"); checkPom := {
+ val pomFile = makePom.value
+ val pom = xml.XML.loadFile(pomFile)
+ val tpe = pom \\ "type"
+ if(!tpe.isEmpty)
+ error("Expected no sections, got: " + tpe + " in \n\n" + pom)
+}
+
+val b = ( )
+val a =
+
+
+
+
+
diff --git a/main/src/test/resources/new-format/3.sbt.txt b/main/src/test/resources/new-format/3.sbt.txt
new file mode 100644
index 000000000..672319b8c
--- /dev/null
+++ b/main/src/test/resources/new-format/3.sbt.txt
@@ -0,0 +1,7 @@
+
+/*
+OKOK
+*/
+
+val b = "*/"
+val a = 4
\ No newline at end of file
diff --git a/main/src/test/resources/old-format/1.sbt.txt b/main/src/test/resources/old-format/1.sbt.txt
new file mode 100644
index 000000000..aa5bf9483
--- /dev/null
+++ b/main/src/test/resources/old-format/1.sbt.txt
@@ -0,0 +1,66 @@
+import SonatypeKeys._
+
+xerial.sbt.Sonatype.sonatypeSettings
+
+organization := "me.benoitguigal"
+
+name := "twitter"
+
+version := "1.1-SNAPSHOT"
+
+scalaVersion := "2.10.2"
+
+resolvers += "spray repo" at "http://repo.spray.io"
+
+libraryDependencies ++= {
+ val sprayV = "1.2.1"
+ Seq(
+ "com.typesafe.akka" %% "akka-actor" % "2.2.3",
+ "joda-time" % "joda-time" % "2.3",
+ "org.joda" % "joda-convert" % "1.2",
+ "io.spray" % "spray-http" % sprayV,
+ "io.spray" % "spray-httpx" % sprayV,
+ "io.spray" % "spray-util" % sprayV,
+ "io.spray" % "spray-client" % sprayV,
+ "io.spray" % "spray-can" % sprayV,
+ "com.netflix.rxjava" % "rxjava-scala" % "0.19.6",
+ "io.spray" %% "spray-json" % "1.2.6",
+ "org.scalatest" % "scalatest_2.10" % "2.1.3" % "test",
+ "org.mockito" % "mockito-core" % "1.9.5" % "test")
+}
+
+publishMavenStyle := true
+
+publishTo := {
+ val nexus = "https://oss.sonatype.org/"
+ if (isSnapshot.value)
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+}
+
+pomIncludeRepository := { _ => false }
+
+pomExtra := (
+ https://github.com/benoitguigal/twitter-spray
+
+
+ BSD-style
+ http://www.opensource.org/licenses/bsd-license.php
+ repo
+
+
+
+ git@github.com:benoitguigal/twitter-spray.git
+ scm:git:git@github.com:benoitguigal/twitter-spray.git
+
+
+
+ BGuigal
+ Benoit Guigal
+ http://benoitguigal.me
+
+
+ )
+
+
diff --git a/main/src/test/resources/old-format/10.sbt.txt b/main/src/test/resources/old-format/10.sbt.txt
new file mode 100644
index 000000000..38ef793e2
--- /dev/null
+++ b/main/src/test/resources/old-format/10.sbt.txt
@@ -0,0 +1,81 @@
+
+//////////////////////////////////////
+// Root project settings
+//////////////////////////////////////
+
+name := Common.PROJECT_NAME
+
+unidocSettings
+
+Common.commonSettings
+
+//////////////////////////////////////
+// Subproject definitions
+//////////////////////////////////////
+
+lazy val core = Common.subproject("core").dependsOn(util)
+
+lazy val util = Common.subproject("util")
+
+//////////////////////////////////////
+// Common settings shared by all projects
+//////////////////////////////////////
+
+version in ThisBuild := Common.PROJECT_VERSION
+
+organization in ThisBuild := Common.ORGANIZATION
+
+scalaVersion in ThisBuild := Common.SCALA_VERSION
+
+libraryDependencies in ThisBuild ++= Seq(
+ "org.scala-lang" % "scala-reflect" % Common.SCALA_VERSION,
+ "org.slf4j" % "slf4j-api" % Common.SLF4J_VERSION,
+ "ch.qos.logback" % "logback-classic" % Common.LOGBACK_VERSION % "runtime",
+ "org.scalatest" %% "scalatest" % Common.SCALATEST_VERSION % "test"
+ )
+
+scalacOptions in (ThisBuild, Compile) ++= Seq(
+ "-unchecked",
+ "-deprecation",
+ "-feature"
+ )
+
+parallelExecution in (ThisBuild, Test) := false
+
+fork in (ThisBuild, Test) := true
+
+//////////////////////////////////////
+// Publishing settings
+//////////////////////////////////////
+
+publishMavenStyle in (ThisBuild) := true
+
+pomIncludeRepository in (ThisBuild) := { _ => false }
+
+licenses in (ThisBuild) := Seq(
+ "BSD-style" -> url("http://opensource.org/licenses/BSD-2-Clause")
+ )
+
+homepage in (ThisBuild) := Some(url("http://genslerappspod.github.io/scalavro/"))
+
+pomExtra in (ThisBuild) := (
+
+ git@github.com:GenslerAppsPod/scalavro.git
+ scm:git:git@github.com:GenslerAppsPod/scalavro.git
+
+
+
+ ConnorDoyle
+ Connor Doyle
+ http://gensler.com
+
+
+ )
+
+publishTo in (ThisBuild) <<= version { (v: String) =>
+ val nexus = "https://oss.sonatype.org/"
+ if (v.trim.endsWith("SNAPSHOT"))
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+ }
diff --git a/main/src/test/resources/old-format/11.sbt.txt b/main/src/test/resources/old-format/11.sbt.txt
new file mode 100644
index 000000000..a76615a42
--- /dev/null
+++ b/main/src/test/resources/old-format/11.sbt.txt
@@ -0,0 +1,52 @@
+name := "core"
+
+resolvers += "spray repo" at "http://repo.spray.io"
+
+libraryDependencies ++= Seq(
+ "com.github.scala-incubator.io" %% "scala-io-core" % "0.4.2",
+ "com.github.scala-incubator.io" %% "scala-io-file" % "0.4.2",
+ "com.typesafe.akka" %% "akka-actor" % "2.2.4",
+ "com.typesafe.akka" %% "akka-slf4j" % "2.2.4",
+ "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2",
+ "io.spray" % "spray-client" % "1.2.1",
+ "jline" % "jline" % "2.12",
+ "org.apache.curator" % "curator-recipes" % "2.4.2",
+ "org.apache.zookeeper" % "zookeeper" % "3.4.6",
+ "org.fusesource" % "sigar" % "1.6.4" classifier "native" classifier "",
+ "org.mozilla" % "rhino" % "1.7R4",
+ "org.reactivemongo" %% "play2-reactivemongo" % "0.10.2",
+ "org.reactivemongo" %% "reactivemongo" % "0.10.0",
+ "org.scalaz" %% "scalaz-core" % "7.0.6"
+).map(_.exclude("org.slf4j", "slf4j-log4j12"))
+
+val copyNativeLibraries = taskKey[Set[File]]("Copy native libraries to native libraries directory")
+
+copyNativeLibraries := {
+ val cp = (managedClasspath in Runtime).value
+ // FIXME: Currently, only sigar has a native library.
+ // Extract this as a setting when more native libraries are added.
+ val nativeJarFile = cp.map(_.data).find(_.getName == "sigar-1.6.4-native.jar").get
+ val nativeLibrariesDirectory = target.value / "native_libraries" / (System.getProperty("sun.arch.data.model") + "bits")
+ IO.unzip(nativeJarFile, nativeLibrariesDirectory)
+}
+
+run <<= (run in Runtime) dependsOn copyNativeLibraries
+
+(test in Test) <<= (test in Test) dependsOn copyNativeLibraries
+
+val toolsJar = if (System.getProperty("os.name") != "Mac OS X") {
+ Seq(Attributed.blank(file(System.getProperty("java.home").dropRight(3) + "lib/tools.jar")))
+} else {
+ Nil
+}
+
+// adding the tools.jar to the unmanaged-jars seq
+unmanagedJars in Compile ~= (toolsJar ++ _)
+
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
+
+org.scalastyle.sbt.ScalastylePlugin.Settings
+
+scalariformSettings
+
+Common.settings
diff --git a/main/src/test/resources/old-format/12.sbt.txt b/main/src/test/resources/old-format/12.sbt.txt
new file mode 100644
index 000000000..eb3d1c1c4
--- /dev/null
+++ b/main/src/test/resources/old-format/12.sbt.txt
@@ -0,0 +1,55 @@
+name := "play-recaptcha"
+
+description := "Google reCAPTCHA integration for Play Framework"
+
+organization := "com.nappin"
+
+version := "0.9-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
+
+crossScalaVersions := Seq("2.10.4", "2.11.1")
+
+libraryDependencies ++= Seq(
+ ws,
+ "org.mockito" % "mockito-core" % "1.+" % "test"
+)
+
+// needed to publish to maven central
+publishMavenStyle := true
+
+publishTo := {
+ val nexus = "https://oss.sonatype.org/"
+ if (isSnapshot.value)
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+}
+
+publishArtifact in Test := false
+
+pomIncludeRepository := { _ => false }
+
+pomExtra := (
+ http://chrisnappin.github.io/play-recaptcha
+
+
+ Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+ scm:git:git@github.com:chrisnappin/play-recaptcha.git
+ scm:git:git@github.com:chrisnappin/play-recaptcha.git
+ git@github.com:chrisnappin/play-recaptcha.git
+
+
+
+ chrisnappin
+ Chris Nappin
+ chris@nappin.com
+ UTC
+
+ )
+
\ No newline at end of file
diff --git a/main/src/test/resources/old-format/13.sbt.txt b/main/src/test/resources/old-format/13.sbt.txt
new file mode 100644
index 000000000..12586ccb9
--- /dev/null
+++ b/main/src/test/resources/old-format/13.sbt.txt
@@ -0,0 +1,75 @@
+name := """FTL"""
+
+version := "1.0-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
+
+scalaVersion := "2.11.1"
+
+resolvers += "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
+
+libraryDependencies ++= Seq(
+ jdbc,
+ anorm,
+ cache,
+ ws,
+ filters,
+ "org.webjars" % "bootstrap" % "3.0.2",
+ "com.typesafe.play.plugins" %% "play-plugins-util" % "2.3.0",
+ "com.typesafe.play.plugins" %% "play-plugins-mailer" % "2.3.0",
+ "org.mindrot" % "jbcrypt" % "0.3m",
+ "org.specs2" %% "specs2" % "2.3.12" % "test",
+ "org.mockito" % "mockito-all" % "1.9.5" % "test",
+ "org.reactivemongo" %% "play2-reactivemongo" % "0.11.0-SNAPSHOT",
+ "org.reactivemongo" %% "reactivemongo" % "0.11.0-SNAPSHOT"
+)
+
+resolvers ++= Seq(
+ Resolver.typesafeRepo("releases")
+)
+
+organization := "ws.securesocial"
+
+organizationName := "SecureSocial"
+
+organizationHomepage := Some(new URL("http://www.securesocial.ws"))
+
+publishMavenStyle := true
+
+publishArtifact in Test := false
+
+pomIncludeRepository := { _ => false }
+
+publishTo := {
+ val nexus = "https://oss.sonatype.org/"
+ if (version.value.trim.endsWith("SNAPSHOT"))
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+}
+
+startYear := Some(2012)
+
+description := "An authentication module for Play Framework applications supporting OAuth, OAuth2, OpenID, Username/Password and custom authentication schemes."
+
+licenses := Seq("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt"))
+
+homepage := Some(url("http://www.securesocial.ws"))
+
+pomExtra := (
+
+ https://github.com/jaliss/securesocial
+ scm:git:git@github.com:jaliss/securesocial.git
+ scm:git:https://github.com/jaliss/securesocial.git
+
+
+
+ jaliss
+ Jorge Aliss
+ jaliss [at] gmail.com
+ https://twitter.com/jaliss
+
+
+)
+
+scalacOptions := Seq("-feature", "-deprecation")
diff --git a/main/src/test/resources/old-format/14.sbt.txt b/main/src/test/resources/old-format/14.sbt.txt
new file mode 100644
index 000000000..63c7182a0
--- /dev/null
+++ b/main/src/test/resources/old-format/14.sbt.txt
@@ -0,0 +1,41 @@
+name := "cms"
+
+organization := "org.qirx"
+
+scalaVersion := "2.11.1"
+
+resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases/"
+
+libraryDependencies ++= Seq(
+ "com.typesafe.play" %% "play" % "2.3.0",
+ "com.typesafe.play" %% "play-test" % "2.3.0",
+ "com.typesafe.play" %% "play-json" % "2.3.0",
+ "org.qirx" %% "little-spec" % "0.4-SNAPSHOT" % "test",
+ "org.qirx" %% "little-spec-extra-documentation" % "0.4-SNAPSHOT" % "test"
+)
+
+unmanagedSourceDirectories in Compile := Seq((scalaSource in Compile).value)
+
+unmanagedSourceDirectories in Test := Seq((scalaSource in Test).value)
+
+testFrameworks += new TestFramework("org.qirx.littlespec.sbt.TestFramework")
+
+val x = taskKey[Unit /* Geef niets terug */]("test")
+
+x := {
+ val cacheDir = (streams in x).value.cacheDirectory / "unzipped"
+ val dependencies = (externalDependencyClasspath in Compile).value
+ val possibleJar = dependencies
+ .map(a => a.data)
+ .filter(f => f.getName contains "play-json")
+ .headOption
+ possibleJar match {
+ case Some(file) =>
+ val unzippedFiles = IO.unzip(from = file, toDirectory = cacheDir)
+ // use flatmap because relativize returns an option, which can be flattened
+ val names = unzippedFiles.flatMap(file => IO.relativize(base = cacheDir, file))
+ println(s"Unzipped the following files in `$cacheDir`")
+ names.foreach(println)
+ case None => sys.error("Could not find jar")
+ }
+}
diff --git a/main/src/test/resources/old-format/15.sbt.txt b/main/src/test/resources/old-format/15.sbt.txt
new file mode 100644
index 000000000..dce8e063b
--- /dev/null
+++ b/main/src/test/resources/old-format/15.sbt.txt
@@ -0,0 +1,21 @@
+
+name := "play-html-compressor"
+
+scalaVersion := "2.11.1"
+
+val pom =
+ git@github.com:mohiva/play-html-compressor.git
+ scm:git:git@github.com:mohiva/play-html-compressor.git
+
+
+
+ akkie
+ Christian Kaps
+ http://mohiva.com
+
+
+
+publishMavenStyle := true
+
+
+
diff --git a/main/src/test/resources/old-format/16.sbt.txt b/main/src/test/resources/old-format/16.sbt.txt
new file mode 100644
index 000000000..123e05ab4
--- /dev/null
+++ b/main/src/test/resources/old-format/16.sbt.txt
@@ -0,0 +1,141 @@
+import sbt._
+import AssemblyKeys._
+import aether.Aether._
+
+name := "conjecture"
+
+version := "0.1.2-SNAPSHOT"
+
+organization := "com.etsy"
+
+scalaVersion := "2.9.3"
+
+sbtVersion := "0.12.1"
+
+scalacOptions ++= Seq("-unchecked", "-deprecation")
+
+compileOrder := CompileOrder.JavaThenScala
+
+javaHome := Some(file("/usr/java/latest"))
+
+publishArtifact in packageDoc := false
+
+resolvers ++= {
+ Seq(
+ "Concurrent Maven Repo" at "http://conjars.org/repo",
+ "cloudera" at "https://repository.cloudera.com/artifactory/cloudera-repos/"
+ )
+}
+
+libraryDependencies += "cascading" % "cascading-core" % "2.0.0"
+
+libraryDependencies += "cascading" % "cascading-local" % "2.0.0" exclude("com.google.guava", "guava")
+
+libraryDependencies += "cascading" % "cascading-hadoop" % "2.0.0"
+
+libraryDependencies += "cascading.kryo" % "cascading.kryo" % "0.4.6"
+
+libraryDependencies += "com.google.code.gson" % "gson" % "2.2.2"
+
+libraryDependencies += "com.twitter" % "maple" % "0.2.4"
+
+libraryDependencies += "com.twitter" % "algebird-core_2.9.2" % "0.1.12"
+
+libraryDependencies += "com.twitter" % "scalding-core_2.9.2" % "0.8.5"
+
+libraryDependencies += "commons-lang" % "commons-lang" % "2.4"
+
+libraryDependencies += "com.joestelmach" % "natty" % "0.7"
+
+libraryDependencies += "io.backchat.jerkson" % "jerkson_2.9.2" % "0.7.0"
+
+libraryDependencies += "com.google.guava" % "guava" % "13.0.1"
+
+libraryDependencies += "org.apache.commons" % "commons-math3" % "3.2"
+
+libraryDependencies += "org.apache.hadoop" % "hadoop-common" % "2.0.0-cdh4.1.1" exclude("commons-daemon", "commons-daemon")
+
+libraryDependencies += "org.apache.hadoop" % "hadoop-hdfs" % "2.0.0-cdh4.1.1" exclude("commons-daemon", "commons-daemon")
+
+libraryDependencies += "org.apache.hadoop" % "hadoop-tools" % "2.0.0-mr1-cdh4.1.1" exclude("commons-daemon", "commons-daemon")
+
+libraryDependencies += "net.sf.trove4j" % "trove4j" % "3.0.3"
+
+libraryDependencies += "com.esotericsoftware.kryo" % "kryo" % "2.21"
+
+libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test"
+
+parallelExecution in Test := false
+
+publishArtifact in Test := false
+
+seq(assemblySettings: _*)
+
+publishTo <<= version { v : String =>
+ val nexus = "https://oss.sonatype.org/"
+ if (v.trim.endsWith("SNAPSHOT")) {
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ } else {
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+ }
+}
+
+publishMavenStyle := true
+
+pomIncludeRepository := { x => false }
+
+pomExtra := (
+ https://github.com/etsy/Conjecture
+
+
+ MIT License
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+ git@github.com:etsy/Conjecture.git
+ scm:git:git@github.com:etsy/Conjecture.git
+
+
+
+ jattenberg
+ Josh Attenberg
+ github.com/jattenberg
+
+
+ rjhall
+ Rob Hall
+ github.com/rjhall
+
+
+)
+
+
+credentials += Credentials(Path.userHome / ".sbt" / ".credentials")
+
+
+seq(aetherPublishSettings: _*)
+
+pomIncludeRepository := { _ => false }
+
+// Uncomment if you don't want to run all the tests before building assembly
+// test in assembly := {}
+
+// Janino includes a broken signature, and is not needed:
+excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
+ val excludes = Set("jsp-api-2.1-6.1.14.jar", "jsp-2.1-6.1.14.jar",
+ "jasper-compiler-5.5.12.jar", "janino-2.5.16.jar")
+ cp filter { jar => excludes(jar.data.getName)}
+}
+
+// Some of these files have duplicates, let's ignore:
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
+ {
+ case s if s.endsWith(".class") => MergeStrategy.last
+ case s if s.endsWith("project.clj") => MergeStrategy.concat
+ case s if s.endsWith(".html") => MergeStrategy.last
+ case s if s.contains("servlet") => MergeStrategy.last
+ case x => old(x)
+ }
+}
diff --git a/main/src/test/resources/old-format/17.sbt.txt b/main/src/test/resources/old-format/17.sbt.txt
new file mode 100644
index 000000000..1ade452a0
--- /dev/null
+++ b/main/src/test/resources/old-format/17.sbt.txt
@@ -0,0 +1,52 @@
+name := "Programming Scala, Second Edition: Code examples"
+
+version := "2.0"
+
+organization := "org.programming-scala"
+
+scalaVersion := "2.11.2"
+
+// Build against several versions of Scala
+crossScalaVersions := Seq("2.11.2", "2.10.4")
+
+// Scala 2.11 split the standard library into smaller components.
+// The XML and parser combinator support are now separate jars.
+// I use the if condition to conditionally add these extra dependencies.
+libraryDependencies ++= Seq(
+ "com.typesafe.akka" %% "akka-actor" % "2.3.3",
+ "org.scalaz" %% "scalaz-core" % "7.0.6",
+ "org.scalacheck" %% "scalacheck" % "1.11.4" % "test",
+ "org.scalatest" %% "scalatest" % "2.2.0" % "test",
+ "org.specs2" %% "specs2" % "2.3.12" % "test",
+ // JUnit is used for some Java interop. examples. A driver for JUnit:
+ "junit" % "junit-dep" % "4.10" % "test",
+ "com.novocode" % "junit-interface" % "0.10" % "test"
+) ++ (
+ if (scalaVersion.value startsWith "2.11")
+ Seq(
+ // Could use this to get everything:
+ // "org.scala-lang.modules" %% "scala-library-all" % "2.11.1")
+ "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.1",
+ "org.scala-lang.modules" %% "scala-xml" % "1.0.2")
+ else Seq.empty)
+
+val commonOptions = Seq(
+ "-encoding", "UTF-8", "-optimise",
+ "-deprecation", "-unchecked", "-feature", "-Xlint")
+// "-explaintypes" - Use when you need more detailed messages for type errors.
+// "-Yinline-warnings" - Warns if constructs have the @inline annotation, but
+// inlining isn't possible. Can be more annoying than useful most of the time,
+// but consider using it for performance critical code.
+
+// Options passed to the Scala and Java compilers:
+scalacOptions <<= scalaVersion map { version: String =>
+ if (version.startsWith("2.10")) commonOptions
+ else commonOptions ++ Seq("-Ywarn-infer-any") // Warn if "Any" is inferred
+}
+
+javacOptions ++= Seq(
+ "-Xlint:unchecked", "-Xlint:deprecation") // Java 8: "-Xdiags:verbose")
+
+// Enable improved incremental compilation feature in 2.11.X.
+// see http://www.scala-lang.org/news/2.11.1
+incOptions := incOptions.value.withNameHashing(true)
diff --git a/main/src/test/resources/old-format/18.sbt.txt b/main/src/test/resources/old-format/18.sbt.txt
new file mode 100644
index 000000000..1cc373cb9
--- /dev/null
+++ b/main/src/test/resources/old-format/18.sbt.txt
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2013-2014 Alexey Aksenov ezh@ezh.msk.ru
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+ScriptedPlugin.scriptedSettings
+
+name := "sbt-osgi-manager"
+
+description := "OSGi development bridge based on Bndtools and Tycho."
+
+licenses := Seq("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt"))
+
+organization := "org.digimead"
+
+organizationHomepage := Some(url("http://digimead.org"))
+
+homepage := Some(url("https://github.com/digimead/sbt-osgi-manager"))
+
+version <<= (baseDirectory) { (b) => scala.io.Source.fromFile(b / "version").mkString.trim }
+
+// There is no "-Xfatal-warnings" because we have cross compilation against different Scala versions
+scalacOptions ++= Seq("-encoding", "UTF-8", "-unchecked", "-deprecation", "-Xcheckinit")
+
+// http://vanillajava.blogspot.ru/2012/02/using-java-7-to-target-much-older-jvms.html
+javacOptions ++= Seq("-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6")
+
+javacOptions in doc := Seq("-source", "1.6")
+
+if (sys.env.contains("XBOOTCLASSPATH")) Seq(javacOptions += "-Xbootclasspath:" + sys.env("XBOOTCLASSPATH")) else Seq()
+
+sbtPlugin := true
+
+resourceGenerators in Compile <+=
+ (resourceManaged in Compile, name, version) map { (dir, n, v) =>
+ val file = dir / "version-%s.properties".format(n)
+ val contents = "name=%s\nversion=%s\nbuild=%s\n".format(n, v, ((System.currentTimeMillis / 1000).toInt).toString)
+ IO.write(file, contents)
+ Seq(file)
+ }
+
+libraryDependencies ++= {
+ val mavenVersion = "3.0" // based on Tycho, MUST be the same
+ val mavenWagonVersion = "2.4"
+ val tychoVersion = "0.18.0"
+ val aetherAPIVersion = "1.7" // based on Tycho, MUST be the same
+ Seq(
+ "biz.aQute.bnd" % "bndlib" % "2.1.0",
+ "org.apache.felix" % "org.apache.felix.resolver" % "1.0.0",
+ "org.apache.maven" % "maven-aether-provider" % mavenVersion,
+ "org.apache.maven" % "maven-artifact" % mavenVersion,
+ "org.apache.maven" % "maven-compat" % mavenVersion,
+ "org.apache.maven" % "maven-core" % mavenVersion,
+ "org.apache.maven" % "maven-plugin-api" % mavenVersion,
+ "org.apache.maven" % "maven-embedder" % mavenVersion, // provide org.apache.maven.cli.MavenCli
+ "org.apache.maven.wagon" % "wagon-http" % mavenWagonVersion, // HTTP connector for remore repositories
+ "org.apache.maven.wagon" % "wagon-file" % mavenWagonVersion, // File connector for local repositories
+ "org.eclipse.tycho" % "tycho-core" % tychoVersion,
+ "org.eclipse.tycho" % "tycho-p2-facade" % tychoVersion,
+ "org.osgi" % "org.osgi.core" % "5.0.0",
+ "org.osgi" % "org.osgi.enterprise" % "5.0.0",
+ "org.sonatype.aether" % "aether-connector-wagon" % aetherAPIVersion
+ )
+}
+
+scriptedBufferLog := false
+
+resolvers ++= Seq(
+ "sbt-osgi-mananger-digimead-maven" at "http://storage.googleapis.com/maven.repository.digimead.org/",
+ Resolver.url("sbt-osgi-manager-typesafe-ivy-releases", url("http://repo.typesafe.com/typesafe/ivy-releases/"))(Resolver.defaultIvyPatterns),
+ Resolver.url("sbt-osgi-manager-typesafe-ivy-snapshots", url("http://repo.typesafe.com/typesafe/ivy-snapshots/"))(Resolver.defaultIvyPatterns),
+ Resolver.url("sbt-osgi-manager-typesafe-repository", url("http://typesafe.artifactoryonline.com/typesafe/ivy-releases/"))(Resolver.defaultIvyPatterns),
+ Resolver.url("sbt-osgi-manager-typesafe-shapshots", url("http://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/"))(Resolver.defaultIvyPatterns))
+
+sourceGenerators in Compile <+= (sbtVersion, sourceDirectory in Compile, sourceManaged in Compile) map { (v, sourceDirectory, sourceManaged) =>
+ val interface = v.split("""\.""").take(2).mkString(".")
+ val source = sourceDirectory / ".." / "patch" / interface
+ val generated = (PathFinder(source) ***) x Path.rebase(source, sourceManaged)
+ IO.copy(generated, true, false)
+ generated.map(_._2).filter(_.getName endsWith ".scala")
+}
+
+//logLevel := Level.Debug
diff --git a/main/src/test/resources/old-format/19.sbt.txt b/main/src/test/resources/old-format/19.sbt.txt
new file mode 100644
index 000000000..700cdfcd0
--- /dev/null
+++ b/main/src/test/resources/old-format/19.sbt.txt
@@ -0,0 +1,2 @@
+//import sbt._
+// val a = 3
\ No newline at end of file
diff --git a/main/src/test/resources/old-format/2.sbt.txt b/main/src/test/resources/old-format/2.sbt.txt
new file mode 100644
index 000000000..9ac625267
--- /dev/null
+++ b/main/src/test/resources/old-format/2.sbt.txt
@@ -0,0 +1,39 @@
+import AssemblyKeys._
+
+name := "s3_website"
+
+version := "0.0.1"
+
+scalaVersion := "2.11.2"
+
+scalacOptions += "-feature"
+
+scalacOptions += "-language:implicitConversions"
+
+scalacOptions += "-language:postfixOps"
+
+scalacOptions += "-target:jvm-1.6"
+
+libraryDependencies += "org.yaml" % "snakeyaml" % "1.13"
+
+libraryDependencies += "org.jruby" % "jruby" % "1.7.11"
+
+libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.7.7"
+
+libraryDependencies += "log4j" % "log4j" % "1.2.17"
+
+libraryDependencies += "commons-codec" % "commons-codec" % "1.9"
+
+libraryDependencies += "commons-io" % "commons-io" % "2.4"
+
+libraryDependencies += "org.apache.tika" % "tika-core" % "1.4"
+
+libraryDependencies += "com.lexicalscope.jewelcli" % "jewelcli" % "0.8.9"
+
+libraryDependencies += "org.specs2" %% "specs2" % "2.3.11" % "test"
+
+resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
+
+jarName in assembly := "s3_website.jar"
+
+test in assembly := {}
diff --git a/main/src/test/resources/old-format/20.sbt.txt b/main/src/test/resources/old-format/20.sbt.txt
new file mode 100644
index 000000000..33a460719
--- /dev/null
+++ b/main/src/test/resources/old-format/20.sbt.txt
@@ -0,0 +1,18 @@
+
+/* */
+/** Project */
+name := "signal-collect-yarn"
+/* */
+
+/*
+AAA
+*/
+val a = 3
+// OK
+
+libraryDependencies ++= Seq("org.scala-lang" % "scala-compiler" % "2.10.4") map {
+ (dependency) =>{
+ dependency
+ } /* OK */
+}
+
diff --git a/main/src/test/resources/old-format/3.sbt.txt b/main/src/test/resources/old-format/3.sbt.txt
new file mode 100644
index 000000000..3775200ff
--- /dev/null
+++ b/main/src/test/resources/old-format/3.sbt.txt
@@ -0,0 +1,51 @@
+parallelExecution in Global := false
+
+val commonSettings = Seq(
+ organization := "com.github.germanosin",
+ version := "1.0",
+ javacOptions in Compile ++= Seq("-source", "1.6", "-target", "1.6"),
+ scalaVersion := "2.11.1"
+)
+
+lazy val foldermessages = project.settings(commonSettings: _*)
+ .settings(
+ name := "play-foldermessages",
+ crossScalaVersions := Seq("2.10.4", "2.11.1"),
+ libraryDependencies += "com.typesafe.play" %% "play" % "2.3.2",
+ resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases/",
+ publishMavenStyle := true,
+ publishTo := {
+ val nexus = "https://oss.sonatype.org"
+ if (isSnapshot.value) Some("snapshots" at s"$nexus/content/repositories/snapshots")
+ else Some("releases" at s"$nexus/service/local/staging/deploy/maven2")
+ },
+ pomExtra := (
+ http://github.com/germanosin/play-foldermessages
+
+
+ MIT License
+ http://opensource.org/licenses/mit-license.php
+
+
+
+ git@github.com:germanosin/play-foldermessages.git
+ scm:git:git@github.com:germanosin/play-foldermessages.git
+
+
+
+ germanosin
+ German Osin
+
+
+ ),
+ useGpg := true
+ )
+
+lazy val sampleApp = Project("sample-app", file("sample-app"))
+ .settings(commonSettings: _*)
+ .enablePlugins(PlayScala)
+ .dependsOn(foldermessages)
+
+lazy val playFolderMessages = project.in(file("."))
+ .settings(commonSettings: _*)
+ .aggregate(foldermessages,sampleApp)
\ No newline at end of file
diff --git a/main/src/test/resources/old-format/4.sbt.txt b/main/src/test/resources/old-format/4.sbt.txt
new file mode 100644
index 000000000..b3cae41bd
--- /dev/null
+++ b/main/src/test/resources/old-format/4.sbt.txt
@@ -0,0 +1,74 @@
+import AssemblyKeys._
+assemblySettings
+
+/** Project */
+name := "signal-collect-yarn"
+
+version := "1.0-SNAPSHOT"
+
+organization := "com.signalcollect"
+
+scalaVersion := "2.11.1"
+
+val hadoopVersion = "2.3.0"
+
+net.virtualvoid.sbt.graph.Plugin.graphSettings
+
+scalacOptions ++= Seq("-optimize", "-Yinline-warnings", "-feature", "-deprecation", "-Xelide-below", "INFO" )
+
+EclipseKeys.createSrc := EclipseCreateSrc.Default + EclipseCreateSrc.Resource
+
+EclipseKeys.withSource := true
+
+parallelExecution in Test := false
+
+test in assembly := {}
+
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
+ {
+ case PathList("org", "apache", "hadoop", xs @ _*) => MergeStrategy.last
+ case PathList("org", "apache", "commons", "collections", xs @ _*) => MergeStrategy.last
+ case PathList("org", "objectweb", "asm", xs @ _*) => MergeStrategy.last
+ case PathList("com", "thoughtworks", xs @ _*) => MergeStrategy.last
+ case PathList("META-INF", "maven", xs @ _*) => MergeStrategy.last
+ case PathList("log4j.properties") => MergeStrategy.last
+ case x => old(x)
+ }
+}
+
+excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
+ cp filter { entry =>
+ (entry.data.getName == "asm-3.2.jar" ||
+ entry.data.getName == "asm-3.1.jar"
+ )}
+}
+
+/** Dependencies */
+libraryDependencies ++= Seq(
+ "org.scala-lang.modules" %% "scala-async" % "0.9.1",
+ "org.scala-lang" % "scala-library" % "2.11.1" % "compile",
+ ("org.apache.hadoop" % "hadoop-common" % hadoopVersion % "compile").
+ exclude("commons-beanutils", "commons-beanutils-core"),
+ "org.apache.hadoop" % "hadoop-yarn-common" % hadoopVersion % "compile",
+ ("org.apache.hadoop" % "hadoop-yarn-client" % hadoopVersion % "compile").
+ exclude("hadoop-yarn-api", "org.apache.hadoop"),
+ "org.apache.hadoop" % "hadoop-yarn-server-resourcemanager" % hadoopVersion % "compile",
+ "org.apache.hadoop" % "hadoop-yarn-server-nodemanager" % hadoopVersion % "compile",
+ "org.apache.hadoop" % "minicluster" % "2.2.0" ,
+ "org.apache.hadoop" % "hadoop-hdfs" % hadoopVersion,
+ "com.github.romix.akka" %% "akka-kryo-serialization-custom" % "0.3.5" % "compile",
+ "com.amazonaws" % "aws-java-sdk" % "1.7.12" % "compile",
+ "com.jcraft" % "jsch" % "0.1.51" % "compile",
+ "org.apache.commons" % "commons-compress" % "1.5" % "compile",
+ "log4j" % "log4j" % "1.2.17" % "compile",
+ "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2",
+ "com.typesafe.akka" % "akka-slf4j_2.11" % "2.3.4",
+ "junit" % "junit" % "4.8.2" % "test",
+ "org.specs2" %% "specs2" % "2.3.11" % "test",
+ "org.scalacheck" %% "scalacheck" % "1.11.3" % "test",
+ "org.scalatest" %% "scalatest" % "2.1.3" % "test",
+ "org.easymock" % "easymock" % "3.2" % "test",
+ "com.typesafe.akka" %% "akka-remote" % "2.3.4" force()
+)
+
+resolvers += "Ifi Public" at "https://maven.ifi.uzh.ch/maven2/content/groups/public/"
diff --git a/main/src/test/resources/old-format/5.sbt.txt b/main/src/test/resources/old-format/5.sbt.txt
new file mode 100644
index 000000000..938093ca7
--- /dev/null
+++ b/main/src/test/resources/old-format/5.sbt.txt
@@ -0,0 +1,41 @@
+sbtPlugin := true
+
+name := "sbt-docker"
+
+organization := "se.marcuslonnberg"
+
+organizationHomepage := Some(url("https://github.com/marcuslonnberg"))
+
+version := "0.6.0-SNAPSHOT"
+
+libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.0" % "test"
+
+licenses := Seq("MIT License" -> url("https://github.com/marcuslonnberg/sbt-docker/blob/master/LICENSE"))
+
+homepage := Some(url("https://github.com/marcuslonnberg/sbt-docker"))
+
+scmInfo := Some(ScmInfo(url("https://github.com/marcuslonnberg/sbt-docker"), "scm:git:git://github.com:marcuslonnberg/sbt-docker.git"))
+
+scalacOptions := Seq("-deprecation", "-unchecked", "-feature")
+
+publishMavenStyle := true
+
+publishTo := {
+ val nexus = "https://oss.sonatype.org/"
+ if (isSnapshot.value)
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+}
+
+pomIncludeRepository := { _ => false}
+
+pomExtra := (
+
+
+ marcuslonnberg
+ Marcus Lönnberg
+ http://marcuslonnberg.se
+
+
+)
diff --git a/main/src/test/resources/old-format/6.sbt.txt b/main/src/test/resources/old-format/6.sbt.txt
new file mode 100644
index 000000000..b90ea4af2
--- /dev/null
+++ b/main/src/test/resources/old-format/6.sbt.txt
@@ -0,0 +1,67 @@
+organization := "com.sksamuel.akka"
+
+name := "akka-patterns"
+
+version := "0.11.0"
+
+scalaVersion := "2.11.2"
+
+crossScalaVersions := Seq("2.11.2", "2.10.4")
+
+scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
+
+javacOptions ++= Seq("-source", "1.6", "-target", "1.6")
+
+publishTo <<= version {
+ (v: String) =>
+ val nexus = "https://oss.sonatype.org/"
+ if (v.trim.endsWith("SNAPSHOT"))
+ Some("snapshots" at nexus + "content/repositories/snapshots")
+ else
+ Some("releases" at nexus + "service/local/staging/deploy/maven2")
+}
+
+publishMavenStyle := true
+
+publishArtifact in Test := false
+
+parallelExecution in Test := false
+
+credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
+
+libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.3"
+
+libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.3.3"
+
+libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.7"
+
+libraryDependencies += "org.slf4j" % "log4j-over-slf4j" % "1.7.7" % "test"
+
+libraryDependencies += "log4j" % "log4j" % "1.2.17" % "test"
+
+libraryDependencies += "commons-io" % "commons-io" % "2.4"
+
+libraryDependencies += "org.mockito" % "mockito-all" % "1.9.5" % "test"
+
+libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.0" % "test"
+
+pomExtra := (
+ https://github.com/sksamuel/akka-patterns
+
+
+ Apache 2
+ http://www.apache.org/licenses/LICENSE-2.0
+ repo
+
+
+
+ git@github.com:sksamuel/akka-patterns.git
+ scm:git@github.com:sksamuel/akka-patterns.git
+
+
+
+ sksamuel
+ sksamuel
+ http://github.com/akka-patterns
+
+ )
diff --git a/main/src/test/resources/old-format/7.sbt.txt b/main/src/test/resources/old-format/7.sbt.txt
new file mode 100644
index 000000000..58165b827
--- /dev/null
+++ b/main/src/test/resources/old-format/7.sbt.txt
@@ -0,0 +1,160 @@
+name <<= submitProjectName(pname => "progfun-"+ pname)
+
+version := "1.0.0"
+
+scalaVersion := "2.10.2"
+
+scalacOptions ++= Seq("-deprecation", "-feature")
+
+libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1" % "test"
+
+libraryDependencies += "junit" % "junit" % "4.10" % "test"
+
+libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.10.2"
+
+// This setting defines the project to which a solution is submitted. When creating a
+// handout, the 'createHandout' task will make sure that its value is correct.
+submitProjectName := "suggestions"
+
+libraryDependencies <++= (currentProject) { c =>
+ if (c.isEmpty || c == "quickcheck") Seq(
+ "org.scalacheck" %% "scalacheck" % "1.10.1"
+ )
+ else Seq.empty
+}
+
+libraryDependencies <++= (currentProject) { c =>
+ if (c.isEmpty || c == "nodescala" || c == "suggestions") Seq(
+ "com.netflix.rxjava" % "rxjava-scala" % "0.15.0",
+ "org.json4s" % "json4s-native_2.10" % "3.2.5",
+ "org.scala-lang" % "scala-swing" % "2.10.3",
+ "net.databinder.dispatch" % "dispatch-core_2.10" % "0.11.0",
+ "org.scala-lang" % "scala-reflect" % "2.10.3",
+ "org.slf4j" % "slf4j-api" % "1.7.5",
+ "org.slf4j" % "slf4j-simple" % "1.7.5",
+ "com.squareup.retrofit" % "retrofit" % "1.0.0",
+ "org.scala-lang.modules" %% "scala-async" % "0.9.0-M2"
+ )
+ else Seq.empty
+}
+
+libraryDependencies <++= (currentProject) { c =>
+ if (c.isEmpty || c == "actorbintree") Seq(
+ "com.typesafe.akka" %% "akka-actor" % "2.2.3",
+ "com.typesafe.akka" %% "akka-testkit" % "2.2.3"
+ )
+ else Seq.empty
+}
+
+// See documentation in ProgFunBuild.scala
+projectDetailsMap := {
+val currentCourseId = "reactive-001"
+Map(
+ "example" -> ProjectDetails(
+ packageName = "example",
+ assignmentPartId = "fTzFogNl",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "recfun" -> ProjectDetails(
+ packageName = "recfun",
+ assignmentPartId = "3Rarn9Ki",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "funsets" -> ProjectDetails(
+ packageName = "funsets",
+ assignmentPartId = "fBXOL6Rd",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "objsets" -> ProjectDetails(
+ packageName = "objsets",
+ assignmentPartId = "05dMMEz7",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "patmat" -> ProjectDetails(
+ packageName = "patmat",
+ assignmentPartId = "4gPmpcif",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "forcomp" -> ProjectDetails(
+ packageName = "forcomp",
+ assignmentPartId = "fG2oZGIO",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "streams" -> ProjectDetails(
+ packageName = "streams",
+ assignmentPartId = "DWKgCFCi",
+ maxScore = 10d,
+ styleScoreRatio = 0.2,
+ courseId=currentCourseId),
+ "quickcheck" -> ProjectDetails(
+ packageName = "quickcheck",
+ assignmentPartId = "02Vi5q7m",
+ maxScore = 10d,
+ styleScoreRatio = 0.0,
+ courseId=currentCourseId),
+ "simulations" -> ProjectDetails(
+ packageName = "simulations",
+ assignmentPartId = "pA3TAeu1",
+ maxScore = 10d,
+ styleScoreRatio = 0.0,
+ courseId=currentCourseId),
+ "nodescala" -> ProjectDetails(
+ packageName = "nodescala",
+ assignmentPartId = "RvoTAbRy",
+ maxScore = 10d,
+ styleScoreRatio = 0.0,
+ courseId=currentCourseId),
+ "suggestions" -> ProjectDetails(
+ packageName = "suggestions",
+ assignmentPartId = "rLLdQLGN",
+ maxScore = 10d,
+ styleScoreRatio = 0.0,
+ courseId=currentCourseId),
+ "actorbintree" -> ProjectDetails(
+ packageName = "actorbintree",
+ assignmentPartId = "VxIlIKoW",
+ maxScore = 10d,
+ styleScoreRatio = 0.0,
+ courseId=currentCourseId)
+)}
+
+// Files that we hand out to the students
+handoutFiles <<= (baseDirectory, projectDetailsMap, commonSourcePackages) map { (basedir, detailsMap, commonSrcs) =>
+ (projectName: String) => {
+ val details = detailsMap.getOrElse(projectName, sys.error("Unknown project name: "+ projectName))
+ val commonFiles = (PathFinder.empty /: commonSrcs)((files, pkg) =>
+ files +++ (basedir / "src" / "main" / "scala" / pkg ** "*.scala")
+ )
+ (basedir / "src" / "main" / "scala" / details.packageName ** "*.scala") +++
+ commonFiles +++
+ (basedir / "src" / "main" / "resources" / details.packageName ** "*") +++
+ (basedir / "src" / "test" / "scala" / details.packageName ** "*.scala") +++
+ (basedir / "build.sbt") +++
+ (basedir / "project" / "build.properties") +++
+ (basedir / "project" ** ("*.scala" || "*.sbt")) +++
+ (basedir / "project" / "scalastyle_config.xml") +++
+ (basedir / "project" / "scalastyle_config_reactive.xml") +++
+ (basedir / "lib_managed" ** "*.jar") +++
+ (basedir * (".classpath" || ".project")) +++
+ (basedir / ".settings" / "org.scala-ide.sdt.core.prefs")
+ }
+}
+
+// This setting allows to restrict the source files that are compiled and tested
+// to one specific project. It should be either the empty string, in which case all
+// projects are included, or one of the project names from the projectDetailsMap.
+currentProject := ""
+
+// Packages in src/main/scala that are used in every project. Included in every
+// handout, submission.
+commonSourcePackages += "common"
+
+// Packages in src/test/scala that are used for grading projects. Always included
+// compiling tests, grading a project.
+gradingTestPackages += "grading"
diff --git a/main/src/test/resources/old-format/8.sbt.txt b/main/src/test/resources/old-format/8.sbt.txt
new file mode 100644
index 000000000..1b7b57283
--- /dev/null
+++ b/main/src/test/resources/old-format/8.sbt.txt
@@ -0,0 +1,55 @@
+name := "apidoc"
+
+scalaVersion in ThisBuild := "2.11.1"
+
+lazy val core = project
+ .in(file("core"))
+ .settings(commonSettings: _*)
+ .settings(
+ // play-json needs this to resolve correctly when not using Gilt's internal mirrors
+ resolvers += "Typesafe Maven Repository" at "http://repo.typesafe.com/typesafe/maven-releases/",
+ version := "1.0-SNAPSHOT",
+ libraryDependencies ++= Seq(
+ "com.typesafe.play" %% "play-json" % "2.3.0"
+ )
+ )
+
+lazy val api = project
+ .in(file("api"))
+ .dependsOn(core)
+ .aggregate(core)
+ .enablePlugins(PlayScala)
+ .settings(commonSettings: _*)
+ .settings(
+ version := "1.0-SNAPSHOT",
+ libraryDependencies ++= Seq(
+ jdbc,
+ anorm,
+ "org.postgresql" % "postgresql" % "9.3-1101-jdbc4",
+ "org.mindrot" % "jbcrypt" % "0.3m"
+ )
+ )
+
+lazy val www = project
+ .in(file("www"))
+ .dependsOn(core)
+ .aggregate(core)
+ .enablePlugins(PlayScala)
+ .settings(commonSettings: _*)
+ .settings(
+ version := "1.0-SNAPSHOT",
+ libraryDependencies ++= Seq(
+ ws
+ )
+ )
+
+lazy val commonSettings: Seq[Setting[_]] = Seq(
+ name <<= name("apidoc-" + _),
+ libraryDependencies ++= Seq(
+ "org.scalatest" %% "scalatest" % "2.2.0" % "test"
+ ),
+ scalacOptions += "-feature"
+) ++ instrumentSettings ++ Seq(ScoverageKeys.highlighting := true)
+
+
+
diff --git a/main/src/test/resources/old-format/9.sbt.txt b/main/src/test/resources/old-format/9.sbt.txt
new file mode 100644
index 000000000..b54ccbf27
--- /dev/null
+++ b/main/src/test/resources/old-format/9.sbt.txt
@@ -0,0 +1,40 @@
+organization := "com.typesafe"
+
+name := "jse"
+
+version := "1.0.1-SNAPSHOT"
+
+scalaVersion := "2.10.4"
+
+libraryDependencies ++= Seq(
+ "com.typesafe.akka" %% "akka-actor" % "2.3.2",
+ "com.typesafe.akka" %% "akka-contrib" % "2.3.2",
+ "io.apigee.trireme" % "trireme-core" % "0.8.0",
+ "io.apigee.trireme" % "trireme-node10src" % "0.8.0",
+ "io.spray" %% "spray-json" % "1.2.6",
+ "org.slf4j" % "slf4j-simple" % "1.7.7",
+ "org.specs2" %% "specs2" % "2.3.11" % "test",
+ "junit" % "junit" % "4.11" % "test",
+ "com.typesafe.akka" %% "akka-testkit" % "2.3.2" % "test"
+)
+
+resolvers ++= Seq(
+ Resolver.sonatypeRepo("snapshots"),
+ "Typesafe Releases Repository" at "http://repo.typesafe.com/typesafe/releases/"
+)
+
+publishTo := {
+ val typesafe = "http://private-repo.typesafe.com/typesafe/"
+ val (name, url) = if (isSnapshot.value)
+ ("sbt-plugin-snapshots", typesafe + "maven-snapshots")
+ else
+ ("sbt-plugin-releases", typesafe + "maven-releases")
+ Some(Resolver.url(name, new URL(url)))
+}
+
+lazy val root = project in file(".")
+
+lazy val `js-engine-tester` = project.dependsOn(root)
+
+// Somehow required to get a js engine in tests (https://github.com/sbt/sbt/issues/1214)
+fork in Test := true
diff --git a/main/src/test/scala/PluginCommandTest.scala b/main/src/test/scala/PluginCommandTest.scala
index c118a5232..322bc08aa 100644
--- a/main/src/test/scala/PluginCommandTest.scala
+++ b/main/src/test/scala/PluginCommandTest.scala
@@ -8,7 +8,7 @@ object PluginCommandTestPlugin0 extends AutoPlugin
package subpackage {
-object PluginCommandTestPlugin1 extends AutoPlugin
+ object PluginCommandTestPlugin1 extends AutoPlugin
}
diff --git a/main/src/test/scala/sbt/AbstractSpec.scala b/main/src/test/scala/sbt/AbstractSpec.scala
new file mode 100644
index 000000000..28551eb74
--- /dev/null
+++ b/main/src/test/scala/sbt/AbstractSpec.scala
@@ -0,0 +1,5 @@
+package sbt
+
+import org.specs2.mutable._
+
+trait AbstractSpec extends Specification with SplitExpression
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/CheckIfParsedSpec.scala b/main/src/test/scala/sbt/CheckIfParsedSpec.scala
new file mode 100644
index 000000000..45f9c5c1a
--- /dev/null
+++ b/main/src/test/scala/sbt/CheckIfParsedSpec.scala
@@ -0,0 +1,36 @@
+package sbt
+
+abstract class CheckIfParsedSpec(implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions) extends AbstractSpec {
+
+ this.getClass.getName should {
+
+ "Parse sbt file " in {
+ foreach(files) {
+ case (content, description, nonEmptyImports, nonEmptyStatements) =>
+ println(s"""${getClass.getSimpleName}: "$description" """)
+ val (imports, statements) = split(content)
+
+ statements.nonEmpty must be_==(nonEmptyStatements)
+ // orPending(s"""$description
+ // |***${shouldContains(nonEmptyStatements)} statements***
+ // |$content """.stripMargin)
+
+ imports.nonEmpty must be_==(nonEmptyImports)
+ // orPending(s"""$description
+ // |***${shouldContains(nonEmptyImports)} imports***
+ // |$content """.stripMargin)
+ }
+ }
+ }
+
+ // private def shouldContains(b: Boolean) = s"""Should ${
+ // if (b) {
+ // "contain"
+ // } else {
+ // "not contain"
+ // }
+ // }"""
+
+ protected def files: Seq[(String, String, Boolean, Boolean)]
+
+}
diff --git a/main/src/test/scala/sbt/CommentedXmlSpec.scala b/main/src/test/scala/sbt/CommentedXmlSpec.scala
new file mode 100644
index 000000000..6ddb30ed6
--- /dev/null
+++ b/main/src/test/scala/sbt/CommentedXmlSpec.scala
@@ -0,0 +1,67 @@
+package sbt
+
+class CommentedXmlSpec extends CheckIfParsedSpec {
+
+ override protected def files: Seq[(String, String, Boolean, Boolean)] = Seq(
+ (
+ s"""|
+ |val pom = ""
+ |
+ |val aaa= git@github.com:mohiva/play.git
+ | ewrer
+ |
+ |
+ |val tra = ""
+ |
+ """.stripMargin, "Xml in string", false, true),
+ ("""
+ |val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
+ |
+ |scmpom :=
+ | git@github.com:mohiva/play-html-compressor.git
+ | scm:git:git@github.com:mohiva/play-html-compressor.git
+ |
+ |
+ |
+ | akkie
+ | Christian Kaps
+ | http://mohiva.com
+ |
+ |
+ | //
+ |
+ |
+ |publishMavenStyle := true
+ |
+ """.stripMargin, "Wrong Commented xml ", false, true),
+ ("""
+ |val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
+ |
+ |scmpom :=
+ | git@github.com:mohiva/play-html-compressor.git
+ | scm:git:git@github.com:mohiva/play-html-compressor.git
+ |
+ |
+ |
+ | akkie
+ | Christian Kaps
+ | http://mohiva.com
+ |
+ |
+ | //
+ | //
+ |
+ |publishMavenStyle := true
+ |
+ """.stripMargin, "Commented xml ", false, true),
+ ("""
+ |import sbt._
+ |
+ |//
+ """.stripMargin, "Xml in comment2", false, false)
+
+ )
+}
diff --git a/main/src/test/scala/sbt/EmbeddedXmlSpec.scala b/main/src/test/scala/sbt/EmbeddedXmlSpec.scala
new file mode 100644
index 000000000..4c207179f
--- /dev/null
+++ b/main/src/test/scala/sbt/EmbeddedXmlSpec.scala
@@ -0,0 +1,143 @@
+package sbt
+
+class EmbeddedXmlSpec extends CheckIfParsedSpec {
+
+ "File with xml content " should {
+
+ "Handle last xml part" in {
+ val errorLine = """4.0"""
+ val buildSbt = s"""|
+ |
+ |name := "play-html-compressor"
+ |
+ |scalaVersion := "2.11.1"
+ |
+ |val pom =
+ |git@github.com:mhiva/play-html-compressor.git
+ |scm:git:git@github.com:mohiva/play-html-compressor.git
+ |
+ |
+ |
+ | akkie
+ | Christian Kaps
+ | http://mohiva.com
+ |
+ |
+ |$errorLine
+ |
+ |""".stripMargin
+
+ split(buildSbt) must throwA[MessageOnlyException].like {
+ case exception =>
+ val index = buildSbt.lines.indexWhere(line => line.contains(errorLine)) + 1
+ val numberRegex = """(\d+)""".r
+ val message = exception.getMessage
+ val list = numberRegex.findAllIn(message).toList
+ list must contain(index.toString)
+ }
+
+ }
+
+ }
+
+ protected val files = Seq(
+ ("""
+ |val p =
+ """.stripMargin, "Xml modified closing tag at end of file", false, true),
+ ("""
+ |val p =
+ """.stripMargin, "Xml at end of file", false, true),
+ ("""|
+ |
+ |name := "play-html-compressor"
+ |
+ |scalaVersion := "2.11.1"
+ |
+ |val lll = "=+=>"
+ |
+ |val not = ""
+ |
+ |val aaa = "ass/>"
+ |
+ |val pom = ""
+ |
+ |val aaa= git@github.com:mohiva/play-html-compressor.git
+ | scm:git:git@github.com:mohiva/play-html-compressor.git
+ |
+ |
+ |
+ | akkie
+ | Christian Kaps
+ | http://mohiva.com
+ |
+ |
+ | 4.0
+ |
+ |publishMavenStyle := true
+ |
+ |val anotherXml =
+ | content
+ |
+ |
+ |
+ |
+ |val tra = ""
+ |
+ """.stripMargin, "Xml in string", false, true),
+ ("""|
+ |
+ |name := "play-html-compressor"
+ |
+ |scalaVersion := "2.11.1"
+ |
+ |val ok =
+ |
+ |val pom =
+ |git@github.com:mhiva/play-html-compressor.git
+ | scm:git:git@github.com:mohiva/play-html-compressor.git
+ |
+ |
+ |
+ |akkie
+ |Christian Kaps
+ |http://mohiva.com
+ |
+ |
+ |4.0
+ |
+ |publishMavenStyle := true
+ |
+ |val anotherXml =
+ | content
+ |
+ |
+ |
+ |
+ | """.stripMargin, "Xml with attributes", false, true),
+ (
+ """
+ |scalaVersion := "2.10.2"
+ |
+ |libraryDependencies += "org.scala-sbt" %% "sbinary" % "0.4.1" withSources() withJavadoc()
+ |
+ |lazy val checkPom = taskKey[Unit]("check pom to ensure no sections are generated")
+ |
+ |checkPom := {
+ | val pomFile = makePom.value
+ | val pom = xml.XML.loadFile(pomFile)
+ | val tpe = pom \\ "type"
+ | if(!tpe.isEmpty)
+ | error("Expected no sections, got: " + tpe + " in \n\n" + pom)
+ |}
+ |
+ |
+ |val a =
+ |
+ |
+ |
+ |
+ |
+ """.stripMargin, "xml with blank line", false, true)
+ )
+
+}
diff --git a/main/src/test/scala/sbt/ErrorSpec.scala b/main/src/test/scala/sbt/ErrorSpec.scala
new file mode 100644
index 000000000..15737f47c
--- /dev/null
+++ b/main/src/test/scala/sbt/ErrorSpec.scala
@@ -0,0 +1,61 @@
+package sbt
+
+import java.io.File
+
+import org.scalacheck.Gen._
+import org.scalacheck.Prop._
+import org.specs2.ScalaCheck
+
+import scala.io.Source
+
+class ErrorSpec extends AbstractSpec with ScalaCheck {
+ implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
+
+ "Parser " should {
+
+ "contains file name and line number" in {
+ val rootPath = getClass.getResource("").getPath + "../error-format/"
+ println(s"Reading files from: $rootPath")
+ foreach(new File(rootPath).listFiles) { file =>
+ print(s"Processing ${file.getName}: ")
+ val buildSbt = Source.fromFile(file).getLines().mkString("\n")
+ SplitExpressionsNoBlankies(file, buildSbt.lines.toSeq) must throwA[MessageOnlyException].like {
+ case exp =>
+ val message = exp.getMessage
+ println(s"${exp.getMessage}")
+ message must contain(file.getName)
+ }
+ containsLineNumber(buildSbt)
+ }
+ }
+
+ "handle wrong parsing " in {
+ val buildSbt =
+ """
+ |libraryDependencies ++= Seq("a" % "b" % "2") map {
+ |(dependency) =>{
+ | dependency
+ | } /* */ //
+ |}
+ """.stripMargin
+ BugInParser.tryWithNextStatement(buildSbt, buildSbt.length, 2, "fake.txt", new MessageOnlyException("fake")) must throwA[MessageOnlyException]
+ }
+ }
+
+ private def containsLineNumber(buildSbt: String) = {
+ try {
+ split(buildSbt)
+ throw new IllegalStateException(s"${classOf[MessageOnlyException].getName} expected")
+ } catch {
+ case exception: MessageOnlyException =>
+ val error = exception.getMessage
+ """(\d+)""".r.findFirstIn(error) match {
+ case Some(x) =>
+ true
+ case None =>
+ println(s"Number not found in $error")
+ false
+ }
+ }
+ }
+}
diff --git a/main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala b/main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala
new file mode 100644
index 000000000..dfa3a2420
--- /dev/null
+++ b/main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala
@@ -0,0 +1,39 @@
+package sbt
+
+import java.io.File
+
+import scala.annotation.tailrec
+
+object EvaluateConfigurationsOriginal {
+
+ private[this] def isSpace = (c: Char) => Character isWhitespace c
+ private[this] def fstS(f: String => Boolean): ((String, Int)) => Boolean = { case (s, i) => f(s) }
+ private[this] def firstNonSpaceIs(lit: String) = (_: String).view.dropWhile(isSpace).startsWith(lit)
+ private[this] def or[A](a: A => Boolean, b: A => Boolean): A => Boolean = in => a(in) || b(in)
+
+ def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) =
+ {
+ val blank = (_: String).forall(isSpace)
+ val isImport = firstNonSpaceIs("import ")
+ val comment = firstNonSpaceIs("//")
+ val blankOrComment = or(blank, comment)
+ val importOrBlank = fstS(or(blankOrComment, isImport))
+
+ val (imports, settings) = lines.zipWithIndex span importOrBlank
+ (imports filterNot fstS(blankOrComment), groupedLines(settings, blank, blankOrComment))
+ }
+
+ def groupedLines(lines: Seq[(String, Int)], delimiter: String => Boolean, skipInitial: String => Boolean): Seq[(String, LineRange)] =
+ {
+ val fdelim = fstS(delimiter)
+ @tailrec def group0(lines: Seq[(String, Int)], accum: Seq[(String, LineRange)]): Seq[(String, LineRange)] =
+ if (lines.isEmpty) accum.reverse
+ else {
+ val start = lines dropWhile fstS(skipInitial)
+ val (next, tail) = start.span { case (s, _) => !delimiter(s) }
+ val grouped = if (next.isEmpty) accum else (next.map(_._1).mkString("\n"), LineRange(next.head._2, next.last._2 + 1)) +: accum
+ group0(tail, grouped)
+ }
+ group0(lines, Nil)
+ }
+}
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/NewFormatSpec.scala b/main/src/test/scala/sbt/NewFormatSpec.scala
new file mode 100644
index 000000000..f9f447b50
--- /dev/null
+++ b/main/src/test/scala/sbt/NewFormatSpec.scala
@@ -0,0 +1,27 @@
+package sbt
+
+import java.io.File
+import scala.io.Source
+
+class NewFormatSpec extends AbstractSpec {
+ implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
+
+ "New Format " should {
+ "Handle lines " in {
+ val rootPath = getClass.getResource("").getPath + "../new-format/"
+ println(s"Reading files from: $rootPath")
+ val allFiles = new File(rootPath).listFiles.toList
+ foreach(allFiles) {
+ path =>
+ println(s"$path")
+ val lines = Source.fromFile(path).getLines().toList
+ val (_, statements) = splitter(path, lines)
+ statements.nonEmpty must be_==(true)
+ // orPending(s"""
+ // |***should contains statements***
+ // |$lines """.stripMargin)
+ }
+ }
+ }
+
+}
diff --git a/main/src/test/scala/sbt/SplitExpressions.scala b/main/src/test/scala/sbt/SplitExpressions.scala
new file mode 100644
index 000000000..1c08ac9ab
--- /dev/null
+++ b/main/src/test/scala/sbt/SplitExpressions.scala
@@ -0,0 +1,7 @@
+package sbt
+
+import java.io.File
+
+object SplitExpressions {
+ type SplitExpression = (File, Seq[String]) => (Seq[(String, Int)], Seq[(String, LineRange)])
+}
diff --git a/main/src/test/scala/sbt/SplitExpressionsBehavior.scala b/main/src/test/scala/sbt/SplitExpressionsBehavior.scala
new file mode 100644
index 000000000..c44f182e0
--- /dev/null
+++ b/main/src/test/scala/sbt/SplitExpressionsBehavior.scala
@@ -0,0 +1,91 @@
+package sbt
+
+import org.specs2.mutable.SpecificationLike
+
+trait SplitExpression {
+ def split(s: String)(implicit splitter: SplitExpressions.SplitExpression) = splitter(null, s.split("\n").toSeq)
+}
+
+trait SplitExpressionsBehavior extends SplitExpression {
+ this: SpecificationLike =>
+
+ def oldExpressionsSplitter(implicit splitter: SplitExpressions.SplitExpression) {
+
+ "parse a simple setting" in {
+ val (imports, settingsAndDefs) = split("""version := "1.0"""")
+ settingsAndDefs.head._1 === """version := "1.0""""
+
+ imports.isEmpty should beTrue
+ settingsAndDefs.isEmpty should beFalse
+ }
+
+ "parse a config containing a single import" in {
+ val (imports, settingsAndDefs) = split("""import foo.Bar""")
+ imports.isEmpty should beFalse
+ settingsAndDefs.isEmpty should beTrue
+ }
+
+ "parse a config containing two imports and a setting" in {
+ val (imports, settingsAndDefs) = split(
+ """import foo.Bar
+ import foo.Bar
+
+ version := "1.0"
+ """.stripMargin)
+ imports.size === 2
+ settingsAndDefs.size === 1
+ }
+
+ "parse a config containgn a def" in {
+ val (imports, settingsAndDefs) = split("""def foo(x: Int) = {
+ x + 1
+}""")
+ imports.isEmpty should beTrue
+ settingsAndDefs.isEmpty should beFalse
+ }
+
+ "parse a config containgn a val" in {
+ val (imports, settingsAndDefs) = split("""val answer = 42""")
+ imports.isEmpty should beTrue
+ settingsAndDefs.isEmpty should beFalse
+ }
+
+ "parse a config containgn a lazy val" in {
+ val (imports, settingsAndDefs) = split("""lazy val root = (project in file(".")).enablePluginsÂ(PlayScala)""")
+ imports.isEmpty should beTrue
+ settingsAndDefs.isEmpty should beFalse
+ }
+
+ }
+
+ def newExpressionsSplitter(implicit splitter: SplitExpressions.SplitExpression) {
+
+ "parse a two settings without intervening blank line" in {
+ val (imports, settings) = split("""version := "1.0"
+scalaVersion := "2.10.4"""")
+
+ imports.isEmpty should beTrue
+ settings.size === 2
+ }
+
+ "parse a setting and val without intervening blank line" in {
+ val (imports, settings) = split("""version := "1.0"
+lazy val root = (project in file(".")).enablePluginsÂ(PlayScala)""")
+
+ imports.isEmpty should beTrue
+ settings.size === 2
+ }
+
+ "parse a config containing two imports and a setting with no blank line" in {
+ val (imports, settingsAndDefs) = split(
+ """import foo.Bar
+ import foo.Bar
+ version := "1.0"
+ """.stripMargin)
+ imports.size === 2
+ settingsAndDefs.size === 1
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/SplitExpressionsFilesTest.scala b/main/src/test/scala/sbt/SplitExpressionsFilesTest.scala
new file mode 100644
index 000000000..9116e4721
--- /dev/null
+++ b/main/src/test/scala/sbt/SplitExpressionsFilesTest.scala
@@ -0,0 +1,150 @@
+package sbt
+
+import java.io.File
+
+import org.specs2.mutable.Specification
+
+import scala.annotation.tailrec
+import scala.io.Source
+import scala.tools.reflect.ToolBoxError
+
+class SplitExpressionsFilesTest extends AbstractSplitExpressionsFilesTest("../old-format/")
+
+abstract class AbstractSplitExpressionsFilesTest(pathName: String) extends Specification {
+
+ case class SplitterComparison(oldSplitterResult: util.Try[(Seq[(String, Int)], Seq[LineRange])], newSplitterResult: util.Try[(Seq[(String, Int)], Seq[LineRange])])
+
+ val oldSplitter: SplitExpressions.SplitExpression = EvaluateConfigurationsOriginal.splitExpressions
+ val newSplitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
+
+ final val REVERTED_LINES = true
+ final val START_COMMENT = "/*"
+ final val END_COMMENT = START_COMMENT.reverse
+
+ s"$getClass " should {
+ "split whole sbt files" in {
+ val rootPath = getClass.getResource("").getPath + pathName
+ println(s"Reading files from: $rootPath")
+ val allFiles = new File(rootPath).listFiles.toList
+
+ val results = for {
+ path <- allFiles
+ lines = Source.fromFile(path).getLines().toList
+ comparison = SplitterComparison(splitLines(path, oldSplitter, lines), splitLines(path, newSplitter, lines))
+ } yield path -> comparison
+
+ printResults(results)
+
+ val validResults = results.collect {
+ case (path, SplitterComparison(util.Success(oldRes), util.Success(newRes))) if oldRes == newRes => path
+ }
+
+ validResults.length must be_==(results.length)
+ }
+ }
+
+ def removeCommentFromStatement(statement: String, lineRange: LineRange): Option[LineRange] = {
+ val lines = statement.lines.toList
+ val optionStatements = removeSlashAsterisk(lines, lineRange, !REVERTED_LINES) match {
+ case Some((st, lr)) =>
+ removeDoubleSlash(st, lr)
+ case _ => None
+ }
+ optionStatements.map(t => t._2)
+ }
+
+ @tailrec
+ private def removeSlashAsterisk(statements: Seq[String], lineRange: LineRange, reverted: Boolean): Option[(Seq[String], LineRange)] =
+ statements match {
+ case statement +: _ =>
+ val openSlashAsteriskIndex = statement.indexOf(START_COMMENT, 0)
+ if (openSlashAsteriskIndex == -1 || statement.substring(0, openSlashAsteriskIndex).trim.nonEmpty) {
+ Some((statements, lineRange))
+ } else {
+ val closeSlashAsteriskLine = statements.indexWhere(s => s.contains(END_COMMENT))
+ if (closeSlashAsteriskLine == -1) {
+ Some((statements, lineRange))
+ } else {
+ val newLineRange = if (reverted) {
+ lineRange.copy(end = lineRange.end - closeSlashAsteriskLine - 1)
+ } else {
+ lineRange.copy(start = lineRange.start + closeSlashAsteriskLine + 1)
+ }
+ removeSlashAsterisk(statements.drop(closeSlashAsteriskLine + 1), newLineRange, reverted)
+ }
+ }
+ case _ =>
+ None
+ }
+
+ /**
+ * Remove // and /* */
+ * @param statements - lines
+ * @param lineRange - LineRange
+ * @return (lines,lineRange) without comments
+ */
+ def removeDoubleSlash(statements: Seq[String], lineRange: LineRange): Option[(Seq[String], LineRange)] = {
+
+ @tailrec
+ def removeDoubleSlashReversed(lines: Seq[String], lineRange: LineRange): Option[(Seq[String], LineRange)] =
+ lines match {
+ case statement +: _ =>
+ val doubleSlashIndex = statement.indexOf("//")
+ if (doubleSlashIndex == -1 || statement.substring(0, doubleSlashIndex).trim.nonEmpty) {
+ removeSlashAsterisk(lines, lineRange, REVERTED_LINES) match {
+ case some @ Some((s, ln)) if ln == lineRange =>
+ some
+ case Some((s, ln)) =>
+ removeDoubleSlashReversed(s, ln)
+ case _ => None
+ }
+
+ } else {
+ removeDoubleSlashReversed(lines.tail, lineRange.copy(end = lineRange.end - 1))
+ }
+ case _ =>
+ None
+ }
+ removeDoubleSlashReversed(statements.reverse, lineRange).map(t => (t._1.reverse, t._2))
+ }
+
+ def splitLines(file: File, splitter: SplitExpressions.SplitExpression, lines: List[String]): util.Try[(Seq[(String, Int)], Seq[LineRange])] = {
+ try {
+ val (imports, settingsAndDefs) = splitter(file, lines)
+
+ //TODO: Return actual contents (after making both splitter...
+ //TODO: ...implementations return CharRanges instead of LineRanges)
+ val settingsAndDefWithoutComments = settingsAndDefs.flatMap(t => removeCommentFromStatement(t._1, t._2))
+ util.Success((imports.map(imp => (imp._1.trim, imp._2)), settingsAndDefWithoutComments))
+ } catch {
+ case e: ToolBoxError =>
+ util.Failure(e)
+ case e: Throwable =>
+ util.Failure(e)
+ }
+ }
+
+ def printResults(results: List[(File, SplitterComparison)]) = {
+ for ((file, comparison) <- results) {
+ val fileName = file.getName
+ comparison match {
+ case SplitterComparison(util.Failure(ex), _) =>
+ println(s"In file: $fileName, old splitter failed. ${ex.toString}")
+ case SplitterComparison(_, util.Failure(ex)) =>
+ println(s"In file: $fileName, new splitter failed. ${ex.toString}")
+ case SplitterComparison(util.Success(resultOld), util.Success(resultNew)) =>
+ if (resultOld == resultNew) {
+ println(s"In file: $fileName, same results (imports, settings): $resultOld")
+ } else {
+ println(
+ s"""In file: $fileName, results differ:
+ |resultOld:
+ |$resultOld
+ |resultNew:
+ |$resultNew""".stripMargin)
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/SplitExpressionsTest.scala b/main/src/test/scala/sbt/SplitExpressionsTest.scala
new file mode 100644
index 000000000..bb172a2e4
--- /dev/null
+++ b/main/src/test/scala/sbt/SplitExpressionsTest.scala
@@ -0,0 +1,13 @@
+package sbt
+
+import org.specs2.mutable.Specification
+
+class SplitExpressionsTest extends Specification with SplitExpressionsBehavior {
+
+ "EvaluateConfigurationsOriginal" should oldExpressionsSplitter(EvaluateConfigurationsOriginal.splitExpressions)
+
+ "EvaluateConfigurations" should oldExpressionsSplitter(EvaluateConfigurations.splitExpressions)
+
+ "EvaluateConfigurations" should newExpressionsSplitter(EvaluateConfigurations.splitExpressions)
+
+}
\ No newline at end of file