mirror of https://github.com/sbt/sbt.git
Merge pull request #1645 from sbt/wip/no-blankies-rebased
Natural whitespace handling for SBT configuration parser AKA 'no more blankies'
This commit is contained in:
commit
0f2c6f89a1
|
|
@ -12,7 +12,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], startYear: Option[Int], licenses: Seq[(String, URL)], organizationName: String, organizationHomepage: Option[URL], scmInfo: Option[ScmInfo]) =
|
||||
this(nameFormal = nameFormal, description = description, homepage = homepage, startYear = startYear, licenses = licenses, organizationName = organizationName, organizationHomepage = organizationHomepage, scmInfo = scmInfo, developers = Seq())
|
||||
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)
|
||||
def licensed(lics: (String, URL)*) = copy(licenses = lics)
|
||||
|
|
@ -43,4 +43,4 @@ object ConflictManager {
|
|||
val latestCompatible = ConflictManager("latest-compatible")
|
||||
val strict = ConflictManager("strict")
|
||||
val default = latestRevision
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import compiler.{ Eval, EvalImports }
|
||||
import complete.DefaultParsers.validID
|
||||
import Def.{ ScopedKey, Setting, SettingsDefinition }
|
||||
import Def.{ ScopedKey, Setting }
|
||||
import Scope.GlobalScope
|
||||
import sbt.internals.parser.SbtParser
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
/**
|
||||
|
|
@ -61,11 +62,11 @@ object EvaluateConfigurations {
|
|||
* Parses a sequence of build.sbt lines into a [[ParsedFile]]. The result contains
|
||||
* a fragmentation of all imports, settings and definitions.
|
||||
*
|
||||
* @param buildinImports The set of import statements to add to those parsed in the .sbt file.
|
||||
* @param builtinImports 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 +104,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))
|
||||
|
|
@ -167,7 +168,7 @@ object EvaluateConfigurations {
|
|||
* @param expression The scala expression we're compiling
|
||||
* @param range The original position in source of the expression, for error messages.
|
||||
*
|
||||
* @return A method that given an sbt classloader, can return the actual [[DslEntry]] defined by
|
||||
* @return A method that given an sbt classloader, can return the actual [[internals.DslEntry]] defined by
|
||||
* the expression, and the sequence of .class files generated.
|
||||
*/
|
||||
private[sbt] def evaluateDslEntry(eval: Eval, name: String, imports: Seq[(String, Int)], expression: String, range: LineRange): TrackedEvalResult[internals.DslEntry] = {
|
||||
|
|
@ -215,17 +216,26 @@ object EvaluateConfigurations {
|
|||
* 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)]) =
|
||||
private[sbt] 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))
|
||||
val split = SbtParser(file, lines)
|
||||
// TODO - Look at pulling the parsed expression trees from the SbtParser and stitch them back into a different
|
||||
// scala compiler rather than re-parsing.
|
||||
(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)
|
||||
|
|
@ -239,6 +249,7 @@ object EvaluateConfigurations {
|
|||
}
|
||||
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 =
|
||||
|
|
@ -274,7 +285,7 @@ object Index {
|
|||
val multiMap = settings.groupBy(label)
|
||||
val duplicates = multiMap collect { case (k, xs) if xs.size > 1 => (k, xs.map(_.manifest)) } collect { case (k, xs) if xs.size > 1 => (k, xs) }
|
||||
if (duplicates.isEmpty)
|
||||
multiMap.collect { case (k, v) if validID(k) => (k, v.head) } toMap;
|
||||
multiMap.collect { case (k, v) if validID(k) => (k, v.head) } toMap
|
||||
else
|
||||
sys.error(duplicates map { case (k, tps) => "'" + k + "' (" + tps.mkString(", ") + ")" } mkString ("Some keys were defined with the same name but different types: ", ", ", ""))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,74 +6,164 @@ package sbt
|
|||
import java.io.File
|
||||
import java.net.URI
|
||||
import Def.{ ScopedKey, Setting }
|
||||
import Project._
|
||||
import Types.Endo
|
||||
import compiler.Eval
|
||||
|
||||
import SessionSettings._
|
||||
import sbt.internals.parser.SbtRefactorings
|
||||
|
||||
/**
|
||||
* Represents (potentially) transient settings added into a build via commands/user.
|
||||
*
|
||||
* @param currentBuild
|
||||
* The current sbt build with which we scope new settings
|
||||
* @param currentProject
|
||||
* The current project with which we scope new settings.
|
||||
* @param original
|
||||
* The original list of settings for this build.
|
||||
* @param append
|
||||
* Settings which have been defined and appended that may ALSO be saved to disk.
|
||||
* @param rawAppend
|
||||
* Settings which have been defined and appended which CANNOT be saved to disk
|
||||
* @param currentEval
|
||||
* A compiler we can use to compile new setting strings.
|
||||
*/
|
||||
final case class SessionSettings(currentBuild: URI, currentProject: Map[URI, String], original: Seq[Setting[_]], append: SessionMap, rawAppend: Seq[Setting[_]], currentEval: () => Eval) {
|
||||
assert(currentProject contains currentBuild, "Current build (" + currentBuild + ") not associated with a current project.")
|
||||
|
||||
/**
|
||||
* Modifiy the current state.
|
||||
*
|
||||
* @param build The buid with which we scope new settings.
|
||||
* @param project The project reference with which we scope new settings.
|
||||
* @param eval The mechanism to compile new settings.
|
||||
* @return A new SessionSettings object
|
||||
*/
|
||||
def setCurrent(build: URI, project: String, eval: () => Eval): SessionSettings = copy(currentBuild = build, currentProject = currentProject.updated(build, project), currentEval = eval)
|
||||
|
||||
/**
|
||||
* @return The current ProjectRef with which we scope settings.
|
||||
*/
|
||||
def current: ProjectRef = ProjectRef(currentBuild, currentProject(currentBuild))
|
||||
|
||||
/**
|
||||
* Appends a set of settings which can be persisted to disk
|
||||
* @param s A sequence of SessionSetting objects, which contain a Setting[_] and a string.
|
||||
* @return A new SessionSettings which contains this new sequence.
|
||||
*/
|
||||
def appendSettings(s: Seq[SessionSetting]): SessionSettings = copy(append = modify(append, _ ++ s))
|
||||
|
||||
/**
|
||||
* Appends a set of raw Setting[_] objects to the current session.
|
||||
* @param ss The raw settings to include
|
||||
* @return A new SessionSettings with the appeneded settings.
|
||||
*/
|
||||
def appendRaw(ss: Seq[Setting[_]]): SessionSettings = copy(rawAppend = rawAppend ++ ss)
|
||||
|
||||
/**
|
||||
* @return A combined list of all Setting[_] objects for the current session, in priority order.
|
||||
*/
|
||||
def mergeSettings: Seq[Setting[_]] = original ++ merge(append) ++ rawAppend
|
||||
|
||||
/**
|
||||
* @return A new SessionSettings object where additional transient settings are removed.
|
||||
*/
|
||||
def clearExtraSettings: SessionSettings = copy(append = Map.empty, rawAppend = Nil)
|
||||
|
||||
private[this] def merge(map: SessionMap): Seq[Setting[_]] = map.values.toSeq.flatten[SessionSetting].map(_._1)
|
||||
private[this] def modify(map: SessionMap, onSeq: Endo[Seq[SessionSetting]]): SessionMap =
|
||||
{
|
||||
val cur = current
|
||||
map.updated(cur, onSeq(map.getOrElse(cur, Nil)))
|
||||
}
|
||||
}
|
||||
object SessionSettings {
|
||||
type SessionSetting = (Setting[_], List[String])
|
||||
type SessionMap = Map[ProjectRef, Seq[SessionSetting]]
|
||||
|
||||
private[this] def modify(map: SessionMap, onSeq: Endo[Seq[SessionSetting]]): SessionMap = {
|
||||
val cur = current
|
||||
map.updated(cur, onSeq(map.getOrElse(cur, Nil)))
|
||||
}
|
||||
}
|
||||
|
||||
object SessionSettings {
|
||||
/** A session setting is simply a tuple of a Setting[_] and the strings which define it. */
|
||||
type SessionSetting = (Setting[_], Seq[String])
|
||||
type SessionMap = Map[ProjectRef, Seq[SessionSetting]]
|
||||
type SbtConfigFile = (File, Seq[String])
|
||||
|
||||
/**
|
||||
* This will re-evaluate all Setting[_]'s on this session against the current build state and
|
||||
* return the new build state.
|
||||
*/
|
||||
def reapply(session: SessionSettings, s: State): State =
|
||||
BuiltinCommands.reapply(session, Project.structure(s), s)
|
||||
|
||||
/**
|
||||
* This will clear any user-added session settings for a given build state and return the new build state.
|
||||
*
|
||||
* Note: Does not clear `rawAppend` settings
|
||||
*/
|
||||
def clearSettings(s: State): State =
|
||||
withSettings(s)(session => reapply(session.copy(append = session.append - session.current), s))
|
||||
|
||||
/** This will clear ALL transient session settings in a given build state, returning the new build state. */
|
||||
def clearAllSettings(s: State): State =
|
||||
withSettings(s)(session => reapply(session.clearExtraSettings, s))
|
||||
|
||||
def withSettings(s: State)(f: SessionSettings => State): State =
|
||||
{
|
||||
val extracted = Project extract s
|
||||
import extracted._
|
||||
if (session.append.isEmpty) {
|
||||
s.log.info("No session settings defined.")
|
||||
s
|
||||
} else
|
||||
f(session)
|
||||
}
|
||||
/**
|
||||
* A convenience method to alter the current build state using the current SessionSettings.
|
||||
*
|
||||
* @param s The current build state
|
||||
* @param f A function which takes the current SessionSettings and returns the new build state.
|
||||
* @return The new build state
|
||||
*/
|
||||
def withSettings(s: State)(f: SessionSettings => State): State = {
|
||||
val extracted = Project extract s
|
||||
import extracted._
|
||||
if (session.append.isEmpty) {
|
||||
s.log.info("No session settings defined.")
|
||||
s
|
||||
} else
|
||||
f(session)
|
||||
}
|
||||
|
||||
/** Adds `s` to a strings when needed. Maybe one day we'll care about non-english languages. */
|
||||
def pluralize(size: Int, of: String) = size.toString + (if (size == 1) of else (of + "s"))
|
||||
|
||||
/** Checks to see if any session settings are being discarded and issues a warning. */
|
||||
def checkSession(newSession: SessionSettings, oldState: State) {
|
||||
val oldSettings = (oldState get Keys.sessionSettings).toList.flatMap(_.append).flatMap(_._2)
|
||||
if (newSession.append.isEmpty && !oldSettings.isEmpty)
|
||||
oldState.log.warn("Discarding " + pluralize(oldSettings.size, " session setting") + ". Use 'session save' to persist session settings.")
|
||||
}
|
||||
def removeRanges[T](in: Seq[T], ranges: Seq[(Int, Int)]): Seq[T] =
|
||||
{
|
||||
val asSet = (Set.empty[Int] /: ranges) { case (s, (hi, lo)) => s ++ (hi to lo) }
|
||||
in.zipWithIndex.flatMap { case (t, index) => if (asSet(index + 1)) Nil else t :: Nil }
|
||||
}
|
||||
|
||||
@deprecated("This method will no longer be public", "0.13.7")
|
||||
def removeRanges[T](in: Seq[T], ranges: Seq[(Int, Int)]): Seq[T] = {
|
||||
val asSet = (Set.empty[Int] /: ranges) { case (s, (hi, lo)) => s ++ (hi to lo) }
|
||||
in.zipWithIndex.flatMap { case (t, index) => if (asSet(index + 1)) Nil else t :: Nil }
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes settings from the current session, by range.
|
||||
* @param s The current build state.
|
||||
* @param ranges A set of Low->High tuples for which settings to remove.
|
||||
* @return The new build state with settings removed.
|
||||
*/
|
||||
def removeSettings(s: State, ranges: Seq[(Int, Int)]): State =
|
||||
withSettings(s) { session =>
|
||||
val current = session.current
|
||||
val newAppend = session.append.updated(current, removeRanges(session.append.getOrElse(current, Nil), ranges))
|
||||
reapply(session.copy(append = newAppend), s)
|
||||
}
|
||||
|
||||
/** Saves *all* session settings to disk for all projects. */
|
||||
def saveAllSettings(s: State): State = saveSomeSettings(s)(_ => true)
|
||||
def saveSettings(s: State): State =
|
||||
{
|
||||
val current = Project.session(s).current
|
||||
saveSomeSettings(s)(_ == current)
|
||||
}
|
||||
|
||||
/** Saves the session settings to disk for the current project. */
|
||||
def saveSettings(s: State): State = {
|
||||
val current = Project.session(s).current
|
||||
saveSomeSettings(s)(_ == current)
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves session settings to disk if they match the filter.
|
||||
* @param s The build state
|
||||
* @param include A filter function to determine which project's settings to persist.
|
||||
* @return The new build state.
|
||||
*/
|
||||
def saveSomeSettings(s: State)(include: ProjectRef => Boolean): State =
|
||||
withSettings(s) { session =>
|
||||
val newSettings =
|
||||
|
|
@ -85,54 +175,52 @@ object SessionSettings {
|
|||
val newSession = session.copy(append = newAppend.toMap, original = newOriginal.flatten.toSeq)
|
||||
reapply(newSession.copy(original = newSession.mergeSettings, append = Map.empty), s)
|
||||
}
|
||||
def writeSettings(pref: ProjectRef, settings: List[SessionSetting], original: Seq[Setting[_]], structure: BuildStructure): (Seq[SessionSetting], Seq[Setting[_]]) =
|
||||
{
|
||||
val project = Project.getProject(pref, structure).getOrElse(sys.error("Invalid project reference " + pref))
|
||||
val writeTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt"))
|
||||
writeTo.createNewFile()
|
||||
|
||||
val path = writeTo.getAbsolutePath
|
||||
val (inFile, other, _) = ((List[Setting[_]](), List[Setting[_]](), Set.empty[ScopedKey[_]]) /: original.reverse) {
|
||||
case ((in, oth, keys), s) =>
|
||||
s.pos match {
|
||||
case RangePosition(`path`, _) if !keys.contains(s.key) => (s :: in, oth, keys + s.key)
|
||||
case _ => (in, s :: oth, keys)
|
||||
}
|
||||
}
|
||||
@deprecated("This method will no longer be publlic", "0.13.7")
|
||||
def writeSettings(pref: ProjectRef, settings: List[SessionSetting], original: Seq[Setting[_]], structure: BuildStructure): (Seq[SessionSetting], Seq[Setting[_]]) = {
|
||||
val project = Project.getProject(pref, structure).getOrElse(sys.error("Invalid project reference " + pref))
|
||||
val writeTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt"))
|
||||
writeTo.createNewFile()
|
||||
|
||||
val (_, oldShifted, replace, lineMap) = ((0, List[Setting[_]](), List[SessionSetting](), Map.empty[Int, (Int, List[String])]) /: inFile) {
|
||||
case ((offs, olds, repl, lineMap), s) =>
|
||||
val RangePosition(_, r @ LineRange(start, end)) = s.pos
|
||||
settings find (_._1.key == s.key) match {
|
||||
case Some(ss @ (ns, newLines)) if !ns.init.dependencies.contains(ns.key) =>
|
||||
val shifted = ns withPos RangePosition(path, LineRange(start - offs, start - offs + newLines.size))
|
||||
(offs + end - start - newLines.size, shifted :: olds, ss :: repl, lineMap + (start -> (end, newLines)))
|
||||
case _ =>
|
||||
val shifted = s withPos RangePosition(path, r shift -offs)
|
||||
(offs, shifted :: olds, repl, lineMap)
|
||||
}
|
||||
}
|
||||
val newSettings = settings diff replace
|
||||
val (tmpLines, _) = ((List[String](), 1) /: IO.readLines(writeTo).zipWithIndex) {
|
||||
case ((accLines, n), (line, m)) if n == m + 1 =>
|
||||
lineMap.get(n) match {
|
||||
case Some(Pair(end, lines)) => (lines reverse_::: accLines, end)
|
||||
case None => (line :: accLines, n + 1)
|
||||
}
|
||||
case (res, _) => res
|
||||
}
|
||||
val exist = tmpLines.reverse
|
||||
val adjusted = if (!newSettings.isEmpty && needsTrailingBlank(exist)) exist :+ "" else exist
|
||||
val lines = adjusted ++ newSettings.flatMap(_._2 ::: "" :: Nil)
|
||||
IO.writeLines(writeTo, lines)
|
||||
val (newWithPos, _) = ((List[SessionSetting](), adjusted.size + 1) /: newSettings) {
|
||||
case ((acc, line), (s, newLines)) =>
|
||||
val endLine = line + newLines.size
|
||||
((s withPos RangePosition(path, LineRange(line, endLine)), newLines) :: acc, endLine + 1)
|
||||
}
|
||||
(newWithPos.reverse, other ++ oldShifted)
|
||||
val path = writeTo.getAbsolutePath
|
||||
val (inFile, other, _) = ((List[Setting[_]](), List[Setting[_]](), Set.empty[ScopedKey[_]]) /: original.reverse) {
|
||||
case ((in, oth, keys), s) =>
|
||||
s.pos match {
|
||||
case RangePosition(`path`, _) if !keys.contains(s.key) => (s :: in, oth, keys + s.key)
|
||||
case _ => (in, s :: oth, keys)
|
||||
}
|
||||
}
|
||||
|
||||
val (_, oldShifted, replace) = ((0, List[Setting[_]](), Seq[SessionSetting]()) /: inFile) {
|
||||
case ((offs, olds, repl), s) =>
|
||||
val RangePosition(_, r @ LineRange(start, end)) = s.pos
|
||||
settings find (_._1.key == s.key) match {
|
||||
case Some(ss @ (ns, newLines)) if !ns.init.dependencies.contains(ns.key) =>
|
||||
val shifted = ns withPos RangePosition(path, LineRange(start - offs, start - offs + newLines.size))
|
||||
(offs + end - start - newLines.size, shifted :: olds, ss +: repl)
|
||||
case _ =>
|
||||
val shifted = s withPos RangePosition(path, r shift -offs)
|
||||
(offs, shifted :: olds, repl)
|
||||
}
|
||||
}
|
||||
val newSettings = settings diff replace
|
||||
val oldContent = IO.readLines(writeTo)
|
||||
val (_, exist) = SbtRefactorings.applySessionSettings((writeTo, oldContent), replace)
|
||||
val adjusted = if (!newSettings.isEmpty && needsTrailingBlank(exist)) exist :+ "" else exist
|
||||
val lines = adjusted ++ newSettings.flatMap(x => x._2 :+ "")
|
||||
IO.writeLines(writeTo, lines)
|
||||
val (newWithPos, _) = ((List[SessionSetting](), adjusted.size + 1) /: newSettings) {
|
||||
case ((acc, line), (s, newLines)) =>
|
||||
val endLine = line + newLines.size
|
||||
((s withPos RangePosition(path, LineRange(line, endLine)), newLines) :: acc, endLine + 1)
|
||||
}
|
||||
(newWithPos.reverse, other ++ oldShifted)
|
||||
}
|
||||
|
||||
@deprecated("This method will no longer be publlic", "0.13.7")
|
||||
def needsTrailingBlank(lines: Seq[String]) = !lines.isEmpty && !lines.takeRight(1).exists(_.trim.isEmpty)
|
||||
|
||||
/** Prints all the user-defined SessionSettings (not raw) to System.out. */
|
||||
def printAllSettings(s: State): State =
|
||||
withSettings(s) { session =>
|
||||
for ((ref, settings) <- session.append if !settings.isEmpty) {
|
||||
|
|
@ -141,11 +229,15 @@ object SessionSettings {
|
|||
}
|
||||
s
|
||||
}
|
||||
|
||||
/** Prints all the defined session settings for the current project in the given build state. */
|
||||
def printSettings(s: State): State =
|
||||
withSettings(s) { session =>
|
||||
printSettings(session.append.getOrElse(session.current, Nil))
|
||||
s
|
||||
}
|
||||
|
||||
/** Prints all the passed in session settings */
|
||||
def printSettings(settings: Seq[SessionSetting]): Unit =
|
||||
for (((_, stringRep), index) <- settings.zipWithIndex)
|
||||
println(" " + (index + 1) + ". " + stringRep.mkString("\n"))
|
||||
|
|
@ -183,15 +275,21 @@ save, save-all
|
|||
The session settings defined for a project are appended to the first '.sbt' configuration file in that project.
|
||||
If no '.sbt' configuration file exists, the settings are written to 'build.sbt' in the project's base directory."""
|
||||
|
||||
/** AST for the syntax of the session command. Each subclass is an action that can be performed. */
|
||||
sealed trait SessionCommand
|
||||
|
||||
final class Print(val all: Boolean) extends SessionCommand
|
||||
|
||||
final class Clear(val all: Boolean) extends SessionCommand
|
||||
|
||||
final class Save(val all: Boolean) extends SessionCommand
|
||||
|
||||
final class Remove(val ranges: Seq[(Int, Int)]) extends SessionCommand
|
||||
|
||||
import complete._
|
||||
import DefaultParsers._
|
||||
|
||||
/** Parser for the session command. */
|
||||
lazy val parser =
|
||||
token(Space) ~>
|
||||
(token("list-all" ^^^ new Print(true)) | token("list" ^^^ new Print(false)) | token("clear" ^^^ new Clear(false)) |
|
||||
|
|
@ -199,9 +297,12 @@ save, save-all
|
|||
remove)
|
||||
|
||||
lazy val remove = token("remove") ~> token(Space) ~> natSelect.map(ranges => new Remove(ranges))
|
||||
|
||||
def natSelect = rep1sep(token(range, "<range>"), ',')
|
||||
|
||||
def range: Parser[(Int, Int)] = (NatBasic ~ ('-' ~> NatBasic).?).map { case lo ~ hi => (lo, hi getOrElse lo) }
|
||||
|
||||
/** The raw implementation of the session command. */
|
||||
def command(s: State) = Command.applyEffect(parser) {
|
||||
case p: Print => if (p.all) printAllSettings(s) else printSettings(s)
|
||||
case v: Save => if (v.all) saveAllSettings(s) else saveSettings(s)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,457 @@
|
|||
package sbt
|
||||
package internals
|
||||
package parser
|
||||
|
||||
import java.io.File
|
||||
|
||||
import sbt.internals.parser.SbtParser._
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.reflect.runtime.universe._
|
||||
|
||||
private[sbt] object SbtParser {
|
||||
val END_OF_LINE_CHAR = '\n'
|
||||
val END_OF_LINE = String.valueOf(END_OF_LINE_CHAR)
|
||||
private[parser] val NOT_FOUND_INDEX = -1
|
||||
private[sbt] val FAKE_FILE = new File("fake")
|
||||
}
|
||||
|
||||
/**
|
||||
* This method soley exists to add scaladoc to members in SbtParser which
|
||||
* are defined using pattern matching.
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* An initial parser/splitter of .sbt files.
|
||||
*
|
||||
* This class is responsible for chunking a `.sbt` file into expression ranges
|
||||
* which we can then compile using the Scala compiler.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* {{{
|
||||
* val parser = SbtParser(myFile, IO.readLines(myFile))
|
||||
* // All import statements
|
||||
* val imports = parser.imports
|
||||
* // All other statements (val x =, or raw settings)
|
||||
* val settings = parser.settings
|
||||
* }}}
|
||||
*
|
||||
* @param file The file we're parsing (may be a dummy file)
|
||||
* @param lines The parsed "lines" of the file, where each string is a line.
|
||||
*/
|
||||
private[sbt] case class SbtParser(file: File, lines: Seq[String]) extends ParsedSbtFileExpressions {
|
||||
//settingsTrees,modifiedContent needed for "session save"
|
||||
// TODO - We should look into splitting out "defintiions" vs. "settings" here instead of further string lookups, since we have the
|
||||
// parsed trees.
|
||||
val (imports, settings, settingsTrees, modifiedContent) = splitExpressions(file, lines)
|
||||
|
||||
private def splitExpressions(file: File, lines: Seq[String]): (Seq[(String, Int)], Seq[(String, LineRange)], Seq[(String, Tree)], String) = {
|
||||
import sbt.internals.parser.MissingBracketHandler._
|
||||
import sbt.internals.parser.XmlContent._
|
||||
|
||||
import scala.compat.Platform.EOL
|
||||
import scala.reflect.runtime._
|
||||
import scala.tools.reflect.{ ToolBox, ToolBoxError }
|
||||
|
||||
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 modifiedContent = handleXmlContent(original)
|
||||
val fileName = file.getAbsolutePath
|
||||
|
||||
val parsed =
|
||||
try {
|
||||
toolbox.parse(modifiedContent)
|
||||
} catch {
|
||||
case e: ToolBoxError =>
|
||||
val seq = toolbox.frontEnd.infos.map { i =>
|
||||
s"""[$fileName]:${i.pos.line}: ${i.msg}"""
|
||||
}
|
||||
throw new MessageOnlyException(
|
||||
s"""======
|
||||
|$modifiedContent
|
||||
|======
|
||||
|${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) =
|
||||
(modifiedContent.substring(t.pos.start, t.pos.end), t.pos.line - 1)
|
||||
|
||||
/**
|
||||
* See BugInParser
|
||||
* @param t - tree
|
||||
* @param originalStatement - original
|
||||
* @return originalStatement or originalStatement with missing bracket
|
||||
*/
|
||||
def parseStatementAgain(t: Tree, originalStatement: String): String = {
|
||||
val statement = util.Try(toolbox.parse(originalStatement)) match {
|
||||
case util.Failure(th) =>
|
||||
val missingText = findMissingText(modifiedContent, t.pos.end, t.pos.line, fileName, th)
|
||||
originalStatement + missingText
|
||||
case _ =>
|
||||
originalStatement
|
||||
}
|
||||
statement
|
||||
}
|
||||
|
||||
def convertStatement(t: Tree): Option[(String, Tree, LineRange)] =
|
||||
t.pos match {
|
||||
case NoPosition =>
|
||||
None
|
||||
case position =>
|
||||
val originalStatement = modifiedContent.substring(position.start, position.end)
|
||||
val statement = parseStatementAgain(t, originalStatement)
|
||||
val numberLines = countLines(statement)
|
||||
Some((statement, t, LineRange(position.line - 1, position.line + numberLines)))
|
||||
}
|
||||
val stmtTreeLineRange = statements flatMap convertStatement
|
||||
(imports map convertImport, stmtTreeLineRange.map { case (stmt, _, lr) => (stmt, lr) }, stmtTreeLineRange.map { case (stmt, tree, _) => (stmt, tree) }, modifiedContent)
|
||||
}
|
||||
|
||||
private def countLines(statement: String) = statement.count(c => c == END_OF_LINE_CHAR)
|
||||
}
|
||||
|
||||
/**
|
||||
* Scala parser cuts last bracket -
|
||||
* @see https://github.com/scala/scala/pull/3991
|
||||
*/
|
||||
private[sbt] object MissingBracketHandler {
|
||||
/**
|
||||
*
|
||||
* @param content - parsed file
|
||||
* @param positionEnd - from index
|
||||
* @param positionLine - number of start position line
|
||||
* @param fileName - file name
|
||||
* @param originalException - original exception
|
||||
* @return missing text
|
||||
*/
|
||||
private[sbt] def findMissingText(content: String, positionEnd: Int, positionLine: Int, fileName: String, originalException: Throwable): String = {
|
||||
findClosingBracketIndex(content, positionEnd) match {
|
||||
case Some(index) =>
|
||||
val text = content.substring(positionEnd, index + 1)
|
||||
val textWithoutBracket = text.substring(0, text.length - 1)
|
||||
util.Try(SbtParser(FAKE_FILE, textWithoutBracket.lines.toSeq)) match {
|
||||
case util.Success(_) =>
|
||||
text
|
||||
case util.Failure(th) =>
|
||||
findMissingText(content, index + 1, positionLine, fileName, originalException)
|
||||
}
|
||||
case _ =>
|
||||
throw new MessageOnlyException(s"""[$fileName]:$positionLine: ${originalException.getMessage}""".stripMargin)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param content - parsed file
|
||||
* @param from - start index
|
||||
* @return first not commented index or None
|
||||
*/
|
||||
private[sbt] def findClosingBracketIndex(content: String, from: Int): Option[Int] = {
|
||||
val index = content.indexWhere(c => c == '}' || c == ')', from)
|
||||
if (index == NOT_FOUND_INDEX) {
|
||||
None
|
||||
} else {
|
||||
Some(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* #ToolBox#parse(String) will fail for xml sequence:
|
||||
* <pre>
|
||||
* val xml = <div>txt</div>
|
||||
* <a>rr</a>
|
||||
* </pre>
|
||||
* At least brackets have to be added
|
||||
* <pre>
|
||||
* val xml = (<div>txt</div>
|
||||
* <a>rr</a>)
|
||||
* </pre>
|
||||
*/
|
||||
private[sbt] object XmlContent {
|
||||
|
||||
private val OPEN_PARENTHESIS = '{'
|
||||
|
||||
private val OPEN_CURLY_BRACKET = '('
|
||||
|
||||
private val DOUBLE_SLASH = "//"
|
||||
|
||||
private val OPEN_BRACKET = s" $OPEN_CURLY_BRACKET "
|
||||
|
||||
private val CLOSE_BRACKET = " ) "
|
||||
|
||||
/**
|
||||
*
|
||||
* @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 - 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 - 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 == NOT_FOUND_INDEX) {
|
||||
subs
|
||||
} else {
|
||||
subs.substring(0, spaceIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modified Opening Tag - <aaa/>
|
||||
* @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 == NOT_FOUND_INDEX) {
|
||||
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 == NOT_FOUND_INDEX) {
|
||||
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 == NOT_FOUND_INDEX) {
|
||||
subs.lastIndexOf(s"<$tagName ")
|
||||
} else {
|
||||
index
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml like - <aaa>...<aaa/>
|
||||
* @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 == NOT_FOUND_INDEX) {
|
||||
acc
|
||||
} else {
|
||||
val closeTagEndIndex = content.indexOf(">", closeTagStartIndex)
|
||||
if (closeTagEndIndex == NOT_FOUND_INDEX) {
|
||||
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 - content
|
||||
* @param xmlParts - xmlParts
|
||||
* @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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to head if option is not empty
|
||||
* @param ts - seq
|
||||
* @param option - option
|
||||
* @tparam T - type
|
||||
* @return original seq for None, add to head for Some[T]
|
||||
*/
|
||||
private def addOptionToCollection[T](ts: Seq[T], option: Option[T]) = option.fold(ts)(el => el +: ts)
|
||||
|
||||
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 == NOT_FOUND_INDEX) {
|
||||
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 - open index
|
||||
* @param closeIndex - close index
|
||||
* @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 - statement
|
||||
* @return are brackets necessary?
|
||||
*/
|
||||
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)) {
|
||||
val roundBrackets = statement.lastIndexOf(OPEN_CURLY_BRACKET)
|
||||
val braces = statement.lastIndexOf(OPEN_PARENTHESIS)
|
||||
val max = roundBrackets.max(braces)
|
||||
if (max == NOT_FOUND_INDEX) {
|
||||
true
|
||||
} else {
|
||||
val trimmed = statement.substring(max + 1).trim
|
||||
trimmed.nonEmpty
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package sbt
|
||||
package internals
|
||||
package parser
|
||||
|
||||
import scala.reflect.runtime.universe._
|
||||
|
||||
private[sbt] object SbtRefactorings {
|
||||
|
||||
import sbt.internals.parser.SbtParser.{ END_OF_LINE, FAKE_FILE }
|
||||
import sbt.SessionSettings.{ SessionSetting, SbtConfigFile }
|
||||
|
||||
val EMPTY_STRING = ""
|
||||
val REVERSE_ORDERING_INT = Ordering[Int].reverse
|
||||
|
||||
/**
|
||||
* Refactoring a `.sbt` file so that the new settings are used instead of any existing settings.
|
||||
* @param configFile SbtConfigFile with the lines of an sbt file as a List[String] where each string is one line
|
||||
* @param commands A List of settings (space separate) that should be inserted into the current file.
|
||||
* If the settings replaces a value, it will replace the original line in the .sbt file.
|
||||
* If in the `.sbt` file we have multiply value for one settings -
|
||||
* the first will be replaced and the other will be removed.
|
||||
* @return a SbtConfigFile with new lines which represent the contents of the refactored .sbt file.
|
||||
*/
|
||||
def applySessionSettings(configFile: SbtConfigFile, commands: Seq[SessionSetting]): SbtConfigFile = {
|
||||
val (file, lines) = configFile
|
||||
val split = SbtParser(FAKE_FILE, lines)
|
||||
val recordedCommands = recordCommands(commands, split)
|
||||
val sortedRecordedCommands = recordedCommands.sortBy(_._1)(REVERSE_ORDERING_INT)
|
||||
|
||||
val newContent = replaceFromBottomToTop(split.modifiedContent, sortedRecordedCommands)
|
||||
(file, newContent.lines.toList)
|
||||
}
|
||||
|
||||
private def replaceFromBottomToTop(modifiedContent: String, sortedRecordedCommands: Seq[(Int, String, String)]) = {
|
||||
sortedRecordedCommands.foldLeft(modifiedContent) {
|
||||
case (acc, (from, old, replacement)) =>
|
||||
val before = acc.substring(0, from)
|
||||
val after = acc.substring(from + old.length, acc.length)
|
||||
val afterLast = emptyStringForEmptyString(after)
|
||||
before + replacement + afterLast
|
||||
}
|
||||
}
|
||||
|
||||
private def emptyStringForEmptyString(text: String) = {
|
||||
val trimmed = text.trim
|
||||
if (trimmed.isEmpty) trimmed else text
|
||||
}
|
||||
|
||||
private def recordCommands(commands: Seq[SessionSetting], split: SbtParser) =
|
||||
commands.flatMap {
|
||||
case (_, command) =>
|
||||
val map = toTreeStringMap(command)
|
||||
map.flatMap {
|
||||
case (name, statement) =>
|
||||
treesToReplacements(split, name, command)
|
||||
}
|
||||
}
|
||||
|
||||
private def treesToReplacements(split: SbtParser, name: String, command: Seq[String]) =
|
||||
split.settingsTrees.foldLeft(Seq.empty[(Int, String, String)]) {
|
||||
case (acc, (st, tree)) =>
|
||||
val treeName = extractSettingName(tree)
|
||||
if (name == treeName) {
|
||||
val replacement = if (acc.isEmpty) {
|
||||
command.mkString(END_OF_LINE)
|
||||
} else {
|
||||
EMPTY_STRING
|
||||
}
|
||||
(tree.pos.start, st, replacement) +: acc
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
private def toTreeStringMap(command: Seq[String]) = {
|
||||
val split = SbtParser(FAKE_FILE, command)
|
||||
val trees = split.settingsTrees
|
||||
val seq = trees.map {
|
||||
case (statement, tree) =>
|
||||
(extractSettingName(tree), statement)
|
||||
}
|
||||
seq.toMap
|
||||
}
|
||||
|
||||
private def extractSettingName(tree: Tree): String =
|
||||
tree.children match {
|
||||
case h :: _ =>
|
||||
extractSettingName(h)
|
||||
case _ =>
|
||||
tree.toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
val a = "ss
|
||||
|
|
@ -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")
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import sbt._
|
||||
|
||||
val s = <xml>
|
||||
|
|
@ -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 <type> sections are generated")
|
||||
checkPom := {
|
||||
val pomFile = makePom.value
|
||||
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
|
||||
if(!tpe.isEmpty)
|
||||
error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
}
|
||||
val b = ( <b/>)
|
||||
val a = <aaa
|
||||
b="5">
|
||||
|
||||
</aaa>
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
}
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
/*
|
||||
OKOK
|
||||
*/
|
||||
|
||||
val b = "*/"
|
||||
val a = 4
|
||||
|
|
@ -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 := (
|
||||
<url>https://github.com/benoitguigal/twitter-spray</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>BSD-style</name>
|
||||
<url>http://www.opensource.org/licenses/bsd-license.php</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<url>git@github.com:benoitguigal/twitter-spray.git</url>
|
||||
<connection>scm:git:git@github.com:benoitguigal/twitter-spray.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>BGuigal</id>
|
||||
<name>Benoit Guigal</name>
|
||||
<url>http://benoitguigal.me</url>
|
||||
</developer>
|
||||
</developers>
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -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) := (
|
||||
<scm>
|
||||
<url>git@github.com:GenslerAppsPod/scalavro.git</url>
|
||||
<connection>scm:git:git@github.com:GenslerAppsPod/scalavro.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>ConnorDoyle</id>
|
||||
<name>Connor Doyle</name>
|
||||
<url>http://gensler.com</url>
|
||||
</developer>
|
||||
</developers>
|
||||
)
|
||||
|
||||
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")
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 := (
|
||||
<url>http://chrisnappin.github.io/play-recaptcha</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:chrisnappin/play-recaptcha.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:chrisnappin/play-recaptcha.git</developerConnection>
|
||||
<url>git@github.com:chrisnappin/play-recaptcha.git</url>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>chrisnappin</id>
|
||||
<name>Chris Nappin</name>
|
||||
<email>chris@nappin.com</email>
|
||||
<timezone>UTC</timezone>
|
||||
</developer>
|
||||
</developers>)
|
||||
|
||||
|
|
@ -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 := (
|
||||
<scm>
|
||||
<url>https://github.com/jaliss/securesocial</url>
|
||||
<connection>scm:git:git@github.com:jaliss/securesocial.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/jaliss/securesocial.git</developerConnection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>jaliss</id>
|
||||
<name>Jorge Aliss</name>
|
||||
<email>jaliss [at] gmail.com</email>
|
||||
<url>https://twitter.com/jaliss</url>
|
||||
</developer>
|
||||
</developers>
|
||||
)
|
||||
|
||||
scalacOptions := Seq("-feature", "-deprecation")
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
name := "play-html-compressor"
|
||||
|
||||
scalaVersion := "2.11.1"
|
||||
|
||||
val pom = <scm>
|
||||
<url>git@github.com:mohiva/play-html-compressor.git</url>
|
||||
<connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>akkie</id>
|
||||
<name>Christian Kaps</name>
|
||||
<url>http://mohiva.com</url>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
publishMavenStyle := true
|
||||
|
||||
|
||||
|
||||
|
|
@ -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 := (
|
||||
<url>https://github.com/etsy/Conjecture</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT License</name>
|
||||
<url>http://opensource.org/licenses/MIT</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<url>git@github.com:etsy/Conjecture.git</url>
|
||||
<connection>scm:git:git@github.com:etsy/Conjecture.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>jattenberg</id>
|
||||
<name>Josh Attenberg</name>
|
||||
<url>github.com/jattenberg</url>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>rjhall</id>
|
||||
<name>Rob Hall</name>
|
||||
<url>github.com/rjhall</url>
|
||||
</developer>
|
||||
</developers>
|
||||
)
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
//import sbt._
|
||||
// val a = 3
|
||||
|
|
@ -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 := {}
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
@ -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 := (
|
||||
<url>http://github.com/germanosin/play-foldermessages</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT License</name>
|
||||
<url>http://opensource.org/licenses/mit-license.php</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<url>git@github.com:germanosin/play-foldermessages.git</url>
|
||||
<connection>scm:git:git@github.com:germanosin/play-foldermessages.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>germanosin</id>
|
||||
<name>German Osin</name>
|
||||
</developer>
|
||||
</developers>
|
||||
),
|
||||
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)
|
||||
|
|
@ -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/"
|
||||
|
|
@ -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 := (
|
||||
<developers>
|
||||
<developer>
|
||||
<id>marcuslonnberg</id>
|
||||
<name>Marcus Lönnberg</name>
|
||||
<url>http://marcuslonnberg.se</url>
|
||||
</developer>
|
||||
</developers>
|
||||
)
|
||||
|
|
@ -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 := (
|
||||
<url>https://github.com/sksamuel/akka-patterns</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<url>git@github.com:sksamuel/akka-patterns.git</url>
|
||||
<connection>scm:git@github.com:sksamuel/akka-patterns.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>sksamuel</id>
|
||||
<name>sksamuel</name>
|
||||
<url>http://github.com/akka-patterns</url>
|
||||
</developer>
|
||||
</developers>)
|
||||
|
|
@ -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"
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
k4 := { val x = k4.value; () }
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
k4 := ()
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := (); k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
name := "newName"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
sys.error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
};scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
organization := "jozwikr" // OK
|
||||
|
||||
scalaVersion := "2.9.2"
|
||||
|
||||
organization := "ololol"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
name := "alaMaKota"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
name := "alaMaKota"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
sys.error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
};scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
organization := "jozwikr" // OK
|
||||
|
||||
scalaVersion := "2.9.2"
|
||||
|
||||
organization := "ololol"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
name := "alaMaKota"
|
||||
organization := "scalania"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
name := "alaMaKota"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
sys.error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
};scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
organization := "scalania" // OK
|
||||
|
||||
scalaVersion := "2.9.2"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
checkPom := "OK"
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
name := "newName"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := "OK";scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
organization := "jozwikr" // OK
|
||||
|
||||
scalaVersion := "2.9.2"
|
||||
|
||||
organization := "ololol"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
name := "newName";scalaVersion := "2.9.2"; organization := "jozwikr"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
sys.error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
};scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
name := "alaMaKota"
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
name := "alaMaKota";scalaVersion := "2.9.2"; organization := "jozwikr"
|
||||
libraryDependencies := Seq("org.scala-sbt" %% "sbinary" % "0.4.1")
|
||||
|
||||
lazy val checkPom = taskKey[Unit]("check pom to ensure no <type> sections are generated"); checkPom := {
|
||||
val pomFile = makePom.value
|
||||
val pom = xml.XML.loadFile(pomFile)
|
||||
val tpe = pom \\ "type"
|
||||
if(!tpe.isEmpty)
|
||||
sys.error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
};scalacOptions := Seq("-deprecation")
|
||||
|
||||
val b = ( <b/>)
|
||||
val a = <aaa>
|
||||
|
||||
</aaa>
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import sbt._
|
||||
|
||||
val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
|
||||
|
||||
scmpom := <scm>
|
||||
<url>git@github.com:mohiva/play-html-compressor.git</url>
|
||||
<connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
</scm>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>akkie</id>
|
||||
<name>Christian Kaps</name>
|
||||
<url>http://mohiva.com</url>
|
||||
</developer>
|
||||
</developers>
|
||||
<a></a>
|
||||
|
|
@ -0,0 +1 @@
|
|||
scmpom := <a/><b a="rt">OK</b>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import sbt._
|
||||
|
||||
val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
|
||||
|
||||
scmpom := ( <a/><b a="rt">OK</b> )
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
k4 := { val x = k4.value; () }
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
k4 := ()
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := (); k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ object PluginCommandTestPlugin0 extends AutoPlugin
|
|||
|
||||
package subpackage {
|
||||
|
||||
object PluginCommandTestPlugin1 extends AutoPlugin
|
||||
object PluginCommandTestPlugin1 extends AutoPlugin
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import org.specs2.mutable._
|
||||
|
||||
trait AbstractSpec extends Specification with SplitExpression
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import sbt.EvaluateConfigurations
|
||||
|
||||
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).setMessage(s"""$description
|
||||
|***${shouldContains(nonEmptyStatements)} statements***
|
||||
|$content """.stripMargin)
|
||||
imports.nonEmpty must be_==(nonEmptyImports).setMessage(s"""$description
|
||||
|***${shouldContains(nonEmptyImports)} imports***
|
||||
|$content """.stripMargin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def shouldContains(b: Boolean) = s"""Should ${
|
||||
if (b) {
|
||||
"contain"
|
||||
} else {
|
||||
"not contain"
|
||||
}
|
||||
}"""
|
||||
|
||||
protected val files: Seq[(String, String, Boolean, Boolean)]
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
class CommentedXmlSpec extends CheckIfParsedSpec {
|
||||
|
||||
override protected val files = Seq(
|
||||
(
|
||||
s"""|
|
||||
|val pom = "</scm>"
|
||||
|
|
||||
|val aaa= <scm><url>git@a.com:a/a.git</url>
|
||||
| <cc>e</cc>
|
||||
| </scm>
|
||||
|
|
||||
|val tra = "</scm>"
|
||||
|
|
||||
""".stripMargin, "Xml in string", false, true),
|
||||
("""
|
||||
|val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
|
||||
|
|
||||
|scmpom := <scm>
|
||||
| <url>git@github.com:mohiva/play-html-compressor.git</url>
|
||||
| <connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
| </scm>
|
||||
| <developers>
|
||||
| <developer>
|
||||
| <id>akkie</id>
|
||||
| <name>Christian Kaps</name>
|
||||
| <url>http://mohiva.com</url>
|
||||
| </developer>
|
||||
| </developers>
|
||||
| //<aaa/>
|
||||
| <a></a>
|
||||
|
|
||||
|publishMavenStyle := true
|
||||
|
|
||||
""".stripMargin, "Wrong Commented xml ", false, true),
|
||||
("""
|
||||
|val scmpom = taskKey[xml.NodeBuffer]("Node buffer")
|
||||
|
|
||||
|scmpom := <scm>
|
||||
| <url>git@github.com:mohiva/play-html-compressor.git</url>
|
||||
| <connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
| </scm>
|
||||
| <developers>
|
||||
| <developer>
|
||||
| <id>akkie</id>
|
||||
| <name>Christian Kaps</name>
|
||||
| <url>http://mohiva.com</url>
|
||||
| </developer>
|
||||
| </developers>
|
||||
| //<aaa/>
|
||||
| //<a></a>
|
||||
|
|
||||
|publishMavenStyle := true
|
||||
|
|
||||
""".stripMargin, "Commented xml ", false, true),
|
||||
("""
|
||||
|import sbt._
|
||||
|
|
||||
|// </a
|
||||
""".stripMargin, "Xml in comment", true, false),
|
||||
("""
|
||||
|// a/>
|
||||
""".stripMargin, "Xml in comment2", false, false)
|
||||
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import sbt.MessageOnlyException
|
||||
|
||||
class EmbeddedXmlSpec extends CheckIfParsedSpec {
|
||||
|
||||
"File with xml content " should {
|
||||
|
||||
"Handle last xml part" in {
|
||||
val errorLine = """<version>4.0<version>"""
|
||||
val buildSbt = s"""|
|
||||
|
|
||||
|name := "play-html-compressor"
|
||||
|
|
||||
|scalaVersion := "2.11.1"
|
||||
|
|
||||
|val pom = <scm>
|
||||
|<url>git@github.com:mhiva/play-html-compressor.git</url>
|
||||
|<connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
| </scm>
|
||||
|<developers>
|
||||
| <developer>
|
||||
| <id>akkie</id>
|
||||
| <name>Christian Kaps</name>
|
||||
| <url>http://mohiva.com</url>
|
||||
| </developer>
|
||||
| </developers>
|
||||
|$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 = <a/>
|
||||
""".stripMargin, "Xml modified closing tag at end of file", false, true),
|
||||
("""
|
||||
|val p = <a></a>
|
||||
""".stripMargin, "Xml at end of file", false, true),
|
||||
("""|
|
||||
|
|
||||
|name := "play-html-compressor"
|
||||
|
|
||||
|scalaVersion := "2.11.1"
|
||||
|
|
||||
|val lll = "</=+=>"
|
||||
|
|
||||
|val not = "<sss><sss>"
|
||||
|
|
||||
|val aaa = "ass/>"
|
||||
|
|
||||
|val pom = "</scm>"
|
||||
|
|
||||
|val aaa= <scm><url>git@github.com:mohiva/play-html-compressor.git</url>
|
||||
| <connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
| </scm>
|
||||
| <developers>
|
||||
| <developer>
|
||||
| <id>akkie</id>
|
||||
| <name>Christian Kaps</name>
|
||||
| <url>http://mohiva.com</url>
|
||||
| </developer>
|
||||
| </developers>
|
||||
| <version>4.0</version>
|
||||
|
|
||||
|publishMavenStyle := true
|
||||
|
|
||||
|val anotherXml = <a a="r"><bbb>
|
||||
| content</bbb>
|
||||
| <ccc atr="tre" />
|
||||
| <aa/>
|
||||
| </a>
|
||||
|
|
||||
|val tra = "</scm>"
|
||||
|
|
||||
""".stripMargin, "Xml in string", false, true),
|
||||
("""|
|
||||
|
|
||||
|name := "play-html-compressor"
|
||||
|
|
||||
|scalaVersion := "2.11.1"
|
||||
|
|
||||
|val ok = <ccc atr="tre" />
|
||||
|
|
||||
|val pom = <scm>
|
||||
|<url>git@github.com:mhiva/play-html-compressor.git</url>
|
||||
| <connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
|
||||
|</scm>
|
||||
|<developers>
|
||||
|<developer>
|
||||
|<id>akkie</id>
|
||||
|<name>Christian Kaps</name>
|
||||
|<url>http://mohiva.com</url>
|
||||
|</developer>
|
||||
|</developers>
|
||||
|<version>4.0</version>
|
||||
|
|
||||
|publishMavenStyle := true
|
||||
|
|
||||
|val anotherXml = <a a="r"><bbb>
|
||||
| content</bbb>
|
||||
| <ccc atr="tre" />
|
||||
|<aa/>
|
||||
| </a>
|
||||
|
|
||||
| """.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 <type> sections are generated")
|
||||
|
|
||||
|checkPom := {
|
||||
| val pomFile = makePom.value
|
||||
| val pom = xml.XML.loadFile(pomFile)
|
||||
| val tpe = pom \\ "type"
|
||||
| if(!tpe.isEmpty)
|
||||
| error("Expected no <type> sections, got: " + tpe + " in \n\n" + pom)
|
||||
|}
|
||||
|
|
||||
|
|
||||
|val a = <aaa>
|
||||
|
|
||||
|</aaa>
|
||||
|
|
||||
|
|
||||
|
|
||||
""".stripMargin, "xml with blank line", false, true)
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import java.io.File
|
||||
|
||||
import org.specs2.ScalaCheck
|
||||
import sbt.{ EvaluateConfigurations, MessageOnlyException }
|
||||
|
||||
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.getClassLoader.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")
|
||||
SbtParser(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
|
||||
MissingBracketHandler.findMissingText(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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import java.io.File
|
||||
|
||||
import sbt.LineRange
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
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
|
||||
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
class NewFormatSpec extends AbstractSpec {
|
||||
implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
|
||||
|
||||
"New Format " should {
|
||||
"Handle lines " in {
|
||||
val rootPath = getClass.getClassLoader.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).setMessage(s"""
|
||||
|***should contains statements***
|
||||
|$lines """.stripMargin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package sbt
|
||||
package internals
|
||||
package parser
|
||||
|
||||
import java.io.{ File, FilenameFilter }
|
||||
|
||||
import org.specs2.matcher.MatchResult
|
||||
|
||||
import scala.collection.GenTraversableOnce
|
||||
import scala.io.Source
|
||||
import SessionSettings.SessionSetting
|
||||
|
||||
abstract class AbstractSessionSettingsSpec(folder: String) extends AbstractSpec {
|
||||
protected val rootPath = getClass.getClassLoader.getResource("").getPath + folder
|
||||
println(s"Reading files from: $rootPath")
|
||||
protected val rootDir = new File(rootPath)
|
||||
|
||||
"SessionSettings " should {
|
||||
"Be identical for empty map " in {
|
||||
def unit(f: File) = Seq((Source.fromFile(f).getLines().toList, Seq()))
|
||||
runTestOnFiles(unit)
|
||||
}
|
||||
|
||||
"Replace statements " in {
|
||||
runTestOnFiles(replace)
|
||||
}
|
||||
}
|
||||
|
||||
private def runTestOnFiles(expectedResultAndMap: File => Seq[(List[String], Seq[SessionSetting])]): MatchResult[GenTraversableOnce[File]] = {
|
||||
|
||||
val allFiles = rootDir.listFiles(new FilenameFilter() {
|
||||
def accept(dir: File, name: String) = name.endsWith(".sbt.txt")
|
||||
}).toList
|
||||
foreach(allFiles) {
|
||||
file =>
|
||||
val originalLines = Source.fromFile(file).getLines().toList
|
||||
foreach(expectedResultAndMap(file)) {
|
||||
case (expectedResultList, commands) =>
|
||||
val resultList = SbtRefactorings.applySessionSettings((file, originalLines), commands)
|
||||
val expected = SbtParser(file, expectedResultList)
|
||||
val result = SbtParser(file, resultList._2)
|
||||
result.settings must_== expected.settings
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected def replace(f: File) = {
|
||||
val dirs = rootDir.listFiles(new FilenameFilter() {
|
||||
def accept(dir: File, name: String) = {
|
||||
val startsWith = f.getName + "_"
|
||||
name.startsWith(startsWith)
|
||||
}
|
||||
}).toSeq
|
||||
dirs.flatMap {
|
||||
dir =>
|
||||
val files = dir.listFiles(new FilenameFilter {
|
||||
override def accept(dir: File, name: String) = name.endsWith(".set")
|
||||
})
|
||||
files.map { file =>
|
||||
val seq = Source.fromFile(file).getLines().toSeq
|
||||
val result = Source.fromFile(file.getAbsolutePath + ".result").getLines().toList
|
||||
val sessionSettings = seq.map(line => (null, Seq(line)))
|
||||
(result, sessionSettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SessionSettingsSpec extends AbstractSessionSettingsSpec("session-settings")
|
||||
|
||||
//class SessionSettingsQuickSpec extends AbstractSessionSettingsSpec("session-settings-quick", true)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import java.io.File
|
||||
|
||||
import sbt.LineRange
|
||||
|
||||
object SplitExpressions {
|
||||
type SplitExpression = (File, Seq[String]) => (Seq[(String, Int)], Seq[(String, LineRange)])
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import java.io.File
|
||||
|
||||
import org.specs2.mutable.SpecificationLike
|
||||
|
||||
trait SplitExpression {
|
||||
def split(s: String, file: File = new File("noFile"))(implicit splitter: SplitExpressions.SplitExpression) = splitter(file, 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package sbt
|
||||
package internals
|
||||
package parser
|
||||
|
||||
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.getClassLoader.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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package sbt.internals.parser
|
||||
|
||||
import org.specs2.mutable.Specification
|
||||
import sbt.EvaluateConfigurations
|
||||
|
||||
class SplitExpressionsTest extends Specification with SplitExpressionsBehavior {
|
||||
|
||||
"EvaluateConfigurationsOriginal" should oldExpressionsSplitter(EvaluateConfigurationsOriginal.splitExpressions)
|
||||
|
||||
"EvaluateConfigurations" should oldExpressionsSplitter(EvaluateConfigurations.splitExpressions)
|
||||
|
||||
"EvaluateConfigurations" should newExpressionsSplitter(EvaluateConfigurations.splitExpressions)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[1606]: https://github.com/sbt/sbt/issues/1606
|
||||
[1645]: https://github.com/sbt/sbt/pull/1645
|
||||
|
||||
### whitespace handling improvements
|
||||
|
||||
Starting sbt 0.13.7, build.sbt will be parsed using a customized Scala parser. This eliminates the requirement to use blank line as the delimiter between each settings, and also allows blank lines to be inserted at arbitrary position within a block.
|
||||
|
||||
This feature was contributed by [Andrzej Jozwik @ajozwik](https://github.com/ajozwik) inspired by Typesafe's @gkossakowski organizing multiple meetups with Warszaw Scala on [how to patch sbt specifically with the focus on blank line issue](http://blog.japila.pl/2014/07/gkossakowski-on-warszawscala-about-how-to-patch-scalasbt/). [#1606][1606]/[#1645][1645]
|
||||
|
|
@ -2,3 +2,11 @@ k1 := {error("k1")}
|
|||
|
||||
k2 <<= k1 map identity
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
|
@ -2,3 +2,11 @@ k1 := {}
|
|||
|
||||
k2 <<= k1 map identity
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
|
|
|||
|
|
@ -2,5 +2,14 @@ k1 := {}
|
|||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
k4 := { val x = k4.value; () }
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
k1 := {}
|
||||
|
||||
k2 := {}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := (); k5 := ()
|
||||
|
||||
k1 <<= k1 map {_ => error("k1")}
|
||||
|
||||
|
|
@ -4,3 +4,11 @@ k1 := {
|
|||
k2 := {
|
||||
}
|
||||
|
||||
k3 := {
|
||||
|
||||
|
||||
val x = "hi"
|
||||
()
|
||||
}
|
||||
|
||||
k4 := { }; k5 := ()
|
||||
|
|
@ -3,6 +3,9 @@ import sbt._
|
|||
object TestBuild extends Build {
|
||||
val k1 = TaskKey[Unit]("k1")
|
||||
val k2 = TaskKey[Unit]("k2")
|
||||
val k3 = TaskKey[Unit]("k3")
|
||||
val k4 = TaskKey[Unit]("k4")
|
||||
val k5 = TaskKey[Unit]("k4")
|
||||
|
||||
lazy val root = Project("root", file("."))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,4 +22,12 @@ $ must-mirror build.sbt build.check.2
|
|||
> reload
|
||||
-> k1
|
||||
> k2
|
||||
$ must-mirror build.sbt build.check.3
|
||||
$ must-mirror build.sbt build.check.3
|
||||
|
||||
> set k4 := { val x = k4.value; () }
|
||||
> session save
|
||||
$ must-mirror build.sbt build.check.4
|
||||
|
||||
> set k4 := ()
|
||||
> session save
|
||||
$ must-mirror build.sbt build.check.5
|
||||
|
|
@ -8,3 +8,5 @@ k1 := {
|
|||
k2 := {
|
||||
println("This is k2")
|
||||
}
|
||||
|
||||
val x = 5; k3 := {}; k4 := {}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
name := "projectName"
|
||||
|
||||
k1 := {
|
||||
//
|
||||
//
|
||||
}
|
||||
|
||||
k2 := {
|
||||
println("This is k2")
|
||||
}
|
||||
|
||||
val x = 5; k3 := {
|
||||
//
|
||||
//
|
||||
}; k4 := {}
|
||||
|
|
@ -5,3 +5,5 @@ k1 := {}
|
|||
k2 := {
|
||||
println("This is k2")
|
||||
}
|
||||
|
||||
val x = 5; k3 := {}; k4 := {}
|
||||
|
|
@ -4,6 +4,8 @@ import Keys._
|
|||
object build extends Build {
|
||||
lazy val k1 = taskKey[Unit]("")
|
||||
lazy val k2 = taskKey[Unit]("")
|
||||
lazy val k3 = taskKey[Unit]("")
|
||||
lazy val k4 = taskKey[Unit]("")
|
||||
|
||||
val UpdateK1 = Command.command("UpdateK1") { st: State =>
|
||||
val ex = Project extract st
|
||||
|
|
@ -17,8 +19,21 @@ object build extends Build {
|
|||
SessionSettings.saveAllSettings(st1)
|
||||
}
|
||||
|
||||
|
||||
val UpdateK3 = Command.command("UpdateK3") { st: State =>
|
||||
val ex = Project extract st
|
||||
import ex._
|
||||
val session2 = BuiltinCommands.setThis(st, ex, Seq(k3 := {}), """k3 := {
|
||||
|//
|
||||
|//
|
||||
|}""".stripMargin).session
|
||||
val st1 = BuiltinCommands.reapply(session2, structure, st)
|
||||
// SessionSettings.writeSettings(ex.currentRef, session2, ex.session.original, ex.structure)
|
||||
SessionSettings.saveAllSettings(st1)
|
||||
}
|
||||
|
||||
lazy val root = Project("root", file(".")) settings(
|
||||
commands += UpdateK1
|
||||
commands ++= Seq(UpdateK1, UpdateK3)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,5 @@
|
|||
$ must-mirror build.sbt build.check.1
|
||||
> UpdateK1
|
||||
$ must-mirror build.sbt build.check.1
|
||||
> UpdateK3
|
||||
$ must-mirror build.sbt build.check.2
|
||||
|
|
|
|||
Loading…
Reference in New Issue