diff --git a/main/src/main/scala/sbt/internals/parser/SbtParser.scala b/main/src/main/scala/sbt/internals/parser/SbtParser.scala
index 785492e7b..08d71c736 100644
--- a/main/src/main/scala/sbt/internals/parser/SbtParser.scala
+++ b/main/src/main/scala/sbt/internals/parser/SbtParser.scala
@@ -23,10 +23,13 @@ private[sbt] object SbtParser {
sealed trait ParsedSbtFileExpressions {
/** The set of parsed import expressions. */
def imports: Seq[(String, Int)]
+
/** The set of parsed defintions and/or sbt build settings. */
def settings: Seq[(String, LineRange)]
+
/** The set of scala tree's for parsed definitions/settings and the underlying string representation.. */
def settingsTrees: Seq[(String, Tree)]
+
/** Represents the changes we had to perform to the sbt file so that XML will parse correctly. */
def modifiedContent: String
}
@@ -200,9 +203,9 @@ private[sbt] object XmlContent {
private val DOUBLE_SLASH = "//"
- private val OPEN_BRACKET = s" $OPEN_CURLY_BRACKET "
+ private val OPEN_BRACKET = s"$OPEN_CURLY_BRACKET"
- private val CLOSE_BRACKET = " ) "
+ private val CLOSE_BRACKET = ")"
/**
*
@@ -222,24 +225,25 @@ private[sbt] object XmlContent {
* Cut file for normal text - xml - normal text - xml ....
* @param content - content
* @param ts - import/statements
- * @return (text,true) - is xml (text,false) - if normal text
+ * @return Seq - Right(xml,whiteSpaces) - for xml, Left(statement) - for 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
+ private def splitFile(content: String, ts: Seq[(String, Int, Int)]): Seq[Either[(String), (String, String)]] = {
+ val (statements, lastIndex) = ts.foldLeft((Seq.empty[Either[(String), (String, String)]], 0)) {
+ case ((accSeq, index), (statement, startIndex, endIndex)) =>
+ val toAdd = if (index >= startIndex) {
+ Seq(Right((statement, "")))
} else {
val s = content.substring(index, startIndex)
- Some((s, false))
+ if (s.trim.isEmpty) {
+ Seq(Right((statement, s)))
+ } else {
+ Seq(Right((statement, "")), Left(s))
+ }
}
- val newAccSeq = (statement, true) +: addOptionToCollection(accSeq, textStatementOption)
- (newAccSeq, endIndex)
+ (toAdd ++ accSeq, endIndex)
}
- val endOfFile = content.substring(index, content.length)
- val withEndOfFile = (endOfFile, false) +: statements
+ val endOfFile = content.substring(lastIndex, content.length)
+ val withEndOfFile = if (endOfFile.isEmpty) statements else Left(endOfFile) +: statements
withEndOfFile.reverse
}
@@ -265,6 +269,8 @@ private[sbt] object XmlContent {
}
}
+ private val CLOSE_XML_TAG = "/>"
+
/**
* Modified Opening Tag -
* @param offsetIndex - index
@@ -273,7 +279,7 @@ private[sbt] object XmlContent {
*/
@tailrec
private def findModifiedOpeningTags(content: String, offsetIndex: Int, acc: Seq[(String, Int, Int)]): Seq[(String, Int, Int)] = {
- val endIndex = content.indexOf("/>", offsetIndex)
+ val endIndex = content.indexOf(CLOSE_XML_TAG, offsetIndex)
if (endIndex == NOT_FOUND_INDEX) {
acc
} else {
@@ -352,46 +358,40 @@ private[sbt] object XmlContent {
* @return content with xml with brackets
*/
private def addExplicitXmlContent(content: String, xmlParts: Seq[(String, Int, Int)]): String = {
- val statements: Seq[(String, Boolean)] = splitFile(content, xmlParts)
- val (correctedStmt, shouldAddCloseBrackets, wasXml, _) = addBracketsIfNecessary(statements)
- val closeIfNecessaryCorrectedStmt =
- if (shouldAddCloseBrackets && wasXml) {
- correctedStmt.head +: CLOSE_BRACKET +: correctedStmt.tail
- } else {
- correctedStmt
- }
- closeIfNecessaryCorrectedStmt.reverse.mkString
- }
+ val statements = splitFile(content, xmlParts)
- def addBracketsIfNecessary(statements: Seq[(String, Boolean)]): (Seq[String], Boolean, Boolean, String) = {
- statements.foldLeft((Seq.empty[String], false, false, "")) {
- case ((accStmt, shouldAddCloseBracket, prvWasXml, prvStmt), (stmt, isXml)) =>
- if (stmt.trim.isEmpty) {
- (stmt +: accStmt, shouldAddCloseBracket, prvWasXml, stmt)
- } else {
- val (newShouldAddCloseBracket, newStmtAcc) = if (isXml) {
- addOpenBracketIfNecessary(accStmt, shouldAddCloseBracket, prvWasXml, prvStmt)
- } else if (shouldAddCloseBracket) {
- (false, CLOSE_BRACKET +: accStmt)
- } else {
- (false, accStmt)
- }
-
- (stmt +: newStmtAcc, newShouldAddCloseBracket, isXml, stmt)
+ val (_, seq, lastAdd) = statements.foldLeft[(Option[Either[(String), (String, String)]], Seq[String], Boolean)]((None, Seq.empty[String], false)) {
+ case ((previousOption, acc, add), element) =>
+ val (newAcc, newAdd) = (element, previousOption) match {
+ case (Left(text), _) =>
+ val accWithClose = if (add) {
+ addCloseBracket(acc)
+ } else {
+ acc
+ }
+ (text +: accWithClose, false)
+ case (Right((xml, nonXml)), Some(Left(text))) =>
+ val (accWithOpen, added) = if (areBracketsNecessary(text)) {
+ (OPEN_BRACKET +: acc, true)
+ } else {
+ (acc, false)
+ }
+ (xml +: (nonXml +: accWithOpen), added)
+ case (Right((xml, nonXml)), _) =>
+ (xml +: (nonXml +: acc), add)
}
+ (Some(element), newAcc, newAdd)
}
+
+ val correctedSeq = if (lastAdd) {
+ addCloseBracket(seq)
+ } else {
+ seq
+ }
+ correctedSeq.reverse.mkString
}
- private def addOpenBracketIfNecessary(stmtAcc: Seq[String], shouldAddCloseBracket: Boolean, prvWasXml: Boolean, prvStatement: String) =
- if (prvWasXml) {
- (shouldAddCloseBracket, stmtAcc)
- } else {
- if (areBracketsNecessary(prvStatement)) {
- (true, OPEN_BRACKET +: stmtAcc)
- } else {
- (false, stmtAcc)
- }
- }
+ private def addCloseBracket(statements: Seq[String]) = CLOSE_BRACKET +: statements
/**
* Add to head if option is not empty
@@ -439,8 +439,15 @@ private[sbt] object XmlContent {
*/
private def areBracketsNecessary(statement: String): Boolean = {
val doubleSlash = statement.indexOf(DOUBLE_SLASH)
- val endOfLine = statement.indexOf(END_OF_LINE)
- if (doubleSlash == NOT_FOUND_INDEX || (doubleSlash < endOfLine)) {
+
+ if (doubleSlash != NOT_FOUND_INDEX) {
+ val endOfLine = statement.indexOf(END_OF_LINE, doubleSlash)
+ if (endOfLine == NOT_FOUND_INDEX) {
+ false
+ } else {
+ areBracketsNecessary(statement.substring(endOfLine))
+ }
+ } else {
val roundBrackets = statement.lastIndexOf(OPEN_CURLY_BRACKET)
val braces = statement.lastIndexOf(OPEN_PARENTHESIS)
val max = roundBrackets.max(braces)
@@ -450,8 +457,7 @@ private[sbt] object XmlContent {
val trimmed = statement.substring(max + 1).trim
trimmed.nonEmpty
}
- } else {
- false
+
}
}
}
\ No newline at end of file
diff --git a/main/src/test/resources/fail-format/.gitignore b/main/src/test/resources/fail-format/.gitignore
new file mode 100644
index 000000000..f59ec20aa
--- /dev/null
+++ b/main/src/test/resources/fail-format/.gitignore
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/main/src/test/resources/old-format/21.sbt.txt b/main/src/test/resources/old-format/21.sbt.txt
new file mode 100644
index 000000000..c4cfc8585
--- /dev/null
+++ b/main/src/test/resources/old-format/21.sbt.txt
@@ -0,0 +1,72 @@
+
+name := "scala-stm"
+
+organization := "org.scala-stm"
+
+version := "0.8-SNAPSHOT"
+
+scalaVersion := "2.11.2"
+
+crossScalaVersions := Seq("2.11.2", "2.10.4", "2.9.3")
+
+libraryDependencies += ("org.scalatest" %% "scalatest" % "[1.5,)" % "test")
+
+libraryDependencies += ("junit" % "junit" % "4.5" % "test")
+
+// skip exhaustive tests
+testOptions += Tests.Argument("-l", "slow")
+
+// test of TxnExecutor.transformDefault must be run by itself
+parallelExecution in Test := false
+
+////////////////////
+// publishing
+
+pomExtra :=
+ http://nbronson.github.com/scala-stm/
+
+
+ BSD
+ https://github.com/nbronson/scala-stm/blob/master/LICENSE.txt
+ repo
+
+
+
+ scm:git:git@github.com:nbronson/scala-stm.git
+ git@github.com:nbronson/scala-stm.git
+
+
+
+ nbronson
+ Nathan Bronson
+ ngbronson@gmail.com
+
+
+
+publishMavenStyle := true
+
+publishTo <<= (version) { v: String =>
+ val base = "https://oss.sonatype.org/"
+ if (v.trim.endsWith("SNAPSHOT"))
+ Some("snapshots" at base + "content/repositories/snapshots/")
+ else
+ Some("releases" at base + "service/local/staging/deploy/maven2/")
+ }
+
+// exclude scalatest from the Maven POM
+pomPostProcess := { xi: scala.xml.Node =>
+ import scala.xml._
+ val badDeps = (xi \\ "dependency") filter {
+ x => (x \ "artifactId").text != "scala-library"
+ } toSet
+ def filt(root: Node): Node = root match {
+ case x: Elem => {
+ val ch = x.child filter { !badDeps(_) } map { filt(_) }
+ Elem(x.prefix, x.label, x.attributes, x.scope, ch: _*)
+ }
+ case x => x
+ }
+ filt(xi)
+ }
+
+credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
diff --git a/main/src/test/resources/session-settings-quick/3.sbt.txt b/main/src/test/resources/session-settings-quick/3.sbt.txt
new file mode 100644
index 000000000..6db83e79c
--- /dev/null
+++ b/main/src/test/resources/session-settings-quick/3.sbt.txt
@@ -0,0 +1,16 @@
+import sbt._
+
+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
+
+
+
\ No newline at end of file
diff --git a/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set b/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set
new file mode 100644
index 000000000..3e2aa8d48
--- /dev/null
+++ b/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set
@@ -0,0 +1 @@
+scmpom := OK
\ No newline at end of file
diff --git a/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set.result b/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set.result
new file mode 100644
index 000000000..c992f0b5a
--- /dev/null
+++ b/main/src/test/resources/session-settings-quick/3.sbt.txt_1/1.set.result
@@ -0,0 +1,5 @@
+import sbt._
+
+val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
+
+scmpom := (OK)
\ No newline at end of file
diff --git a/main/src/test/resources/session-settings-quick/4.sbt.txt b/main/src/test/resources/session-settings-quick/4.sbt.txt
deleted file mode 100644
index 5d1bcd5b2..000000000
--- a/main/src/test/resources/session-settings-quick/4.sbt.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-k1 := {}
-
-k2 := {}
-
-k3 := {
-
-
- val x = "hi"
- ()
-}
-
-k4 := { }; k5 := ()
-
-k1 <<= k1 map {_ => sys.error("k1")}
-
-k4 := { val x = k4.value; () }
-
diff --git a/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set b/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set
deleted file mode 100644
index 2a3525578..000000000
--- a/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set
+++ /dev/null
@@ -1 +0,0 @@
-k4 := ()
diff --git a/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set.result b/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set.result
deleted file mode 100644
index 3f5ec19f4..000000000
--- a/main/src/test/resources/session-settings-quick/4.sbt.txt_1/1.set.result
+++ /dev/null
@@ -1,15 +0,0 @@
-k1 := {}
-
-k2 := {}
-
-k3 := {
-
-
- val x = "hi"
- ()
-}
-
-k4 := (); k5 := ()
-
-k1 <<= k1 map {_ => sys.error("k1")}
-
diff --git a/main/src/test/resources/session-settings/3.sbt.txt_1/1.set.result b/main/src/test/resources/session-settings/3.sbt.txt_1/1.set.result
index 6b1956fb1..2c18733df 100644
--- a/main/src/test/resources/session-settings/3.sbt.txt_1/1.set.result
+++ b/main/src/test/resources/session-settings/3.sbt.txt_1/1.set.result
@@ -2,4 +2,4 @@ import sbt._
val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
-scmpom := ( OK )
\ No newline at end of file
+scmpom := OK;
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala b/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala
index b7c53c7c5..71580529f 100644
--- a/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala
+++ b/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala
@@ -2,40 +2,16 @@ package sbt.internals.parser
import java.io.File
-import sbt.LineRange
+import sbt.{ EvaluateConfigurations, LineRange }
import scala.annotation.tailrec
+@deprecated("This class is be removed. Only for test backward compatibility", "1.0")
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))
+ EvaluateConfigurations.splitExpressions(lines)
}
- 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/internals/parser/SessionSettingsSpec.scala b/main/src/test/scala/sbt/internals/parser/SessionSettingsSpec.scala
index db64a065a..aa5007020 100644
--- a/main/src/test/scala/sbt/internals/parser/SessionSettingsSpec.scala
+++ b/main/src/test/scala/sbt/internals/parser/SessionSettingsSpec.scala
@@ -70,4 +70,4 @@ abstract class AbstractSessionSettingsSpec(folder: String) extends AbstractSpec
class SessionSettingsSpec extends AbstractSessionSettingsSpec("session-settings")
-//class SessionSettingsQuickSpec extends AbstractSessionSettingsSpec("session-settings-quick", true)
\ No newline at end of file
+class SessionSettingsQuickSpec extends AbstractSessionSettingsSpec("session-settings-quick")
\ No newline at end of file
diff --git a/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala b/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala
index 704e12366..bf566aa54 100644
--- a/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala
+++ b/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala
@@ -12,6 +12,8 @@ import scala.tools.reflect.ToolBoxError
class SplitExpressionsFilesTest extends AbstractSplitExpressionsFilesTest("/old-format/")
+//class SplitExpressionsFilesFailedTest extends AbstractSplitExpressionsFilesTest("/fail-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])])