summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-04 17:43:10 -0800
committerPaul Phillips <paulp@improving.org>2011-12-04 17:43:10 -0800
commit1ed57a4c19f89bc6736271fd63d465fed405c4d3 (patch)
tree3a5d7d3d91e326682486bac2acc19c4917381b25
parent261c63995ccf6a238786fd3c31796be7a965fec4 (diff)
parenta289465c70630719cbd3a74edf5502a156ef83c4 (diff)
downloadscala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.tar.gz
scala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.tar.bz2
scala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.zip
Merge branch 'master' into xsbt
-rw-r--r--build.xml29
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala44
-rw-r--r--src/compiler/scala/tools/util/EditDistance.scala54
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala19
-rw-r--r--src/library/scala/Enumeration.scala64
-rw-r--r--src/library/scala/collection/GenSeqLike.scala4
-rw-r--r--src/library/scala/collection/TraversableLike.scala4
-rw-r--r--src/library/scala/collection/immutable/Range.scala7
-rw-r--r--src/library/scala/math/package.scala12
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala70
-rw-r--r--test/files/jvm/signum.scala15
-rw-r--r--test/files/neg/nopredefs.check2
-rw-r--r--test/files/neg/reassignment.check13
-rw-r--r--test/files/neg/reassignment.scala7
-rw-r--r--test/files/neg/suggest-similar.check10
-rw-r--r--test/files/neg/suggest-similar.scala11
-rw-r--r--test/files/neg/t0903.check2
-rw-r--r--test/files/neg/t2870.check2
-rw-r--r--test/files/pos/t4758.scala17
-rw-r--r--test/files/pos/t5084.scala5
-rw-r--r--test/files/run/enums.check10
-rw-r--r--test/files/run/enums.scala55
-rw-r--r--test/files/run/parserFilter.check9
-rw-r--r--test/files/run/parserFilter.scala15
-rw-r--r--test/files/run/parserForFilter.check1
-rw-r--r--test/files/run/parserForFilter.scala12
-rw-r--r--test/files/run/parserNoSuccessMessage.check20
-rw-r--r--test/files/run/parserNoSuccessMessage.scala19
-rw-r--r--test/files/run/reify_anonymous.check1
-rw-r--r--test/files/run/reify_anonymous.scala14
-rw-r--r--test/files/run/reify_generic.check1
-rw-r--r--test/files/run/reify_generic.scala15
-rw-r--r--test/files/run/reify_inheritance.check1
-rw-r--r--test/files/run/reify_inheritance.scala23
-rw-r--r--test/files/run/reify_printf.check0
-rw-r--r--test/files/run/reify_printf.scala75
-rw-r--r--test/files/run/t4658.check80
-rw-r--r--test/files/run/t4658.scala41
-rw-r--r--test/files/run/t5230.check2
-rw-r--r--test/files/run/t5230.scala (renamed from test/pending/run/t5230.scala)0
-rw-r--r--test/pending/run/reify_csv.check10
-rw-r--r--test/pending/run/reify_csv.scala42
-rw-r--r--test/pending/run/t5224.check9
-rw-r--r--test/pending/run/t5224.scala8
-rw-r--r--test/pending/run/t5225_1.check4
-rw-r--r--test/pending/run/t5225_1.scala8
-rw-r--r--test/pending/run/t5225_2.check4
-rw-r--r--test/pending/run/t5225_2.scala8
-rw-r--r--test/pending/run/t5229_1.check0
-rw-r--r--test/pending/run/t5229_1.scala14
-rw-r--r--test/pending/run/t5229_2.check2
-rw-r--r--test/pending/run/t5229_2.scala19
-rw-r--r--test/pending/run/t5230.check1
-rw-r--r--test/pending/run/t5266_1.check2
-rw-r--r--test/pending/run/t5266_1.scala23
-rw-r--r--test/pending/run/t5266_2.check2
-rw-r--r--test/pending/run/t5266_2.scala17
-rw-r--r--test/pending/run/t5269.check1
-rw-r--r--test/pending/run/t5269.scala22
-rw-r--r--test/pending/run/t5270.check1
-rw-r--r--test/pending/run/t5270.scala26
-rwxr-xr-xtools/get-scala-revision28
-rw-r--r--tools/get-scala-revision.bat27
70 files changed, 987 insertions, 120 deletions
diff --git a/build.xml b/build.xml
index 1694ba8b7a..6a708755a3 100644
--- a/build.xml
+++ b/build.xml
@@ -201,7 +201,17 @@ PROPERTIES
INITIALISATION
============================================================================ -->
- <target name="init">
+ <condition property="starr.absent">
+ <not><available file="${lib.dir}/scala-library.jar"/></not>
+ </condition>
+
+ <target name="init.starr" if="starr.absent">
+ <echo level="warn" message="Downloading bootstrap libs. (To do this by hand, run ./pull-binary-libs.sh)"/>
+ <exec osfamily="unix" vmlauncher="false" executable="./pull-binary-libs.sh" failifexecutionfails="true" />
+ <exec osfamily="windows" vmlauncher="false" executable="pull-binary-libs.sh" failifexecutionfails="true" />
+ </target>
+
+ <target name="init" depends="init.starr">
<!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
@@ -222,10 +232,10 @@ INITIALISATION
<os family="windows"/>
</condition>
- <exec osfamily="unix" executable="tools/get-scala-revision" outputproperty="svn.number" failifexecutionfails="false" />
- <exec osfamily="windows" executable="tools/get-scala-revision.bat" outputproperty="svn.number" failifexecutionfails="false" />
+ <exec osfamily="unix" executable="tools/get-scala-revision" outputproperty="git.describe" failifexecutionfails="false" />
+ <exec osfamily="windows" executable="tools/get-scala-revision.bat" outputproperty="git.describe" failifexecutionfails="false" />
<!-- some default in case something went wrong getting the revision -->
- <property name="svn.number" value="0"/>
+ <property name="git.describe" value="-unknown-"/>
<property name="init.avail" value="yes"/>
@@ -233,10 +243,11 @@ INITIALISATION
<property file="${basedir}/build.number"/>
<property
name="version.number"
- value="${version.major}.${version.minor}.${version.patch}.r${svn.number}-b${time.short}"/>
+ value="${version.major}.${version.minor}.${version.patch}.${git.describe}"/>
+
<!-- And print-out what we are building -->
<echo level="info" message="Build number is '${version.number}'"/>
- <echo level="info" message="Built ${time.human} from revision ${svn.number} with ${java.vm.name} ${java.version}"/>
+ <echo level="info" message="Built ${time.human} from revision ${git.describe} with ${java.vm.name} ${java.version}"/>
<!-- Local libs (developer use.) -->
<mkdir dir="${lib-extra.dir}"/>
@@ -639,7 +650,7 @@ QUICK BUILD (QUICK)
<scalacfork
destdir="${build-quick.dir}/classes/library"
compilerpathref="quick.classpath"
- params="${scalac.args.quick} -Xplugin-require:continuations -P:continuations:enable"
+ params="${scalac.args.quick} -Xplugin-require:continuations"
srcdir="${src.dir}/continuations/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1154,7 +1165,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/library"
compilerpathref="pack.classpath"
- params="${scalac.args.all} -Xplugin-require:continuations -P:continuations:enable"
+ params="${scalac.args.all} -Xplugin-require:continuations"
srcdir="${src.dir}/continuations/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1614,7 +1625,7 @@ BOOTRAPING TEST AND TEST SUITE
<partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
timeout="2400000"
srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable">
+ scalacopts="${scalac.args.optimise} -Xplugin-require:continuations">
<compilerarg value="-Xpluginsdir"/>
<compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
<compilationpath>
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala
index 6d672d9263..60b353a7c4 100644
--- a/src/compiler/scala/reflect/internal/Importers.scala
+++ b/src/compiler/scala/reflect/internal/Importers.scala
@@ -231,6 +231,8 @@ trait Importers { self: SymbolTable =>
new PackageDef(importRefTree(pid), stats map importTree)
case from.ModuleDef(mods, name, impl) =>
new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl))
+ case from.emptyValDef =>
+ emptyValDef
case from.ValDef(mods, name, tpt, rhs) =>
new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 320fb949ff..265261f594 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -4174,8 +4174,16 @@ A type's typeSymbol should never be inspected directly.
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
if (phase.flatClasses) {
sym
+ } else if (sym == definitions.RootClass) {
+ definitions.RootClass
+ } else if (sym == definitions.RootPackage) {
+ definitions.RootPackage
} else if (sym.isModuleClass) {
- adaptToNewRun(pre, sym.sourceModule).moduleClass
+ val sourceModule1 = adaptToNewRun(pre, sym.sourceModule)
+ val result = sourceModule1.moduleClass
+ val msg = "sym = %s, sourceModule = %s, sourceModule.moduleClass = %s => sourceModule1 = %s, sourceModule1.moduleClass = %s"
+ assert(result != NoSymbol, msg.format(sym, sym.sourceModule, sym.sourceModule.moduleClass, sourceModule1, sourceModule1.moduleClass))
+ result
} else if ((pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass) {
sym
} else {
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 9668debbbb..85849cfad4 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -257,6 +257,10 @@ trait Trees extends reflect.internal.Trees { self: Global =>
case _: DefTree | Function(_, _) | Template(_, _, _) =>
resetDef(tree)
tree.tpe = null
+ tree match {
+ case tree: DefDef => tree.tpt.tpe = null
+ case _ => ()
+ }
case tpt: TypeTree =>
if (tpt.wasEmpty) tree.tpe = null
case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 5e5320ca9a..813958af85 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -563,7 +563,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
if (!nameLink.isEmpty)
<a href={nameLink}>{nameHtml}</a>
else nameHtml
- }{
+ }
+ {
def tparamsToHtml(mbr: Entity): NodeSeq = mbr match {
case hk: HigherKinded =>
val tpss = hk.typeParams
@@ -579,8 +580,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case _ => NodeSeq.Empty
}
tparamsToHtml(mbr)
- }{
- if (isReduced) NodeSeq.Empty else {
+ }
+ { if (isReduced) NodeSeq.Empty else {
def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
def param0(vl: ValueParam): NodeSeq =
// notice the }{ in the next lines, they are necessary to avoid a undesired withspace in output
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 7a64fc9b5e..68a53e57a1 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -475,7 +475,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
case tt: TypeTree if (tt.tpe != null) =>
if (!(boundSyms exists (tt.tpe contains _))) mirrorCall("TypeTree", reifyType(tt.tpe))
else if (tt.original != null) reify(tt.original)
- else TypeTree()
+ else mirrorCall("TypeTree")
case global.emptyValDef =>
mirrorSelect("emptyValDef")
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index d252281002..1d9eb9c292 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -17,13 +17,16 @@ import annotation.tailrec
trait Contexts { self: Analyzer =>
import global._
- val NoContext = new Context {
- override def implicitss: List[List[ImplicitInfo]] = List()
- outer = this
+ object NoContext extends Context {
+ outer = this
+ enclClass = this
+ enclMethod = this
+
+ override def nextEnclosing(p: Context => Boolean): Context = this
+ override def enclosingContextChain: List[Context] = Nil
+ override def implicitss: List[List[ImplicitInfo]] = Nil
override def toString = "NoContext"
}
- NoContext.enclClass = NoContext
- NoContext.enclMethod = NoContext
private val startContext = {
NoContext.make(
@@ -337,7 +340,9 @@ trait Contexts { self: Analyzer =>
}
def nextEnclosing(p: Context => Boolean): Context =
- if (this == NoContext || p(this)) this else outer.nextEnclosing(p)
+ if (p(this)) this else outer.nextEnclosing(p)
+
+ def enclosingContextChain: List[Context] = this :: outer.enclosingContextChain
override def toString = "Context(%s@%s unit=%s scope=%s)".format(
owner.fullName, tree.shortClass, unit, scope.##
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b969e9629f..7671ccbed7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -19,6 +19,7 @@ import symtab.Flags._
import util.Statistics
import util.Statistics._
import scala.tools.util.StringOps.{ countAsString, countElementsAsString }
+import scala.tools.util.EditDistance.similarString
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -3457,12 +3458,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (treeInfo.isVariableOrGetter(qual1)) {
stopTimer(failedOpEqNanos, opeqStart)
convertToAssignment(fun, qual1, name, args, ex)
- } else {
+ }
+ else {
stopTimer(failedApplyNanos, appStart)
- if ((qual1.symbol ne null) && qual1.symbol.isValue)
- error(tree.pos, "reassignment to val")
- else
- reportTypeError(fun.pos, ex)
+ reportTypeError(fun.pos, ex)
setError(tree)
}
case _ =>
@@ -3754,7 +3753,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
defSym = EmptyPackageClass.tpe.nonPrivateMember(name)
defSym != NoSymbol
}
-
+ def startingIdentContext = (
+ // ignore current variable scope in patterns to enforce linearity
+ if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context
+ else context.outer
+ )
// A symbol qualifies if it exists and is not stale. Stale symbols
// are made to disappear here. In addition,
// if we are in a constructor of a pattern, we ignore all definitions
@@ -3770,13 +3773,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
- var cx = context
- if ((mode & (PATTERNmode | TYPEPATmode)) != 0) {
- // println("ignoring scope: "+name+" "+cx.scope+" "+cx.outer.scope)
- // ignore current variable scope in patterns to enforce linearity
- cx = cx.outer
- }
-
+ var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext) {
currentRun.compileSourceFor(context.asInstanceOf[analyzer.Context], name)
pre = cx.enclClass.prefix
@@ -3874,7 +3871,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (inaccessibleSym eq NoSymbol) {
// Avoiding some spurious error messages: see SI-2388.
if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) ()
- else error(tree.pos, "not found: "+decodeWithKind(name, context.owner))
+ else {
+ val similar = (
+ // name length check to limit unhelpful suggestions for e.g. "x" and "b1"
+ if (name.length > 2) {
+ val allowed = (
+ startingIdentContext.enclosingContextChain
+ flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols))
+ filter (sym => sym.isTerm == name.isTermName)
+ filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName)
+ )
+ val allowedStrings = (
+ allowed.map("" + _.name).distinct.sorted
+ filterNot (s => (s contains '$') || (s contains ' '))
+ )
+ similarString("" + name, allowedStrings)
+ }
+ else ""
+ )
+ error(tree.pos, "not found: "+decodeWithKind(name, context.owner) + similar)
+ }
}
else new AccessError(
tree, inaccessibleSym, context.enclClass.owner.thisType,
diff --git a/src/compiler/scala/tools/util/EditDistance.scala b/src/compiler/scala/tools/util/EditDistance.scala
new file mode 100644
index 0000000000..a8d7408532
--- /dev/null
+++ b/src/compiler/scala/tools/util/EditDistance.scala
@@ -0,0 +1,54 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package util
+
+object EditDistance {
+ def similarString(name: String, allowed: TraversableOnce[String]): String = {
+ val suggested = suggestions(name, allowed.toSeq, maxDistance = 1, maxSuggestions = 2)
+ if (suggested.isEmpty) ""
+ else suggested.mkString(" (similar: ", ", ", ")")
+ }
+
+ def suggestions(a: String, bs: Seq[String], maxDistance: Int, maxSuggestions: Int): Seq[String] = (
+ bs map (b => (b, distance(a, b)))
+ filter (_._2 <= maxDistance)
+ sortBy (_._2)
+ take (maxSuggestions)
+ map (_._1)
+ )
+
+ def distance(a: String, b: String): Int = levenshtein(a, b, transpositions = true)
+
+ def levenshtein(s: String, t: String, transpositions: Boolean): Int = {
+ val n = s.length
+ val m = t.length
+ if (n == 0) return m
+ if (m == 0) return n
+
+ val d = Array.ofDim[Int](n + 1, m + 1)
+ 0 to n foreach (x => d(x)(0) = x)
+ 0 to m foreach (x => d(0)(x) = x)
+
+ for (i <- 1 to n ; val s_i = s(i - 1) ; j <- 1 to m) {
+ val t_j = t(j - 1)
+ val cost = if (s_i == t_j) 0 else 1
+
+ val c1 = d(i - 1)(j) + 1
+ val c2 = d(i)(j - 1) + 1
+ val c3 = d(i - 1)(j - 1) + cost
+
+ d(i)(j) = c1 min c2 min c3
+
+ if (transpositions) {
+ if (i > 1 && j > 1 && s(i - 1) == t(j - 2) && s(i - 2) == t(j - 1))
+ d(i)(j) = d(i)(j) min (d(i - 2)(j - 2) + cost)
+ }
+ }
+
+ d(n)(m)
+ }
+}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 5cb06d42db..f4481b800e 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -9,7 +9,7 @@ trait CPSUtils {
import global._
import definitions._
- var cpsEnabled = false
+ var cpsEnabled = true
val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true"
def vprintln(x: =>Any): Unit = if (verbose) println(x)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
index 8a500d6c4d..eb18f03748 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
@@ -26,7 +26,6 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
override val runsBefore = List("uncurry")
}
-
val components = List[PluginComponent](anfPhase, cpsPhase)
val checker = new CPSAnnotationChecker {
@@ -43,19 +42,17 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
}
// TODO: require -enabled command-line flag
-
override def processOptions(options: List[String], error: String => Unit) = {
- var enabled = false
- for (option <- options) {
- if (option == "enable") {
- enabled = true
- } else {
- error("Option not understood: "+option)
- }
+ var enabled = true
+ options foreach {
+ case "enable" => enabled = true
+ case "disable" => enabled = false
+ case option => error("Option not understood: "+option)
}
setEnabled(enabled)
}
- override val optionsHelp: Option[String] =
- Some(" -P:continuations:enable Enable continuations")
+ override val optionsHelp: Option[String] = {
+ Some(" -P:continuations:disable Disable continuations plugin")
+ }
}
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 07e758013c..c967a48abc 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -8,7 +8,7 @@
package scala
-import scala.collection.{ mutable, immutable, generic, SetLike, AbstractSet }
+import scala.collection.{ mutable, immutable, generic, SortedSetLike, AbstractSet }
import java.lang.reflect.{ Modifier, Method => JMethod, Field => JField }
import scala.reflect.NameTransformer._
import java.util.regex.Pattern
@@ -53,10 +53,14 @@ import java.util.regex.Pattern
* @author Matthias Zenger
*/
@SerialVersionUID(8476000850333817230L)
-abstract class Enumeration(initial: Int, names: String*) extends Serializable {
+abstract class Enumeration(initial: Int,
+ @deprecated("Names should be specified individually or discovered via reflection", "2.10")
+ names: String*) extends Serializable {
thisenum =>
def this() = this(0)
+
+ @deprecated("Names should be specified individually or discovered via reflection", "2.10")
def this(names: String*) = this(0, names: _*)
/* Note that `readResolve` cannot be private, since otherwise
@@ -86,7 +90,7 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
*/
def values: ValueSet = {
if (!vsetDefined) {
- vset = new ValueSet(immutable.SortedSet.empty[Int] ++ (vmap.values map (_.id)))
+ vset = (ValueSet.newBuilder ++= vmap.values).result()
vsetDefined = true
}
vset
@@ -104,6 +108,10 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
* enumeration. */
private var topId = initial
+ /** The lowest integer amongst those used to identify values in this
+ * enumeration, but no higher than 0. */
+ private var bottomId = if(initial < 0) initial else 0
+
/** The highest integer amongst those used to identify values in this
* enumeration. */
final def maxId = topId
@@ -200,6 +208,9 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
case _ => false
}
override def hashCode: Int = id.##
+
+ /** Create a ValueSet which contains this value and another one */
+ def + (v: Value) = ValueSet(this, v)
}
/** A class implementing the [[scala.Enumeration.Value]] type. This class
@@ -217,6 +228,7 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
vsetDefined = false
nextId = i + 1
if (nextId > topId) topId = nextId
+ if (i < bottomId) bottomId = i
def id = i
override def toString() =
if (name != null) name
@@ -230,34 +242,56 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
}
}
+ /** An ordering by id for values of this set */
+ object ValueOrdering extends Ordering[Value] {
+ def compare(x: Value, y: Value): Int = x.id - y.id
+ }
+
/** A class for sets of values.
* Iterating through this set will yield values in increasing order of their ids.
*
- * @param ids The set of ids of values, organized as a `SortedSet`.
+ * @param nnIds The set of ids of values (adjusted so that the lowest value does
+ * not fall below zero), organized as a `BitSet`.
*/
- class ValueSet private[Enumeration] (val ids: immutable.SortedSet[Int])
+ class ValueSet private[ValueSet] (private[this] var nnIds: immutable.BitSet)
extends AbstractSet[Value]
- with Set[Value]
- with SetLike[Value, ValueSet] {
+ with immutable.SortedSet[Value]
+ with SortedSetLike[Value, ValueSet]
+ with Serializable {
+
+ implicit def ordering: Ordering[Value] = ValueOrdering
+ def rangeImpl(from: Option[Value], until: Option[Value]): ValueSet =
+ new ValueSet(nnIds.rangeImpl(from.map(_.id - bottomId), until.map(_.id - bottomId)))
override def empty = ValueSet.empty
- def contains(v: Value) = ids contains (v.id)
- def + (value: Value) = new ValueSet(ids + value.id)
- def - (value: Value) = new ValueSet(ids - value.id)
- def iterator = ids.iterator map thisenum.apply
+ def contains(v: Value) = nnIds contains (v.id - bottomId)
+ def + (value: Value) = new ValueSet(nnIds + (value.id - bottomId))
+ def - (value: Value) = new ValueSet(nnIds - (value.id - bottomId))
+ def iterator = nnIds.iterator map (id => thisenum.apply(id + bottomId))
override def stringPrefix = thisenum + ".ValueSet"
+ /** Creates a bit mask for the zero-adjusted ids in this set as a
+ * new array of longs */
+ def toBitMask: Array[Long] = nnIds.toBitMask
}
-
+
/** A factory object for value sets */
object ValueSet {
import generic.CanBuildFrom
/** The empty value set */
- val empty = new ValueSet(immutable.SortedSet.empty)
+ val empty = new ValueSet(immutable.BitSet.empty)
/** A value set consisting of given elements */
- def apply(elems: Value*): ValueSet = empty ++ elems
+ def apply(elems: Value*): ValueSet = (newBuilder ++= elems).result()
+ /** A value set containing all the values for the zero-adjusted ids
+ * corresponding to the bits in an array */
+ def fromBitMask(elems: Array[Long]): ValueSet = new ValueSet(immutable.BitSet.fromBitMask(elems))
/** A builder object for value sets */
- def newBuilder: mutable.Builder[Value, ValueSet] = new mutable.SetBuilder(empty)
+ def newBuilder: mutable.Builder[Value, ValueSet] = new mutable.Builder[Value, ValueSet] {
+ private[this] val b = new mutable.BitSet
+ def += (x: Value) = { b += (x.id - bottomId); this }
+ def clear() = b.clear
+ def result() = new ValueSet(b.toImmutable)
+ }
/** The implicit builder for value sets */
implicit def canBuildFrom: CanBuildFrom[ValueSet, Value, ValueSet] =
new CanBuildFrom[ValueSet, Value, ValueSet] {
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index b3dd4764a9..63e9543711 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -276,6 +276,8 @@ trait GenSeqLike[+A, +Repr] extends GenIterableLike[A, Repr] with Equals with Pa
/** A copy of the $coll with an element prepended.
*
* Note that :-ending operators are right associative (see example).
+ * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side.
+ *
* Also, the original $coll is not modified, so you will want to capture the result.
*
* Example:
@@ -304,6 +306,8 @@ trait GenSeqLike[+A, +Repr] extends GenIterableLike[A, Repr] with Equals with Pa
/** A copy of this $coll with an element appended.
*
+ * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side.
+ *
* $willNotTerminateInf
* @param elem the appended element
* @tparam B the element type of the returned $coll.
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 6fa05bd85b..4f0fec1de3 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -159,8 +159,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** As with `++`, returns a new collection containing the elements from the left operand followed by the
* elements from the right operand.
+ *
* It differs from `++` in that the right operand determines the type of
* the resulting collection rather than the left one.
+ * Mnemonic: the COLon is on the side of the new COLlection type.
*
* Example:
* {{{
@@ -195,8 +197,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** As with `++`, returns a new collection containing the elements from the
* left operand followed by the elements from the right operand.
+ *
* It differs from `++` in that the right operand determines the type of
* the resulting collection rather than the left one.
+ * Mnemonic: the COLon is on the side of the new COLlection type.
*
* Example:
* {{{
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 47ce2f0341..3736096f36 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -211,6 +211,13 @@ extends collection.AbstractSeq[Int]
final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0)
+ final override def sum[B >: Int](implicit num: Numeric[B]): Int = {
+ val len = length
+ if (len == 0) 0
+ else if (len == 1) head
+ else (len.toLong * (head + last) / 2).toInt
+ }
+
override def toIterable = this
override def toSeq = this
diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala
index 8948722340..0417461f85 100644
--- a/src/library/scala/math/package.scala
+++ b/src/library/scala/math/package.scala
@@ -127,15 +127,9 @@ package object math {
else if (x > 0) 1.0f
else x // NaN
- def signum(x: Long): Long =
- if (x == 0l) 0l
- else if (x < 0) -1l
- else 1l
-
- def signum(x: Int): Int =
- if (x == 0) 0
- else if (x < 0) -1
- else 1
+ def signum(x: Long): Long = java.lang.Long.signum(x)
+
+ def signum(x: Int): Int = java.lang.Integer.signum(x)
// -----------------------------------------------------------------------
// root functions
diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala
index e7ea9f598b..751539243b 100644
--- a/src/library/scala/util/parsing/combinator/Parsers.scala
+++ b/src/library/scala/util/parsing/combinator/Parsers.scala
@@ -108,6 +108,8 @@ trait Parsers {
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
+ def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T]
+
def append[U >: T](a: => ParseResult[U]): ParseResult[U]
def isEmpty = !successful
@@ -137,6 +139,10 @@ trait Parsers {
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
= f(result)(next)
+ def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T] =
+ if (p(result)) this
+ else Failure(error(result), position)
+
def append[U >: T](a: => ParseResult[U]): ParseResult[U] = this
def get: T = result
@@ -161,6 +167,8 @@ trait Parsers {
def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U]
= this
+ def filterWithError(p: Nothing => Boolean, error: Nothing => String, position: Input): ParseResult[Nothing] = this
+
def get: Nothing = sys.error("No result when parsing failed")
}
/** An extractor so `NoSuccess(msg, next)` can be used in matches. */
@@ -224,6 +232,12 @@ trait Parsers {
def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
= Parser{ in => this(in) map(f)}
+ def filter(p: T => Boolean): Parser[T]
+ = withFilter(p)
+
+ def withFilter(p: T => Boolean): Parser[T]
+ = Parser{ in => this(in) filterWithError(p, "Input doesn't match filter: "+_, in)}
+
// no filter yet, dealing with zero is tricky!
@migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.")
@@ -443,6 +457,62 @@ trait Parsers {
* @return opt(this)
*/
def ? = opt(this)
+
+ /** Changes the failure message produced by a parser.
+ *
+ * This doesn't change the behavior of a parser on neither
+ * success nor error, just on failure. The semantics are
+ * slightly different than those obtained by doing `| failure(msg)`,
+ * in that the message produced by this method will always
+ * replace the message produced, which is not guaranteed
+ * by that idiom.
+ *
+ * For example, parser `p` below will always produce the
+ * designated failure message, while `q` will not produce
+ * it if `sign` is parsed but `number` is not.
+ *
+ * {{{
+ * def p = sign.? ~ number withFailureMessage "Number expected!"
+ * def q = sign.? ~ number | failure("Number expected!")
+ * }}}
+ *
+ * @param msg The message that will replace the default failure message.
+ * @return A parser with the same properties and different failure message.
+ */
+ def withFailureMessage(msg: String) = Parser{ in =>
+ this(in) match {
+ case Failure(_, next) => Failure(msg, next)
+ case other => other
+ }
+ }
+
+ /** Changes the error message produced by a parser.
+ *
+ * This doesn't change the behavior of a parser on neither
+ * success nor failure, just on error. The semantics are
+ * slightly different than those obtained by doing `| error(msg)`,
+ * in that the message produced by this method will always
+ * replace the message produced, which is not guaranteed
+ * by that idiom.
+ *
+ * For example, parser `p` below will always produce the
+ * designated error message, while `q` will not produce
+ * it if `sign` is parsed but `number` is not.
+ *
+ * {{{
+ * def p = sign.? ~ number withErrorMessage "Number expected!"
+ * def q = sign.? ~ number | error("Number expected!")
+ * }}}
+ *
+ * @param msg The message that will replace the default error message.
+ * @return A parser with the same properties and different error message.
+ */
+ def withErrorMessage(msg: String) = Parser{ in =>
+ this(in) match {
+ case Error(_, next) => Error(msg, next)
+ case other => other
+ }
+ }
}
/** Wrap a parser so that its failures become errors (the `|` combinator
diff --git a/test/files/jvm/signum.scala b/test/files/jvm/signum.scala
new file mode 100644
index 0000000000..feb28d3e43
--- /dev/null
+++ b/test/files/jvm/signum.scala
@@ -0,0 +1,15 @@
+object Test {
+ def main(args: Array[String]) {
+ assert(math.signum(Long.MaxValue) == 1L)
+ assert(math.signum(1L) == 1L)
+ assert(math.signum(0L) == 0L)
+ assert(math.signum(-1L) == -1L)
+ assert(math.signum(Long.MinValue) == -1L)
+
+ assert(math.signum(Int.MaxValue) == 1)
+ assert(math.signum(1) == 1)
+ assert(math.signum(0) == 0)
+ assert(math.signum(-1) == -1)
+ assert(math.signum(Int.MinValue) == -1)
+ }
+}
diff --git a/test/files/neg/nopredefs.check b/test/files/neg/nopredefs.check
index 0a0ab34482..e6c1af78a0 100644
--- a/test/files/neg/nopredefs.check
+++ b/test/files/neg/nopredefs.check
@@ -1,4 +1,4 @@
-nopredefs.scala:5: error: not found: value Set
+nopredefs.scala:5: error: not found: value Set (similar: Seq)
val y = Set(3)
^
one error found
diff --git a/test/files/neg/reassignment.check b/test/files/neg/reassignment.check
new file mode 100644
index 0000000000..f0effd1459
--- /dev/null
+++ b/test/files/neg/reassignment.check
@@ -0,0 +1,13 @@
+reassignment.scala:2: error: not found: value x
+ x = 5
+ ^
+reassignment.scala:3: error: not found: value y
+ y := 45
+ ^
+reassignment.scala:4: error: not found: value y
+ y += 45
+ ^
+reassignment.scala:6: error: reassignment to val
+ z = 51
+ ^
+four errors found
diff --git a/test/files/neg/reassignment.scala b/test/files/neg/reassignment.scala
new file mode 100644
index 0000000000..e31eefbf3f
--- /dev/null
+++ b/test/files/neg/reassignment.scala
@@ -0,0 +1,7 @@
+class A {
+ x = 5
+ y := 45
+ y += 45
+ val z = 50
+ z = 51
+} \ No newline at end of file
diff --git a/test/files/neg/suggest-similar.check b/test/files/neg/suggest-similar.check
new file mode 100644
index 0000000000..0a858aaf2e
--- /dev/null
+++ b/test/files/neg/suggest-similar.check
@@ -0,0 +1,10 @@
+suggest-similar.scala:8: error: not found: value flippitx (similar: flippity)
+ flippitx = 123
+ ^
+suggest-similar.scala:9: error: not found: value identiyt (similar: identity)
+ Nil map identiyt
+ ^
+suggest-similar.scala:10: error: not found: type Bingus (similar: Dingus)
+ new Bingus
+ ^
+three errors found
diff --git a/test/files/neg/suggest-similar.scala b/test/files/neg/suggest-similar.scala
new file mode 100644
index 0000000000..ff327478fe
--- /dev/null
+++ b/test/files/neg/suggest-similar.scala
@@ -0,0 +1,11 @@
+class Dingus
+object Dingus {
+ var flippity = 1
+}
+import Dingus._
+
+class A {
+ flippitx = 123
+ Nil map identiyt
+ new Bingus
+}
diff --git a/test/files/neg/t0903.check b/test/files/neg/t0903.check
index db4cd94d2c..2dd05cd3ee 100644
--- a/test/files/neg/t0903.check
+++ b/test/files/neg/t0903.check
@@ -1,4 +1,4 @@
-t0903.scala:3: error: reassignment to val
+t0903.scala:3: error: value += is not a member of Int
x += 1
^
t0903.scala:4: error: reassignment to val
diff --git a/test/files/neg/t2870.check b/test/files/neg/t2870.check
index 6577577d3f..72bc0d98a1 100644
--- a/test/files/neg/t2870.check
+++ b/test/files/neg/t2870.check
@@ -1,4 +1,4 @@
-t2870.scala:1: error: not found: type Jar
+t2870.scala:1: error: not found: type Jar (similar: Jars)
class Jars(jar: Jar)
^
t2870.scala:6: error: illegal cyclic reference involving value <import>
diff --git a/test/files/pos/t4758.scala b/test/files/pos/t4758.scala
new file mode 100644
index 0000000000..627dfd7a23
--- /dev/null
+++ b/test/files/pos/t4758.scala
@@ -0,0 +1,17 @@
+// /scala/trac/4758/a.scala
+// Fri Dec 2 13:41:54 PST 2011
+
+package bar {
+ // works
+ trait M[F[_]]
+ class S[X[_] <: M[X], A](val x:X[A])
+ object S {
+ def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = new S[X, A](x)
+ def unapply[X[_] <: M[X], A](p: S[X, A]) = Some(p.x)
+ }
+}
+package foo {
+ // seemingly equivalent, doesn't work
+ trait M[F[_]]
+ case class S[X[_] <: M[X], A](x: X[A])
+}
diff --git a/test/files/pos/t5084.scala b/test/files/pos/t5084.scala
new file mode 100644
index 0000000000..17d0a68adf
--- /dev/null
+++ b/test/files/pos/t5084.scala
@@ -0,0 +1,5 @@
+case class Search(tpe: Search.Value)
+
+object Search {
+ type Value = String
+}
diff --git a/test/files/run/enums.check b/test/files/run/enums.check
index f53aba8794..93eadae6e3 100644
--- a/test/files/run/enums.check
+++ b/test/files/run/enums.check
@@ -3,3 +3,13 @@ test Test2 was successful
test Test3 was successful
test Test4 was successful
+D1.ValueSet(North, East)
+D2.ValueSet(North, East)
+D1.ValueSet(North, East, West)
+D2.ValueSet(North, East, West)
+List(101)
+List(101)
+D1.ValueSet(North, East)
+D2.ValueSet(North, East)
+WeekDays.ValueSet(Tue, Wed, Thu, Fri)
+
diff --git a/test/files/run/enums.scala b/test/files/run/enums.scala
index 6dda8cbc6e..9cdeed2691 100644
--- a/test/files/run/enums.scala
+++ b/test/files/run/enums.scala
@@ -65,6 +65,58 @@ object Test4 {
}
}
+object Test5 {
+
+ object D1 extends Enumeration(0) {
+ val North, South, East, West = Value;
+ }
+
+ object D2 extends Enumeration(-2) {
+ val North, South, East, West = Value;
+ }
+
+ object WeekDays extends Enumeration {
+ val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ }
+
+ def run {
+ val s1 = D1.ValueSet(D1.North, D1.East)
+ val s2 = D2.North + D2.East
+ println(s1)
+ println(s2)
+ println(s1 + D1.West)
+ println(s2 + D2.West)
+ println(s1.toBitMask.map(_.toBinaryString).toList)
+ println(s2.toBitMask.map(_.toBinaryString).toList)
+ println(D1.ValueSet.fromBitMask(s1.toBitMask))
+ println(D2.ValueSet.fromBitMask(s2.toBitMask))
+ println(WeekDays.values.range(WeekDays.Tue, WeekDays.Sat))
+ }
+}
+
+object SerializationTest {
+ object Types extends Enumeration { val X, Y = Value }
+ class A extends java.io.Serializable { val types = Types.values }
+ class B extends java.io.Serializable { val types = Set(Types.X, Types.Y) }
+
+ def serialize(obj: AnyRef) = {
+ val baos = new java.io.ByteArrayOutputStream()
+ val oos = new java.io.ObjectOutputStream(baos)
+ oos.writeObject(obj)
+ oos.close()
+ val bais = new java.io.ByteArrayInputStream(baos.toByteArray)
+ val ois = new java.io.ObjectInputStream(bais)
+ val prime = ois.readObject()
+ ois.close()
+ prime
+ }
+
+ def run {
+ serialize(new B())
+ serialize(new A())
+ }
+}
+
//############################################################################
// Test code
@@ -94,6 +146,9 @@ object Test {
check_success("Test3", Test3.run, 1);
check_success("Test4", Test4.run, 0);
Console.println;
+ Test5.run;
+ Console.println;
+ SerializationTest.run;
}
}
diff --git a/test/files/run/parserFilter.check b/test/files/run/parserFilter.check
new file mode 100644
index 0000000000..be04454426
--- /dev/null
+++ b/test/files/run/parserFilter.check
@@ -0,0 +1,9 @@
+[1.3] failure: Input doesn't match filter: false
+
+if false
+ ^
+[1.1] failure: Input doesn't match filter: not
+
+not true
+^
+[1.8] parsed: (if~true)
diff --git a/test/files/run/parserFilter.scala b/test/files/run/parserFilter.scala
new file mode 100644
index 0000000000..d007d441f4
--- /dev/null
+++ b/test/files/run/parserFilter.scala
@@ -0,0 +1,15 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ val keywords = Set("if", "false")
+ def word: Parser[String] = "\\w+".r
+
+ def keyword: Parser[String] = word filter (keywords.contains)
+ def ident: Parser[String] = word filter(!keywords.contains(_))
+
+ def test = keyword ~ ident
+
+ def main(args: Array[String]) {
+ println(parseAll(test, "if false"))
+ println(parseAll(test, "not true"))
+ println(parseAll(test, "if true"))
+ }
+}
diff --git a/test/files/run/parserForFilter.check b/test/files/run/parserForFilter.check
new file mode 100644
index 0000000000..a53c147719
--- /dev/null
+++ b/test/files/run/parserForFilter.check
@@ -0,0 +1 @@
+[1.13] parsed: (second,first)
diff --git a/test/files/run/parserForFilter.scala b/test/files/run/parserForFilter.scala
new file mode 100644
index 0000000000..1bc44f8033
--- /dev/null
+++ b/test/files/run/parserForFilter.scala
@@ -0,0 +1,12 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ def word: Parser[String] = "\\w+".r
+
+ def twoWords = for {
+ (a ~ b) <- word ~ word
+ } yield (b, a)
+
+ def main(args: Array[String]) {
+ println(parseAll(twoWords, "first second"))
+ }
+}
+
diff --git a/test/files/run/parserNoSuccessMessage.check b/test/files/run/parserNoSuccessMessage.check
new file mode 100644
index 0000000000..fe00d2fd3a
--- /dev/null
+++ b/test/files/run/parserNoSuccessMessage.check
@@ -0,0 +1,20 @@
+[1.2] failure: string matching regex `\d+' expected but `x' found
+
+-x
+ ^
+[1.1] failure: string matching regex `\d+' expected but `x' found
+
+x
+^
+[1.3] parsed: (Some(-)~5)
+[1.2] parsed: (None~5)
+[1.2] error: Number expected!
+
+-x
+ ^
+[1.1] error: Number expected!
+
+x
+^
+[1.3] parsed: (Some(-)~5)
+[1.2] parsed: (None~5)
diff --git a/test/files/run/parserNoSuccessMessage.scala b/test/files/run/parserNoSuccessMessage.scala
new file mode 100644
index 0000000000..93aa252db0
--- /dev/null
+++ b/test/files/run/parserNoSuccessMessage.scala
@@ -0,0 +1,19 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ def sign = "-"
+ def number = "\\d+".r
+ def p = sign.? ~ number withErrorMessage "Number expected!"
+ def q = sign.? ~! number withErrorMessage "Number expected!"
+
+ def main(args: Array[String]) {
+ println(parseAll(p, "-x"))
+ println(parseAll(p, "x"))
+ println(parseAll(p, "-5"))
+ println(parseAll(p, "5"))
+ println(parseAll(q, "-x"))
+ println(parseAll(q, "x"))
+ println(parseAll(q, "-5"))
+ println(parseAll(q, "5"))
+ }
+}
+
+
diff --git a/test/files/run/reify_anonymous.check b/test/files/run/reify_anonymous.check
new file mode 100644
index 0000000000..b8626c4cff
--- /dev/null
+++ b/test/files/run/reify_anonymous.check
@@ -0,0 +1 @@
+4
diff --git a/test/files/run/reify_anonymous.scala b/test/files/run/reify_anonymous.scala
new file mode 100644
index 0000000000..1e7f3fe856
--- /dev/null
+++ b/test/files/run/reify_anonymous.scala
@@ -0,0 +1,14 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ println(new {def x = 2; def y = x * x}.y)
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/files/run/reify_generic.check b/test/files/run/reify_generic.check
new file mode 100644
index 0000000000..b8626c4cff
--- /dev/null
+++ b/test/files/run/reify_generic.check
@@ -0,0 +1 @@
+4
diff --git a/test/files/run/reify_generic.scala b/test/files/run/reify_generic.scala
new file mode 100644
index 0000000000..aef038b2d8
--- /dev/null
+++ b/test/files/run/reify_generic.scala
@@ -0,0 +1,15 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ val product = List(1, 2, 3).head * List[Any](4, 2, 0).head.asInstanceOf[Int]
+ println(product)
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/files/run/reify_inheritance.check b/test/files/run/reify_inheritance.check
new file mode 100644
index 0000000000..25bf17fc5a
--- /dev/null
+++ b/test/files/run/reify_inheritance.check
@@ -0,0 +1 @@
+18 \ No newline at end of file
diff --git a/test/files/run/reify_inheritance.scala b/test/files/run/reify_inheritance.scala
new file mode 100644
index 0000000000..2a1b5f764f
--- /dev/null
+++ b/test/files/run/reify_inheritance.scala
@@ -0,0 +1,23 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ class C {
+ def x = 2
+ def y = x * x
+ }
+
+ class D extends C {
+ override def x = 3
+ }
+
+ println(new D().y * new C().x)
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/files/run/reify_printf.check b/test/files/run/reify_printf.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/reify_printf.check
diff --git a/test/files/run/reify_printf.scala b/test/files/run/reify_printf.scala
new file mode 100644
index 0000000000..30901b98c2
--- /dev/null
+++ b/test/files/run/reify_printf.scala
@@ -0,0 +1,75 @@
+import java.io.{ ByteArrayOutputStream, PrintStream }
+import scala.reflect.Code
+import scala.reflect.mirror._
+import scala.reflect.api._
+import scala.reflect.api.Trees
+import scala.reflect.internal.Types
+import reflect.runtime.Mirror.ToolBox
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import scala.util.matching.Regex
+
+object Test extends App {
+ val tree = tree_printf(Code.lift("hello %s").tree, Code.lift("world").tree)
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter, args mkString " ")
+ val ttree = toolbox.typeCheck(tree)
+
+ val output = new ByteArrayOutputStream()
+ Console.setOut(new PrintStream(output))
+ val evaluated = toolbox.runExpr(ttree)
+
+ assert(output.toString() == "hello world", output.toString() +" == hello world")
+
+ /*
+ macro def printf(format: String, params: Any*) : String = tree_printf(format: Tree, (params: Seq[Tree]): _*)
+ */
+
+ var i = 0
+ def gensym(name: String) = { i += 1; newTermName(name + i) }
+
+ def createTempValDef( value : Tree, tpe : Type ) : (Option[Tree],Tree) = {
+ val local = gensym("temp")
+ (
+ Some(
+ ValDef(
+ Modifiers()
+ , local
+ , TypeTree().setType(tpe)
+ , value
+ )
+ )
+ , Ident(local)
+ )
+ }
+
+ def tree_printf(format: Tree, params: Tree*) = {
+ val Literal(Constant(s_format: String)) = format
+ val paramsStack = scala.collection.mutable.Stack(params: _*)
+ val parsed = s_format.split("(?<=%[\\w%])|(?=%[\\w%])") map {
+ case "%d" => createTempValDef( paramsStack.pop, classToType(classOf[Int]) )
+ case "%s" => createTempValDef( paramsStack.pop, classToType(classOf[String]) )
+ case "%%" => {
+ (None:Option[Tree], Literal(Constant("%")))
+ }
+ case part => {
+ (None:Option[Tree], Literal(Constant(part)))
+ }
+ }
+
+ val evals = for ((Some(eval), _) <- parsed if eval != None) yield (eval: Tree)
+ val prints = for ((_, ref) <- parsed) yield
+ Apply(
+ Select(
+ Select(
+ Ident( newTermName("scala") )
+ , newTermName("Predef")
+ )
+ , newTermName("print")
+ )
+ , List(ref)
+ ): Tree
+ Block((evals ++ prints).toList, Literal(Constant(())))
+ }
+}
diff --git a/test/files/run/t4658.check b/test/files/run/t4658.check
new file mode 100644
index 0000000000..743b0faee3
--- /dev/null
+++ b/test/files/run/t4658.check
@@ -0,0 +1,80 @@
+Ranges:
+1073741824
+1073741824
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+IntRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+LongRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+BigIntRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
diff --git a/test/files/run/t4658.scala b/test/files/run/t4658.scala
new file mode 100644
index 0000000000..e1799fae9b
--- /dev/null
+++ b/test/files/run/t4658.scala
@@ -0,0 +1,41 @@
+import scala.collection.immutable.NumericRange
+//#4658
+object Test {
+
+ case class R(start: Int, end: Int, step: Int = 1, inclusive: Boolean = true)
+
+ val rangeData = Array(
+ R(1, Int.MaxValue), R(-Int.MaxValue, -1), R(0, 0), R(0,0, inclusive = false), R(1,10),
+ R(1,10,2), R(1,10,11), R(-10, -5), R(-10, 0), R(-10, 10), R(-10, -5, 2), R(-10, 0, 2), R(-10, 10, 2),
+ R(-10, -5, inclusive = false), R(-10, 0, inclusive = false), R(-10, 10, inclusive = false),
+ R(-10, -5, 2, inclusive = false), R(-10, 0, 2, inclusive = false), R(-10, 10, 2, inclusive = false)
+ )
+
+ def ranges = rangeData.map(r => if (r.inclusive) r.start to r.end by r.step else r.start until r.end by r.step)
+
+ def numericIntRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(r.start, r.end, r.step) else NumericRange(r.start, r.end, r.step))
+
+ def numericLongRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(r.start.toLong, r.end, r.step) else NumericRange(r.start.toLong, r.end, r.step))
+
+ def numericBigIntRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(BigInt(r.start), BigInt(r.end), BigInt(r.step)) else NumericRange(BigInt(r.start), BigInt(r.end), BigInt(r.step)))
+
+ def main(args: Array[String]) {
+ // We drop the first two tests for all ranges which don't have a decent sum implementation,
+ // because it is just too slow.
+ println("Ranges:")
+ ranges.foreach{range => println(range.sum)}
+ println("IntRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericIntRanges.drop(2).foreach{range => println(range.sum)}
+ println("LongRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericLongRanges.drop(2).foreach{range => println(range.sum)}
+ println("BigIntRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericBigIntRanges.drop(2).foreach{range => println(range.sum)}
+ }
+
+} \ No newline at end of file
diff --git a/test/files/run/t5230.check b/test/files/run/t5230.check
new file mode 100644
index 0000000000..5db6ec9b38
--- /dev/null
+++ b/test/files/run/t5230.check
@@ -0,0 +1,2 @@
+2
+evaluated = null
diff --git a/test/pending/run/t5230.scala b/test/files/run/t5230.scala
index 5aab8f9290..5aab8f9290 100644
--- a/test/pending/run/t5230.scala
+++ b/test/files/run/t5230.scala
diff --git a/test/pending/run/reify_csv.check b/test/pending/run/reify_csv.check
new file mode 100644
index 0000000000..b56f4bb50b
--- /dev/null
+++ b/test/pending/run/reify_csv.check
@@ -0,0 +1,10 @@
+List(phase name, id, description)
+record(parser,1,parse source into ASTs, perform simple desugaring)
+record(namer,2,resolve names, attach symbols to named trees)
+record(packageobjects,3,load package objects)
+record(typer,4,the meat and potatoes: type the trees)
+record(superaccessors,5,add super accessors in traits and nested classes)
+record(pickler,6,serialize symbol tables)
+record(refchecks,7,reference/override checking, translate nested objects)
+record(selectiveanf,8,)
+record(liftcode,9,reify trees)
diff --git a/test/pending/run/reify_csv.scala b/test/pending/run/reify_csv.scala
new file mode 100644
index 0000000000..a05a3b55d4
--- /dev/null
+++ b/test/pending/run/reify_csv.scala
@@ -0,0 +1,42 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val csv = """
+ | phase name; id; description
+ | parser; 1; parse source into ASTs, perform simple desugaring
+ | namer; 2; resolve names, attach symbols to named trees
+ |packageobjects; 3; load package objects
+ | typer; 4; the meat and potatoes: type the trees
+ |superaccessors; 5; add super accessors in traits and nested classes
+ | pickler; 6; serialize symbol tables
+ | refchecks; 7; reference/override checking, translate nested objects
+ | selectiveanf; 8;
+ | liftcode; 9; reify trees""".stripMargin.split("\n").map{_.trim()}.drop(1).toList
+
+ val fields = csv.head.split(";").map{_.trim()}.toList
+ println(fields)
+
+ val code = scala.reflect.Code.lift({
+ object Csv {
+ case class record(`phase name`: String, id: String, description: String)
+
+ object record {
+ def parse(lines: List[String]) = {
+ lines drop(1) map { line => line.split(";", -1).toList match {
+ case phase$whitespace$name :: id :: description :: _ => record(phase$whitespace$name.trim(), id.trim(), description.trim())
+ case _ => throw new Exception("format error")
+ }}
+ }
+ }
+ }
+
+ Csv.record.parse(csv) foreach println
+ })
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/pending/run/t5224.check b/test/pending/run/t5224.check
new file mode 100644
index 0000000000..2b920773c0
--- /dev/null
+++ b/test/pending/run/t5224.check
@@ -0,0 +1,9 @@
+{
+ @serializable class C extends Object with ScalaObject {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+} \ No newline at end of file
diff --git a/test/pending/run/t5224.scala b/test/pending/run/t5224.scala
new file mode 100644
index 0000000000..865ce4bfe9
--- /dev/null
+++ b/test/pending/run/t5224.scala
@@ -0,0 +1,8 @@
+import scala.reflect._
+import scala.reflect.api._
+
+object Test extends App {
+ println(scala.reflect.Code.lift{
+ @serializable class C
+ }.tree.toString)
+} \ No newline at end of file
diff --git a/test/pending/run/t5225_1.check b/test/pending/run/t5225_1.check
new file mode 100644
index 0000000000..b29cd9c365
--- /dev/null
+++ b/test/pending/run/t5225_1.check
@@ -0,0 +1,4 @@
+{
+ @transient @volatile var x: Int = 2;
+ ()
+} \ No newline at end of file
diff --git a/test/pending/run/t5225_1.scala b/test/pending/run/t5225_1.scala
new file mode 100644
index 0000000000..454502e810
--- /dev/null
+++ b/test/pending/run/t5225_1.scala
@@ -0,0 +1,8 @@
+import scala.reflect._
+import scala.reflect.api._
+
+object Test extends App {
+ println(scala.reflect.Code.lift{
+ @transient @volatile var x = 2
+ }.tree.toString)
+} \ No newline at end of file
diff --git a/test/pending/run/t5225_2.check b/test/pending/run/t5225_2.check
new file mode 100644
index 0000000000..88972fd27f
--- /dev/null
+++ b/test/pending/run/t5225_2.check
@@ -0,0 +1,4 @@
+{
+ def foo(@cloneable x: Int): String = "";
+ ()
+}
diff --git a/test/pending/run/t5225_2.scala b/test/pending/run/t5225_2.scala
new file mode 100644
index 0000000000..82bad0f353
--- /dev/null
+++ b/test/pending/run/t5225_2.scala
@@ -0,0 +1,8 @@
+import scala.reflect._
+import scala.reflect.api._
+
+object Test extends App {
+ println(scala.reflect.Code.lift{
+ def foo(@cloneable x: Int) = ""
+ }.tree.toString)
+} \ No newline at end of file
diff --git a/test/pending/run/t5229_1.check b/test/pending/run/t5229_1.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/pending/run/t5229_1.check
diff --git a/test/pending/run/t5229_1.scala b/test/pending/run/t5229_1.scala
new file mode 100644
index 0000000000..1d7bf0590b
--- /dev/null
+++ b/test/pending/run/t5229_1.scala
@@ -0,0 +1,14 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ object C
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/pending/run/t5229_2.check b/test/pending/run/t5229_2.check
new file mode 100644
index 0000000000..5db6ec9b38
--- /dev/null
+++ b/test/pending/run/t5229_2.check
@@ -0,0 +1,2 @@
+2
+evaluated = null
diff --git a/test/pending/run/t5229_2.scala b/test/pending/run/t5229_2.scala
new file mode 100644
index 0000000000..67be7328a6
--- /dev/null
+++ b/test/pending/run/t5229_2.scala
@@ -0,0 +1,19 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ object C {
+ val x = 2
+ }
+
+ println(C.x)
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ val evaluated = toolbox.runExpr(ttree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/pending/run/t5230.check b/test/pending/run/t5230.check
deleted file mode 100644
index 5ef4ff4d04..0000000000
--- a/test/pending/run/t5230.check
+++ /dev/null
@@ -1 +0,0 @@
-evaluated = 2
diff --git a/test/pending/run/t5266_1.check b/test/pending/run/t5266_1.check
new file mode 100644
index 0000000000..3feac16a0b
--- /dev/null
+++ b/test/pending/run/t5266_1.check
@@ -0,0 +1,2 @@
+2
+evaluated = null \ No newline at end of file
diff --git a/test/pending/run/t5266_1.scala b/test/pending/run/t5266_1.scala
new file mode 100644
index 0000000000..06a81a04ea
--- /dev/null
+++ b/test/pending/run/t5266_1.scala
@@ -0,0 +1,23 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ def x = 2
+ println(x)
+ };
+
+ val settings = new Settings
+ settings.debug.value = true
+ settings.Xshowtrees.value = true
+ settings.Xprint.value = List("typer")
+ settings.printtypes.value = true
+ settings.Ytyperdebug.value = true
+
+ val reporter = new ConsoleReporter(settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ val evaluated = toolbox.runExpr(ttree)
+ println("evaluated = " + evaluated)
+} \ No newline at end of file
diff --git a/test/pending/run/t5266_2.check b/test/pending/run/t5266_2.check
new file mode 100644
index 0000000000..3feac16a0b
--- /dev/null
+++ b/test/pending/run/t5266_2.check
@@ -0,0 +1,2 @@
+2
+evaluated = null \ No newline at end of file
diff --git a/test/pending/run/t5266_2.scala b/test/pending/run/t5266_2.scala
new file mode 100644
index 0000000000..cd841da021
--- /dev/null
+++ b/test/pending/run/t5266_2.scala
@@ -0,0 +1,17 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ def x = 2
+ def y = x
+ println(y)
+ };
+
+ val reporter = new ConsoleReporter(settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ val evaluated = toolbox.runExpr(ttree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/pending/run/t5269.check b/test/pending/run/t5269.check
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/test/pending/run/t5269.check
@@ -0,0 +1 @@
+2
diff --git a/test/pending/run/t5269.scala b/test/pending/run/t5269.scala
new file mode 100644
index 0000000000..a30509f3fe
--- /dev/null
+++ b/test/pending/run/t5269.scala
@@ -0,0 +1,22 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ trait Z {
+ val z = 2
+ }
+
+ class X extends Z {
+ def println() = Predef.println(z)
+ }
+
+ new X().println()
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/test/pending/run/t5270.check b/test/pending/run/t5270.check
new file mode 100644
index 0000000000..08839f6bb2
--- /dev/null
+++ b/test/pending/run/t5270.check
@@ -0,0 +1 @@
+200
diff --git a/test/pending/run/t5270.scala b/test/pending/run/t5270.scala
new file mode 100644
index 0000000000..10f79790b0
--- /dev/null
+++ b/test/pending/run/t5270.scala
@@ -0,0 +1,26 @@
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ val code = scala.reflect.Code.lift{
+ class Y {
+ def y = 100
+ }
+
+ trait Z { this: Y =>
+ val z = 2 * y
+ }
+
+ class X extends Y with Z {
+ def println() = Predef.println(z)
+ }
+
+ new X().println()
+ };
+
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(code.tree)
+ toolbox.runExpr(ttree)
+}
diff --git a/tools/get-scala-revision b/tools/get-scala-revision
index 8731705d06..23b216aa2b 100755
--- a/tools/get-scala-revision
+++ b/tools/get-scala-revision
@@ -1,30 +1,12 @@
#!/bin/sh
#
# Usage: get-scala-revision [dir]
-# Figures out current scala revision of an svn checkout or
-# a git-svn mirror (or a git clone.)
+# Figures out current scala revision of a git clone.
#
# If no dir is given, current working dir is used.
-DIR=""
-if [ $# -eq 0 ]; then
- DIR=`pwd`
-else
- DIR=$1
-fi
+[[ -n "$1" ]] && cd "$1"
-cd $DIR
-
-if [ -d .svn ]; then
- # 2>&1 to catch also error output (e.g. svn warnings)
- svn info . 2>&1 | grep ^Revision | sed 's/Revision: //'
-elif [ -d .git ]; then
- GIT_PAGER=cat
- # this grabs more than one line because otherwise if you have local
- # commits which aren't in git-svn it won't see any revision.
- git log -10 | grep git-svn-id | head -1 | sed 's/[^@]*@\([0-9]*\).*/\1/'
-else
- echo "${DIR} doesn't appear to be git or svn dir." >&2
- echo 0
- exit 1
-fi
+# dev should be a tag at the merge-base of master and the
+# most recent release.
+git describe head --abbrev=7 --match dev
diff --git a/tools/get-scala-revision.bat b/tools/get-scala-revision.bat
index 880bcc3f5c..ed3ade8a3e 100644
--- a/tools/get-scala-revision.bat
+++ b/tools/get-scala-revision.bat
@@ -1,17 +1,11 @@
@echo off
rem
rem Usage: get-scala-revison.bat [dir]
-rem Figures out current scala revision of an svn checkout or
-rem a git-svn mirror (or a git clone.)
+rem Figures out current scala revision of a git clone.
rem
rem If no dir is given, current working dir is used.
-if "%OS%" NEQ "Windows_NT" (
- echo "Sorry, your version of Windows is too old to run Scala."
- goto :eof
-)
@setlocal
-
set _DIR=
if "%*"=="" (
for /f "delims=;" %%i in ('cd') do set "_DIR=%%i"
@@ -20,23 +14,10 @@ if "%*"=="" (
)
cd %_DIR%
-if exist .svn\NUL (
- rem 2>&1 to catch also error output (e.g. svn warnings)
- for /f "skip=4 tokens=2" %%i in ('svn info') do (
- echo %%i
- goto :end
- )
-) else ( if exist .git\NUL (
- set _GIT_PAGER=type
- rem this grabs more than one line because otherwise if you have local
- rem commits which aren't in git-svn it won't see any revision.
- rem TODO: git log -10 | findstr git-svn-id | ...
+if exist .git\NUL (
+ git describe head --abbrev=7 --match dev
echo 0
-) else (
- echo %_DIR% doesn't appear to be git or svn dir.
- echo 0
- exit 1
-))
+)
:end
@endlocal