diff --git a/ivy/src/main/scala/sbt/IvyInterface.scala b/ivy/src/main/scala/sbt/IvyInterface.scala index b42ba89c4..e4c2e8e46 100644 --- a/ivy/src/main/scala/sbt/IvyInterface.scala +++ b/ivy/src/main/scala/sbt/IvyInterface.scala @@ -11,7 +11,7 @@ import org.apache.ivy.util.url.CredentialsStore /** Additional information about a project module */ final case class ModuleInfo(nameFormal: String, description: String = "", homepage: Option[URL] = None, startYear: Option[Int] = None, licenses: Seq[(String, URL)] = Nil, organizationName: String = "", organizationHomepage: Option[URL] = None, scmInfo: Option[ScmInfo] = None, developers: Seq[Developer] = Seq()) { - def this(nameFormal: String, description: String = "", homepage: Option[URL] = None, startYear: Option[Int] = None, licenses: Seq[(String, URL)] = Nil, organizationName: String = "", organizationHomepage: Option[URL] = None, scmInfo: Option[ScmInfo] = None) = + def this(nameFormal: String, description: String, homepage: Option[URL], startYear: Option[Int], licenses: Seq[(String, URL)], organizationName: String, organizationHomepage: Option[URL], scmInfo: Option[ScmInfo]) = this(nameFormal, description, homepage, startYear, licenses, organizationName, organizationHomepage, scmInfo, Seq()) def formally(name: String) = copy(nameFormal = name) def describing(desc: String, home: Option[URL]) = copy(description = desc, homepage = home) diff --git a/main/src/main/scala/sbt/EvaluateConfigurations.scala b/main/src/main/scala/sbt/EvaluateConfigurations.scala index f1c200a42..44fdcf29f 100644 --- a/main/src/main/scala/sbt/EvaluateConfigurations.scala +++ b/main/src/main/scala/sbt/EvaluateConfigurations.scala @@ -8,6 +8,9 @@ import compiler.{ Eval, EvalImports } import complete.DefaultParsers.validID import Def.{ ScopedKey, Setting } import Scope.GlobalScope +import sbt.internals.parser.SplitExpressionsNoBlankies + +import scala.annotation.tailrec /** * This file is responsible for compiling the .sbt files used to configure sbt builds. @@ -206,18 +209,45 @@ 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(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) = + private[sbt] def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)]) = { val split = SplitExpressionsNoBlankies(file, lines) (split.imports, split.settings) } + @deprecated("This method is no longer part of the public API.", "0.13.7") + def splitExpressions(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)) + } + @deprecated("This method is deprecated and no longer used.", "0.13.7") + 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/SessionSettingsNoBlankies.scala b/main/src/main/scala/sbt/SessionSettingsNoBlankies.scala index 8fe3e589c..823696fce 100644 --- a/main/src/main/scala/sbt/SessionSettingsNoBlankies.scala +++ b/main/src/main/scala/sbt/SessionSettingsNoBlankies.scala @@ -1,5 +1,8 @@ package sbt +import java.io.File + +import sbt.internals.parser.{ XmlContent, SplitExpressionsNoBlankies } import scala.collection.immutable.SortedMap import scala.reflect.runtime.universe._ diff --git a/main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala b/main/src/main/scala/sbt/internals/parser/SplitExpressionsNoBlankies.scala similarity index 96% rename from main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala rename to main/src/main/scala/sbt/internals/parser/SplitExpressionsNoBlankies.scala index fc91d12fc..754a654cd 100644 --- a/main/src/main/scala/sbt/SplitExpressionsNoBlankies.scala +++ b/main/src/main/scala/sbt/internals/parser/SplitExpressionsNoBlankies.scala @@ -1,29 +1,31 @@ package sbt +package internals +package parser import java.io.File +import sbt.internals.parser.SplitExpressionsNoBlankies._ import scala.annotation.tailrec -import SplitExpressionsNoBlankies._ +import scala.reflect.runtime.universe import scala.reflect.runtime.universe._ -object SplitExpressionsNoBlankies { +private[sbt] object SplitExpressionsNoBlankies { val END_OF_LINE_CHAR = '\n' val END_OF_LINE = String.valueOf(END_OF_LINE_CHAR) private[sbt] val FAKE_FILE = new File("fake") } -case class SplitExpressionsNoBlankies(file: File, lines: Seq[String]) { +private[sbt] case class SplitExpressionsNoBlankies(file: File, lines: Seq[String]) { //settingsTrees needed for "session save" val (imports, settings, settingsTrees) = splitExpressions(file, lines) private def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)], Seq[(String, Tree)]) = { - import scala.reflect.runtime._ + import sbt.internals.parser.BugInParser._ + import sbt.internals.parser.XmlContent._ - import scala.tools.reflect.ToolBoxError - import scala.tools.reflect.ToolBox import scala.compat.Platform.EOL import BugInParser._ - import XmlContent._ + import scala.tools.reflect.{ ToolBox, ToolBoxError } val mirror = universe.runtimeMirror(this.getClass.getClassLoader) val toolbox = mirror.mkToolBox(options = "-Yrangepos") @@ -150,7 +152,7 @@ private[sbt] object BugInParser { * rr) * */ -private object XmlContent { +private[sbt] object XmlContent { /** * * @param original - file content diff --git a/main/src/test/scala/sbt/AbstractSpec.scala b/main/src/test/scala/sbt/AbstractSpec.scala deleted file mode 100644 index 28551eb74..000000000 --- a/main/src/test/scala/sbt/AbstractSpec.scala +++ /dev/null @@ -1,5 +0,0 @@ -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/SessionSettingsCutExpressionSpec.scala b/main/src/test/scala/sbt/SessionSettingsCutExpressionSpec.scala index ebdb9fbd8..17dfa3036 100644 --- a/main/src/test/scala/sbt/SessionSettingsCutExpressionSpec.scala +++ b/main/src/test/scala/sbt/SessionSettingsCutExpressionSpec.scala @@ -1,5 +1,7 @@ package sbt +import sbt.internals.parser.AbstractSpec + class SessionSettingsCutExpressionSpec extends AbstractSpec { "Cut expression " should { diff --git a/main/src/test/scala/sbt/SessionSettingsSpec.scala b/main/src/test/scala/sbt/SessionSettingsSpec.scala index 0f5097478..cc742897f 100644 --- a/main/src/test/scala/sbt/SessionSettingsSpec.scala +++ b/main/src/test/scala/sbt/SessionSettingsSpec.scala @@ -3,6 +3,7 @@ package sbt import java.io.{ File, FilenameFilter } import org.specs2.matcher.MatchResult +import sbt.internals.parser.{ AbstractSpec, SplitExpressionsNoBlankies } import scala.collection.GenTraversableOnce import scala.collection.immutable.{ SortedMap, TreeMap } diff --git a/main/src/test/scala/sbt/internals/parser/AbstractSpec.scala b/main/src/test/scala/sbt/internals/parser/AbstractSpec.scala new file mode 100644 index 000000000..6068bed9b --- /dev/null +++ b/main/src/test/scala/sbt/internals/parser/AbstractSpec.scala @@ -0,0 +1,5 @@ +package sbt.internals.parser + +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/internals/parser/CheckIfParsedSpec.scala similarity index 94% rename from main/src/test/scala/sbt/CheckIfParsedSpec.scala rename to main/src/test/scala/sbt/internals/parser/CheckIfParsedSpec.scala index b1015f400..2a9fdc71e 100644 --- a/main/src/test/scala/sbt/CheckIfParsedSpec.scala +++ b/main/src/test/scala/sbt/internals/parser/CheckIfParsedSpec.scala @@ -1,4 +1,6 @@ -package sbt +package sbt.internals.parser + +import sbt.EvaluateConfigurations abstract class CheckIfParsedSpec(implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions) extends AbstractSpec { diff --git a/main/src/test/scala/sbt/CommentedXmlSpec.scala b/main/src/test/scala/sbt/internals/parser/CommentedXmlSpec.scala similarity index 98% rename from main/src/test/scala/sbt/CommentedXmlSpec.scala rename to main/src/test/scala/sbt/internals/parser/CommentedXmlSpec.scala index 18e8b3bf3..22a91de10 100644 --- a/main/src/test/scala/sbt/CommentedXmlSpec.scala +++ b/main/src/test/scala/sbt/internals/parser/CommentedXmlSpec.scala @@ -1,4 +1,4 @@ -package sbt +package sbt.internals.parser class CommentedXmlSpec extends CheckIfParsedSpec { diff --git a/main/src/test/scala/sbt/EmbeddedXmlSpec.scala b/main/src/test/scala/sbt/internals/parser/EmbeddedXmlSpec.scala similarity index 98% rename from main/src/test/scala/sbt/EmbeddedXmlSpec.scala rename to main/src/test/scala/sbt/internals/parser/EmbeddedXmlSpec.scala index 4c207179f..200a13e7d 100644 --- a/main/src/test/scala/sbt/EmbeddedXmlSpec.scala +++ b/main/src/test/scala/sbt/internals/parser/EmbeddedXmlSpec.scala @@ -1,4 +1,6 @@ -package sbt +package sbt.internals.parser + +import sbt.MessageOnlyException class EmbeddedXmlSpec extends CheckIfParsedSpec { diff --git a/main/src/test/scala/sbt/ErrorSpec.scala b/main/src/test/scala/sbt/internals/parser/ErrorSpec.scala similarity index 90% rename from main/src/test/scala/sbt/ErrorSpec.scala rename to main/src/test/scala/sbt/internals/parser/ErrorSpec.scala index 8cc456df9..198139fd5 100644 --- a/main/src/test/scala/sbt/ErrorSpec.scala +++ b/main/src/test/scala/sbt/internals/parser/ErrorSpec.scala @@ -1,10 +1,9 @@ -package sbt +package sbt.internals.parser import java.io.File -import org.scalacheck.Gen._ -import org.scalacheck.Prop._ import org.specs2.ScalaCheck +import sbt.{ EvaluateConfigurations, MessageOnlyException } import scala.io.Source @@ -14,7 +13,7 @@ class ErrorSpec extends AbstractSpec with ScalaCheck { "Parser " should { "contains file name and line number" in { - val rootPath = getClass.getResource("").getPath + "../error-format/" + val rootPath = getClass.getClassLoader.getResource("").getPath + "/error-format/" println(s"Reading files from: $rootPath") foreach(new File(rootPath).listFiles) { file => print(s"Processing ${file.getName}: ") diff --git a/main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala b/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala similarity index 96% rename from main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala rename to main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala index dfa3a2420..b7c53c7c5 100644 --- a/main/src/test/scala/sbt/EvaluateConfigurationsOriginal.scala +++ b/main/src/test/scala/sbt/internals/parser/EvaluateConfigurationsOriginal.scala @@ -1,7 +1,9 @@ -package sbt +package sbt.internals.parser import java.io.File +import sbt.LineRange + import scala.annotation.tailrec object EvaluateConfigurationsOriginal { diff --git a/main/src/test/scala/sbt/NewFormatSpec.scala b/main/src/test/scala/sbt/internals/parser/NewFormatSpec.scala similarity index 84% rename from main/src/test/scala/sbt/NewFormatSpec.scala rename to main/src/test/scala/sbt/internals/parser/NewFormatSpec.scala index ee5a31493..a540c318b 100644 --- a/main/src/test/scala/sbt/NewFormatSpec.scala +++ b/main/src/test/scala/sbt/internals/parser/NewFormatSpec.scala @@ -1,9 +1,10 @@ -package sbt +package sbt.internals.parser import java.io.File import org.junit.runner.RunWith import org.specs2.runner.JUnitRunner +import sbt.EvaluateConfigurations import scala.io.Source @@ -13,7 +14,7 @@ class NewFormatSpec extends AbstractSpec { "New Format " should { "Handle lines " in { - val rootPath = getClass.getResource("").getPath + "../new-format/" + val rootPath = getClass.getClassLoader.getResource("").getPath + "/new-format/" println(s"Reading files from: $rootPath") val allFiles = new File(rootPath).listFiles.toList foreach(allFiles) { diff --git a/main/src/test/scala/sbt/SplitExpressions.scala b/main/src/test/scala/sbt/internals/parser/SplitExpressions.scala similarity index 73% rename from main/src/test/scala/sbt/SplitExpressions.scala rename to main/src/test/scala/sbt/internals/parser/SplitExpressions.scala index 1c08ac9ab..a93dde00d 100644 --- a/main/src/test/scala/sbt/SplitExpressions.scala +++ b/main/src/test/scala/sbt/internals/parser/SplitExpressions.scala @@ -1,7 +1,9 @@ -package sbt +package sbt.internals.parser import java.io.File +import sbt.LineRange + 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/internals/parser/SplitExpressionsBehavior.scala similarity index 98% rename from main/src/test/scala/sbt/SplitExpressionsBehavior.scala rename to main/src/test/scala/sbt/internals/parser/SplitExpressionsBehavior.scala index 246a29e11..fd44478a5 100644 --- a/main/src/test/scala/sbt/SplitExpressionsBehavior.scala +++ b/main/src/test/scala/sbt/internals/parser/SplitExpressionsBehavior.scala @@ -1,4 +1,4 @@ -package sbt +package sbt.internals.parser import java.io.File diff --git a/main/src/test/scala/sbt/SplitExpressionsFilesTest.scala b/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala similarity index 97% rename from main/src/test/scala/sbt/SplitExpressionsFilesTest.scala rename to main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala index 9116e4721..704e12366 100644 --- a/main/src/test/scala/sbt/SplitExpressionsFilesTest.scala +++ b/main/src/test/scala/sbt/internals/parser/SplitExpressionsFilesTest.scala @@ -1,4 +1,6 @@ package sbt +package internals +package parser import java.io.File @@ -8,7 +10,7 @@ import scala.annotation.tailrec import scala.io.Source import scala.tools.reflect.ToolBoxError -class SplitExpressionsFilesTest extends AbstractSplitExpressionsFilesTest("../old-format/") +class SplitExpressionsFilesTest extends AbstractSplitExpressionsFilesTest("/old-format/") abstract class AbstractSplitExpressionsFilesTest(pathName: String) extends Specification { @@ -23,7 +25,7 @@ abstract class AbstractSplitExpressionsFilesTest(pathName: String) extends Speci s"$getClass " should { "split whole sbt files" in { - val rootPath = getClass.getResource("").getPath + pathName + val rootPath = getClass.getClassLoader.getResource("").getPath + pathName println(s"Reading files from: $rootPath") val allFiles = new File(rootPath).listFiles.toList diff --git a/main/src/test/scala/sbt/SplitExpressionsTest.scala b/main/src/test/scala/sbt/internals/parser/SplitExpressionsTest.scala similarity index 87% rename from main/src/test/scala/sbt/SplitExpressionsTest.scala rename to main/src/test/scala/sbt/internals/parser/SplitExpressionsTest.scala index bb172a2e4..82dfdf0b2 100644 --- a/main/src/test/scala/sbt/SplitExpressionsTest.scala +++ b/main/src/test/scala/sbt/internals/parser/SplitExpressionsTest.scala @@ -1,6 +1,7 @@ -package sbt +package sbt.internals.parser import org.specs2.mutable.Specification +import sbt.EvaluateConfigurations class SplitExpressionsTest extends Specification with SplitExpressionsBehavior { diff --git a/sbt/src/sbt-test/project/session-update-from-cmd/build.check.2 b/sbt/src/sbt-test/project/session-update-from-cmd/build.check.2 new file mode 100644 index 000000000..e69de29bb