summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-05 07:52:06 -0700
committerPaul Phillips <paulp@improving.org>2012-10-05 07:52:06 -0700
commitd42b1e9e0c08349ae97212296aca4c2bad2cc7f2 (patch)
tree8765904a60bbae758d1c853ca2a4e2ac409dd47f /src
parent6c7e6eb5d7bc29975d12b87ca65e3059ede422db (diff)
parent59d869f51aa555b03c13032a5d975d4e8e23bf8e (diff)
downloadscala-d42b1e9e0c08349ae97212296aca4c2bad2cc7f2.tar.gz
scala-d42b1e9e0c08349ae97212296aca4c2bad2cc7f2.tar.bz2
scala-d42b1e9e0c08349ae97212296aca4c2bad2cc7f2.zip
Merge branch 'master' into infer-method-alternative
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala6
-rw-r--r--src/compiler/scala/reflect/reify/phases/Metalevels.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala13
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala41
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala2
-rw-r--r--src/detach/plugin/scala/tools/detach/Detach.scala24
-rw-r--r--src/library/scala/util/matching/Regex.scala98
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala4
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala28
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala9
-rw-r--r--src/reflect/scala/reflect/internal/util/StringOps.scala8
-rw-r--r--src/reflect/scala/reflect/internal/util/package.scala34
26 files changed, 201 insertions, 128 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index bdcc7383b0..86ad23cd15 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -64,7 +64,7 @@ trait GenTrees {
// usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
// however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why.
- if (reifyTreeSymbols && tree.hasSymbol) {
+ if (reifyTreeSymbols && tree.hasSymbolField) {
if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree))
rtree = mirrorBuildCall(nme.setSymbol, rtree, reify(tree.symbol))
}
@@ -86,8 +86,8 @@ trait GenTrees {
// see ``Metalevels'' for more info about metalevel breaches
// and about how we deal with splices that contain them
- val isMetalevelBreach = splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
- val isRuntimeEval = splicee exists (sub => sub.hasSymbol && sub.symbol == ExprSplice)
+ val isMetalevelBreach = splicee exists (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
+ val isRuntimeEval = splicee exists (sub => sub.hasSymbolField && sub.symbol == ExprSplice)
if (isMetalevelBreach || isRuntimeEval) {
// we used to convert dynamic splices into runtime evals transparently, but we no longer do that
// why? see comments in ``Metalevels''
diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
index fbbd12a42f..4c6ebbb288 100644
--- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala
+++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
@@ -124,7 +124,7 @@ trait Metalevels {
withinSplice { super.transform(TreeSplice(ReifiedTree(universe, mirror, symtab1, rtree, tpe, rtpe, concrete))) }
case TreeSplice(splicee) =>
if (reifyDebug) println("entering splice: " + splicee)
- val breaches = splicee filter (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
+ val breaches = splicee filter (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
if (!insideSplice && breaches.nonEmpty) {
// we used to convert dynamic splices into runtime evals transparently, but we no longer do that
// why? see comments above
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 267a5dcefd..be7a6295b4 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -509,7 +509,7 @@ abstract class TreeBrowsers {
/** Return a textual representation of this t's symbol */
def symbolText(t: Tree): String = {
val prefix =
- if (t.hasSymbol) "[has] "
+ if (t.hasSymbolField) "[has] "
else if (t.isDef) "[defines] "
else ""
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 20da5f0087..a74b62bf8d 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -22,7 +22,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
def mkCheckInit(tree: Tree): Tree = {
val tpe =
- if (tree.tpe != null || !tree.hasSymbol) tree.tpe
+ if (tree.tpe != null || !tree.hasSymbolField) tree.tpe
else tree.symbol.tpe
if (!global.phase.erasedTypes && settings.warnSelectNullable.value &&
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 3ccc595fb2..f6073cf185 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -341,7 +341,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
tree
case _ =>
val dupl = tree.duplicate
- if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
+ if (tree.hasSymbolField && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
dupl.symbol = NoSymbol
dupl.tpe = null
dupl
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
index b390ad5417..9a4be27c76 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -10,6 +10,7 @@ import scala.tools.jline._
import scala.tools.jline.console.completer._
import Completion._
import scala.collection.mutable.ListBuffer
+import scala.reflect.internal.util.StringOps.longestCommonPrefix
// REPL completor - queries supplied interpreter for valid
// completions based on current contents of buffer.
@@ -301,16 +302,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
def isConsecutiveTabs(buf: String, cursor: Int) =
cursor == lastCursor && buf == lastBuf
- // Longest common prefix
- def commonPrefix(xs: List[String]): String = {
- if (xs.isEmpty || xs.contains("")) ""
- else xs.head.head match {
- case ch =>
- if (xs.tail forall (_.head == ch)) "" + ch + commonPrefix(xs map (_.tail))
- else ""
- }
- }
-
// This is jline's entry point for completion.
override def complete(buf: String, cursor: Int): Candidates = {
verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
@@ -324,7 +315,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
val newCursor =
if (winners contains "") p.cursor
else {
- val advance = commonPrefix(winners)
+ val advance = longestCommonPrefix(winners)
lastCursor = p.position + advance.length
lastBuf = (buf take p.position) + advance
repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format(
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index fe1c4c0ca8..0bf4999fd6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -212,6 +212,7 @@ trait TypeStrings {
}
private def tparamString[T: ru.TypeTag] : String = {
+ import ru._
def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil }
// [Eugene to Paul] need to use not the `rootMirror`, but a mirror with the REPL's classloader
// how do I get to it? acquiring context classloader seems unreliable because of multithreading
@@ -256,4 +257,4 @@ trait TypeStrings {
)
}
-object TypeStrings extends TypeStrings { } \ No newline at end of file
+object TypeStrings extends TypeStrings { }
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 5dbd22f23b..182338a0a1 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -68,7 +68,7 @@ abstract class Pickler extends SubComponent {
return
}
- if (!t.isDef && t.hasSymbol && t.symbol.isTermMacro) {
+ if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) {
unit.error(t.pos, t.symbol.typeParams.length match {
case 0 => "macro has not been expanded"
case 1 => "this type parameter must be specified"
@@ -235,7 +235,7 @@ abstract class Pickler extends SubComponent {
private def putTree(tree: Tree): Unit = if (putEntry(tree)) {
if (tree != EmptyTree)
putType(tree.tpe)
- if (tree.hasSymbol)
+ if (tree.hasSymbolField)
putSymbol(tree.symbol)
tree match {
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 3e0e40e525..32c2d63b2a 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -321,7 +321,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
Block(List(Apply(gen.mkSuperInitCall, Nil)), expr)
case Block(stats, expr) =>
- // needs `hasSymbol` check because `supercall` could be a block (named / default args)
+ // needs `hasSymbolField` check because `supercall` could be a block (named / default args)
val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER))
treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 27ceb66af4..b54f128961 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -438,7 +438,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
tree match {
case Assign(lhs, rhs) => traverse(rhs) // assignments don't count
case _ =>
- if (tree.hasSymbol && tree.symbol != NoSymbol) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol) {
val sym = tree.symbol
if ((sym.hasAccessorFlag || (sym.isTerm && !sym.isMethod))
&& sym.isPrivate
@@ -804,7 +804,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
class TreeSymSubstituterWithCopying(from: List[Symbol], to: List[Symbol]) extends TreeSymSubstituter(from, to) {
override def transform(tree: Tree): Tree =
- if (tree.hasSymbol && from.contains(tree.symbol))
+ if (tree.hasSymbolField && from.contains(tree.symbol))
super.transform(tree.duplicate)
else super.transform(tree.duplicate)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index f68cbfc141..ea93ad1bd4 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -205,11 +205,8 @@ abstract class UnCurry extends InfoTransform
val keyDef = ValDef(key, New(ObjectClass.tpe))
val tryCatch = Try(body, pat -> rhs)
- body foreach {
- case Try(t, catches, _) if catches exists treeInfo.catchesThrowable =>
- unit.warning(body.pos, "catch block may intercept non-local return from " + meth)
- case _ =>
- }
+ for (Try(t, catches, _) <- body ; cdef <- catches ; if treeInfo catchesThrowable cdef)
+ unit.warning(body.pos, "catch block may intercept non-local return from " + meth)
Block(List(keyDef), tryCatch)
}
@@ -691,16 +688,16 @@ abstract class UnCurry extends InfoTransform
else
tree
}
-
+
def isThrowable(pat: Tree): Boolean = pat match {
- case Typed(Ident(nme.WILDCARD), tpt) =>
+ case Typed(Ident(nme.WILDCARD), tpt) =>
tpt.tpe =:= ThrowableClass.tpe
- case Bind(_, pat) =>
+ case Bind(_, pat) =>
isThrowable(pat)
case _ =>
false
}
-
+
def isDefaultCatch(cdef: CaseDef) = isThrowable(cdef.pat) && cdef.guard.isEmpty
def postTransformTry(tree: Try) = {
@@ -764,10 +761,10 @@ abstract class UnCurry extends InfoTransform
case tree: Try =>
postTransformTry(tree)
-
+
case Apply(Apply(fn, args), args1) =>
treeCopy.Apply(tree, fn, args ::: args1)
-
+
case Ident(name) =>
assert(name != tpnme.WILDCARD_STAR, tree)
applyUnary()
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 2dd0836322..1bd2bbcd5c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -233,7 +233,7 @@ abstract class Duplicators extends Analyzer {
override def typed(tree: Tree, mode: Int, pt: Type): Tree = {
debuglog("typing " + tree + ": " + tree.tpe + ", " + tree.getClass)
val origtreesym = tree.symbol
- if (tree.hasSymbol && tree.symbol != NoSymbol
+ if (tree.hasSymbolField && tree.symbol != NoSymbol
&& !tree.symbol.isLabel // labels cannot be retyped by the type checker as LabelDef has no ValDef/return type trees
&& invalidSyms.isDefinedAt(tree.symbol)) {
debuglog("removed symbol " + tree.symbol)
@@ -403,7 +403,7 @@ abstract class Duplicators extends Analyzer {
case _ =>
debuglog("Duplicators default case: " + tree.summaryString)
debuglog(" ---> " + tree)
- if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==)
}
val ntree = castType(tree, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 5c5966834b..2fd685866f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -276,7 +276,7 @@ trait Infer extends Checkable {
def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue
def errorSym = if (tree.isType) errorClass else errorValue
- if (tree.hasSymbol)
+ if (tree.hasSymbolField)
tree setSymbol errorSym
tree setType ErrorType
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 52880609e9..96e1ed9a1c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -2547,7 +2547,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
val toString =
- if (p.hasSymbol && p.symbol.isStable) p.symbol.name.toString // tp.toString
+ if (p.hasSymbolField && p.symbol.isStable) p.symbol.name.toString // tp.toString
else p.toString //+"#"+ id
Const.unique(narrowTp, new ValueConst(narrowTp, checkableType(wideTp), toString)) // must make wide type checkable so that it is comparable to types from TypeConst
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 48d8c6186c..3054993c20 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -53,7 +53,7 @@ trait Typers extends Modes with Adaptations with Tags {
object UnTyper extends Traverser {
override def traverse(tree: Tree) = {
if (tree != EmptyTree) tree.tpe = null
- if (tree.hasSymbol) tree.symbol = NoSymbol
+ if (tree.hasSymbolField) tree.symbol = NoSymbol
super.traverse(tree)
}
}
@@ -242,7 +242,7 @@ trait Typers extends Modes with Adaptations with Tags {
* of its symbol was not volatile?
*/
protected def isStableExceptVolatile(tree: Tree) = {
- tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
+ tree.hasSymbolField && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
{ val savedTpe = tree.symbol.info
val savedSTABLE = tree.symbol getFlag STABLE
tree.symbol setInfo AnyRefClass.tpe
@@ -915,7 +915,7 @@ trait Typers extends Modes with Adaptations with Tags {
// but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else
// tree setType tree.tpe.normalize
tree
- } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) &&
+ } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) &&
!(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7)
// @M When not typing a higher-kinded type ((mode & HKmode) == 0)
// or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *,
@@ -923,7 +923,7 @@ trait Typers extends Modes with Adaptations with Tags {
// @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
MissingTypeParametersError(tree)
} else if ( // (7.1) @M: check kind-arity
- // @M: removed check for tree.hasSymbol and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
+ // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
(inHKMode(mode)) &&
// @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!!
// (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!)
@@ -1457,7 +1457,7 @@ trait Typers extends Modes with Adaptations with Tags {
// Determine
// - supertparams: Missing type parameters from supertype
// - supertpe: Given supertype, polymorphic in supertparams
- val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List()
+ val supertparams = if (supertpt.hasSymbolField) supertpt.symbol.typeParams else List()
var supertpe = supertpt.tpe
if (!supertparams.isEmpty)
supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (_.tpeHK)))
@@ -2896,7 +2896,7 @@ trait Typers extends Modes with Adaptations with Tags {
def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree }
def preSelectOverloaded(fun: Tree): Tree = {
- if (fun.hasSymbol && fun.symbol.isOverloaded) {
+ if (fun.hasSymbolField && fun.symbol.isOverloaded) {
// remove alternatives with wrong number of parameters without looking at types.
// less expensive than including them in inferMethodAlternative (see below).
def shapeType(arg: Tree): Type = arg match {
@@ -3297,12 +3297,13 @@ trait Typers extends Modes with Adaptations with Tags {
// println(util.Position.formatMessage(uncheckedPattern.pos, "made unchecked type test into a checked one", true))
val args = List(uncheckedPattern)
+ val app = atPos(uncheckedPattern.pos)(Apply(classTagExtractor, args))
// must call doTypedUnapply directly, as otherwise we get undesirable rewrites
// and re-typechecks of the target of the unapply call in PATTERNmode,
// this breaks down when the classTagExtractor (which defineds the unapply member) is not a simple reference to an object,
// but an arbitrary tree as is the case here
- doTypedUnapply(Apply(classTagExtractor, args), classTagExtractor, classTagExtractor, args, PATTERNmode, pt)
- }
+ doTypedUnapply(app, classTagExtractor, classTagExtractor, args, PATTERNmode, pt)
+ }
// if there's a ClassTag that allows us to turn the unchecked type test for `pt` into a checked type test
// return the corresponding extractor (an instance of ClassTag[`pt`])
@@ -4199,7 +4200,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tpt1 = {
val tpt0 = typedTypeConstructor(tpt)
if (checkStablePrefixClassType(tpt0))
- if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
+ if (tpt0.hasSymbolField && !tpt0.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
notifyUndetparamsAdded(context.undetparams)
TypeTree().setOriginal(tpt0)
@@ -4411,12 +4412,12 @@ trait Typers extends Modes with Adaptations with Tags {
else doTypedApply(tree, fun2, args, mode, pt)
/*
- if (fun2.hasSymbol && fun2.symbol.isConstructor && (mode & EXPRmode) != 0) {
+ if (fun2.hasSymbolField && fun2.symbol.isConstructor && (mode & EXPRmode) != 0) {
res.tpe = res.tpe.notNull
}
*/
// TODO: In theory we should be able to call:
- //if (fun2.hasSymbol && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
+ //if (fun2.hasSymbolField && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
// But this causes cyclic reference for Array class in Cleanup. It is easy to overcome this
// by calling ArrayClass.info here (or some other place before specialize).
if (fun2.symbol == Array_apply && !res.isErrorTyped) {
@@ -5022,7 +5023,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
if (tpt1.isErrorTyped) {
tpt1
- } else if (!tpt1.hasSymbol) {
+ } else if (!tpt1.hasSymbolField) {
AppliedTypeNoParametersError(tree, tpt1.tpe)
} else {
val tparams = tpt1.symbol.typeParams
@@ -5131,14 +5132,12 @@ trait Typers extends Modes with Adaptations with Tags {
var block1 = typed(tree.block, pt)
var catches1 = typedCases(tree.catches, ThrowableClass.tpe, pt)
- for (cdef <- catches1 if cdef.guard.isEmpty) {
- def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
- def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- cdef.pat match {
- case Bind(name, i @ Ident(_)) if unbound(i) => warn(name)
- case i @ Ident(name) if unbound(i) => warn(name)
- case _ =>
- }
+ for (cdef <- catches1; if treeInfo catchesThrowable cdef) {
+ val name = (treeInfo assignedNameOfPattern cdef).decoded
+ context.warning(cdef.pat.pos,
+ s"""|This catches all Throwables, which often has undesirable consequences.
+ |If intentional, use `case $name : Throwable` to clear this warning.""".stripMargin
+ )
}
val finalizer1 =
@@ -5394,7 +5393,7 @@ trait Typers extends Modes with Adaptations with Tags {
if (context.retyping &&
(tree.tpe ne null) && (tree.tpe.isErroneous || !(tree.tpe <:< pt))) {
tree.tpe = null
- if (tree.hasSymbol) tree.symbol = NoSymbol
+ if (tree.hasSymbolField) tree.symbol = NoSymbol
}
alreadyTyped = tree.tpe ne null
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 95135b84e0..bc8ded62d8 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -102,7 +102,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
})
var expr = new Transformer {
override def transform(tree: Tree): Tree =
- if (tree.hasSymbol && tree.symbol.isFreeTerm) {
+ if (tree.hasSymbolField && tree.symbol.isFreeTerm) {
tree match {
case Ident(_) =>
val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTerm))
diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala
index 376a56beed..d56a7f0fbe 100644
--- a/src/detach/plugin/scala/tools/detach/Detach.scala
+++ b/src/detach/plugin/scala/tools/detach/Detach.scala
@@ -206,7 +206,7 @@ abstract class Detach extends PluginComponent
symSet(capturedObjects, owner) += qsym
case Select(qual, name)
- if (qual.hasSymbol &&
+ if (qual.hasSymbolField &&
(sym.owner != owner) &&
!(sym.ownerChain contains ScalaPackageClass) &&
!(sym.owner hasFlag JAVA)) =>
@@ -284,7 +284,7 @@ abstract class Detach extends PluginComponent
def isOuter(sym: Symbol): Boolean =
sym.isOuterAccessor ||
sym.name.endsWith(nme.OUTER/*, nme.OUTER.length*/)
- if (tree.hasSymbol && isOuter(tree.symbol)) subst(from, to)
+ if (tree.hasSymbolField && isOuter(tree.symbol)) subst(from, to)
super.traverse(tree)
}
}
@@ -293,7 +293,7 @@ abstract class Detach extends PluginComponent
private class TreeTypeRefSubstituter(clazz: Symbol) extends Traverser {
override def traverse(tree: Tree) {
val sym = tree.symbol
- if (tree.hasSymbol && isRefClass(sym.tpe) &&
+ if (tree.hasSymbolField && isRefClass(sym.tpe) &&
(sym.owner.enclClass == clazz) &&
(sym.isValueParameter || sym.hasFlag(PARAMACCESSOR))) {
sym setInfo mkRemoteRefClass(sym.tpe)
@@ -329,7 +329,7 @@ abstract class Detach extends PluginComponent
}
val map = new mutable.HashMap[Symbol, Symbol]
override def traverse(tree: Tree) {
- if (tree.hasSymbol && tree.symbol != NoSymbol) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol) {
val sym = tree.symbol
if (sym.owner == from) {
val sym1 = map get sym match {
@@ -369,7 +369,7 @@ abstract class Detach extends PluginComponent
def removeAccessors(tree: Tree): Tree = tree match {
case Apply(fun, _) =>
removeAccessors(fun)
- case Select(qual, _) if tree.hasSymbol && tree.symbol.isOuterAccessor =>
+ case Select(qual, _) if tree.hasSymbolField && tree.symbol.isOuterAccessor =>
removeAccessors(qual)
case _ =>
tree
@@ -382,7 +382,7 @@ abstract class Detach extends PluginComponent
// transforms field assignment $outer.i$1.elem=..
// into setter $outer.i$1_=(..)
case Assign(lhs @ Select(qual1 @ Select(qual, name), name1), rhs)
- if qual1.hasSymbol && !qual1.symbol.isPrivateLocal &&
+ if qual1.hasSymbolField && !qual1.symbol.isPrivateLocal &&
isRemoteRefClass(qual1.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Assign1\n\tqual1="+qual1+", sel.tpe="+lhs.tpe+
@@ -398,7 +398,7 @@ abstract class Detach extends PluginComponent
// transforms local assignment this.x$1.elem=..
// into setter method this.x$1_=(..)
case Assign(lhs @ Select(qual, name), rhs)
- if qual.hasSymbol && qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Assign2"+
@@ -412,7 +412,7 @@ abstract class Detach extends PluginComponent
Apply(fun, List(super.transform(rhs))) setType lhs.tpe
case Assign(Select(qual, name), rhs)
- if qual.hasSymbol && (objs contains qual.symbol) =>
+ if qual.hasSymbolField && (objs contains qual.symbol) =>
val sym = qual.symbol
val proxy = proxySyms(objs indexOf sym)
if (DEBUG)
@@ -461,7 +461,7 @@ abstract class Detach extends PluginComponent
// transforms field $outer.name$1 into getter method $outer.name$1()
case Select(qual @ Select(_, name1), name)
- if qual.hasSymbol && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) &&
+ if qual.hasSymbolField && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) &&
!tree.symbol.isMethod =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select0\n\tqual="+qual+
@@ -500,7 +500,7 @@ abstract class Detach extends PluginComponent
// transforms field access $outer.i$1.elem
// into invocation of getter method $outer.i$1()
case Select(qual @ Select(qual1, name1), name)
- if qual.hasSymbol && !qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && !qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select2\n\tqual="+qual+
@@ -513,7 +513,7 @@ abstract class Detach extends PluginComponent
// transforms local access this.i$1.elem
// into invocation of getter method this.i$1()
case Select(qual, name)
- if qual.hasSymbol && qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select3\n\tqual="+qual+
@@ -523,7 +523,7 @@ abstract class Detach extends PluginComponent
Apply(fun, List()) setType tree.tpe
case Select(qual, name)
- if qual.hasSymbol && (objs contains qual.symbol) =>
+ if qual.hasSymbolField && (objs contains qual.symbol) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select4\n\tqual="+qual+
", qual.tpe="+qual.tpe+", name="+name)//debug
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 3655a0a019..63d049208a 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -131,7 +131,7 @@ import java.util.regex.{ Pattern, Matcher }
* @author Martin Odersky
* @version 1.1, 29/01/2008
*
- * @param regex A string representing a regular expression
+ * @param pattern The compiled pattern
* @param groupNames A mapping from names to indices in capture groups
*
* @define replacementString
@@ -144,41 +144,67 @@ import java.util.regex.{ Pattern, Matcher }
* to automatically escape these characters.
*/
@SerialVersionUID(-2094783597747625537L)
-class Regex(regex: String, groupNames: String*) extends Serializable {
+class Regex private[matching](val pattern: Pattern, groupNames: String*) extends Serializable {
outer =>
import Regex._
- /** The compiled pattern */
- val pattern = Pattern.compile(regex)
+ /**
+ * @param regex A string representing a regular expression
+ * @param groupNames A mapping from names to indices in capture groups
+ */
+ def this(regex: String, groupNames: String*) = this(Pattern.compile(regex), groupNames: _*)
- /** Tries to match target (whole match) and returns the matching subgroups.
- * if the pattern has no subgroups, then it returns an empty list on a
- * successful match.
- *
- * Note, however, that if some subgroup has not been matched, a `null` will
- * be returned for that subgroup.
+ /** Tries to match a [[java.lang.CharSequence]].
+ * If the match succeeds, the result is a list of the matching
+ * groups (or a `null` element if a group did not match any input).
+ * If the pattern specifies no groups, then the result will be an empty list
+ * on a successful match.
*
+ * This method attempts to match the entire input by default; to find the next
+ * matching subsequence, use an unanchored Regex.
+
* For example:
*
* {{{
* val p1 = "ab*c".r
- * val p2 = "a(b*)c".r
- *
* val p1Matches = "abbbc" match {
* case p1() => true
* case _ => false
* }
- *
+ * val p2 = "a(b*)c".r
* val numberOfB = "abbbc" match {
* case p2(b) => Some(b.length)
* case _ => None
* }
+ * val p3 = "b*".r.unanchored
+ * val p3Matches = "abbbc" match {
+ * case p3() => true
+ * case _ => false
+ * }
* }}}
*
- * @param target The string to match
+ * @param s The string to match
* @return The matches
*/
+ def unapplySeq(s: CharSequence): Option[Seq[String]] = {
+ val m = pattern matcher s
+ if (runMatcher(m)) Some(1 to m.groupCount map m.group)
+ else None
+ }
+
+ /** Tries to match on a [[scala.util.matching.Regex.Match]].
+ * A previously failed match results in None.
+ * If a successful match was made against the current pattern, then that result is used.
+ * Otherwise, this Regex is applied to the previously matched input,
+ * and the result of that match is used.
+ */
+ def unapplySeq(m: Match): Option[Seq[String]] =
+ if (m.matched == null) None
+ else if (m.matcher.pattern == this.pattern) Some(1 to m.groupCount map m.group)
+ else unapplySeq(m.matched)
+
+ @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.10.0")
def unapplySeq(target: Any): Option[List[String]] = target match {
case s: CharSequence =>
val m = pattern matcher s
@@ -187,6 +213,8 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
case m: Match => unapplySeq(m.matched)
case _ => None
}
+
+ // @see UnanchoredRegex
protected def runMatcher(m: Matcher) = m.matches()
/** Return all matches of this regexp in given character sequence as a [[scala.util.matching.Regex.MatchIterator]],
@@ -200,7 +228,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.util.matching.Regex.MatchIterator]] of all matches.
* @example {{{for (words <- """\w+""".r findAllIn "A simple example.") yield words}}}
*/
- def findAllIn(source: java.lang.CharSequence) = new Regex.MatchIterator(source, this, groupNames)
+ def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames)
/** Return all matches of this regexp in given character sequence as a
@@ -210,7 +238,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]] for all matches.
* @example {{{for (words <- """\w+""".r findAllMatchIn "A simple example.") yield words.start}}}
*/
- def findAllMatchIn(source: java.lang.CharSequence): Iterator[Match] = {
+ def findAllMatchIn(source: CharSequence): Iterator[Match] = {
val matchIterator = findAllIn(source)
new Iterator[Match] {
def hasNext = matchIterator.hasNext
@@ -228,7 +256,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return An [[scala.Option]] of the first matching string in the text.
* @example {{{"""\w+""".r findFirstIn "A simple example." foreach println // prints "A"}}}
*/
- def findFirstIn(source: java.lang.CharSequence): Option[String] = {
+ def findFirstIn(source: CharSequence): Option[String] = {
val m = pattern.matcher(source)
if (m.find) Some(m.group) else None
}
@@ -245,7 +273,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of [[scala.util.matching.Regex.Match]] of the first matching string in the text.
* @example {{{("""[a-z]""".r findFirstMatchIn "A simple example.") map (_.start) // returns Some(2), the index of the first match in the text}}}
*/
- def findFirstMatchIn(source: java.lang.CharSequence): Option[Match] = {
+ def findFirstMatchIn(source: CharSequence): Option[Match] = {
val m = pattern.matcher(source)
if (m.find) Some(new Match(source, m, groupNames)) else None
}
@@ -262,7 +290,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of the matched prefix.
* @example {{{"""[a-z]""".r findPrefixOf "A simple example." // returns None, since the text does not begin with a lowercase letter}}}
*/
- def findPrefixOf(source: java.lang.CharSequence): Option[String] = {
+ def findPrefixOf(source: CharSequence): Option[String] = {
val m = pattern.matcher(source)
if (m.lookingAt) Some(m.group) else None
}
@@ -279,7 +307,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of the [[scala.util.matching.Regex.Match]] of the matched string.
* @example {{{"""\w+""".r findPrefixMatchOf "A simple example." map (_.after) // returns Some(" simple example.")}}}
*/
- def findPrefixMatchOf(source: java.lang.CharSequence): Option[Match] = {
+ def findPrefixMatchOf(source: CharSequence): Option[Match] = {
val m = pattern.matcher(source)
if (m.lookingAt) Some(new Match(source, m, groupNames)) else None
}
@@ -293,7 +321,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return The resulting string
* @example {{{"""\d+""".r replaceAllIn ("July 15", "<NUMBER>") // returns "July <NUMBER>"}}}
*/
- def replaceAllIn(target: java.lang.CharSequence, replacement: String): String = {
+ def replaceAllIn(target: CharSequence, replacement: String): String = {
val m = pattern.matcher(target)
m.replaceAll(replacement)
}
@@ -316,7 +344,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacer The function which maps a match to another string.
* @return The target string after replacements.
*/
- def replaceAllIn(target: java.lang.CharSequence, replacer: Match => String): String = {
+ def replaceAllIn(target: CharSequence, replacer: Match => String): String = {
val it = new Regex.MatchIterator(target, this, groupNames).replacementData
it foreach (md => it replace replacer(md))
it.replaced
@@ -343,7 +371,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacer The function which optionally maps a match to another string.
* @return The target string after replacements.
*/
- def replaceSomeIn(target: java.lang.CharSequence, replacer: Match => Option[String]): String = {
+ def replaceSomeIn(target: CharSequence, replacer: Match => Option[String]): String = {
val it = new Regex.MatchIterator(target, this, groupNames).replacementData
for (matchdata <- it ; replacement <- replacer(matchdata))
it replace replacement
@@ -359,7 +387,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacement The string that will replace the match
* @return The resulting string
*/
- def replaceFirstIn(target: java.lang.CharSequence, replacement: String): String = {
+ def replaceFirstIn(target: CharSequence, replacement: String): String = {
val m = pattern.matcher(target)
m.replaceFirst(replacement)
}
@@ -370,7 +398,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return The array of strings computed by splitting the
* input around matches of this regexp
*/
- def split(toSplit: java.lang.CharSequence): Array[String] =
+ def split(toSplit: CharSequence): Array[String] =
pattern.split(toSplit)
/** Create a new Regex with the same pattern, but no requirement that
@@ -390,9 +418,11 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
*
* @return The new unanchored regex
*/
- def unanchored: UnanchoredRegex = new Regex(regex, groupNames: _*) with UnanchoredRegex { override def anchored = outer }
+ def unanchored: UnanchoredRegex = new Regex(pattern, groupNames: _*) with UnanchoredRegex { override def anchored = outer }
def anchored: Regex = this
+ def regex: String = pattern.pattern
+
/** The string defining the regular expression */
override def toString = regex
}
@@ -421,7 +451,7 @@ object Regex {
trait MatchData {
/** The source from where the match originated */
- val source: java.lang.CharSequence
+ val source: CharSequence
/** The names of the groups, or some empty sequence if one defined */
val groupNames: Seq[String]
@@ -459,25 +489,25 @@ object Regex {
/** The char sequence before first character of match,
* or `null` if nothing was matched */
- def before: java.lang.CharSequence =
+ def before: CharSequence =
if (start >= 0) source.subSequence(0, start)
else null
/** The char sequence before first character of match in group `i`,
* or `null` if nothing was matched for that group */
- def before(i: Int): java.lang.CharSequence =
+ def before(i: Int): CharSequence =
if (start(i) >= 0) source.subSequence(0, start(i))
else null
/** Returns char sequence after last character of match,
* or `null` if nothing was matched */
- def after: java.lang.CharSequence =
+ def after: CharSequence =
if (end >= 0) source.subSequence(end, source.length)
else null
/** The char sequence after last character of match in group `i`,
* or `null` if nothing was matched for that group */
- def after(i: Int): java.lang.CharSequence =
+ def after(i: Int): CharSequence =
if (end(i) >= 0) source.subSequence(end(i), source.length)
else null
@@ -501,8 +531,8 @@ object Regex {
/** Provides information about a succesful match.
*/
- class Match(val source: java.lang.CharSequence,
- matcher: Matcher,
+ class Match(val source: CharSequence,
+ private[matching] val matcher: Matcher,
val groupNames: Seq[String]) extends MatchData {
/** The index of the first matched character */
@@ -563,7 +593,7 @@ object Regex {
/** A class to step through a sequence of regex matches
*/
- class MatchIterator(val source: java.lang.CharSequence, val regex: Regex, val groupNames: Seq[String])
+ class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String])
extends AbstractIterator[String] with Iterator[String] with MatchData { self =>
protected[Regex] val matcher = regex.pattern.matcher(source)
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 1f15ee6070..bbd5d00be3 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -100,7 +100,7 @@ trait Trees { self: Universe =>
def symbol: Symbol
/** ... */
- def hasSymbol: Boolean
+ def hasSymbolField: Boolean
/** Provides an alternate if tree is empty
* @param alt The alternate tree
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index 43902c1930..ea8d6078ff 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -427,17 +427,17 @@ trait Importers extends api.Importers { self: SymbolTable =>
}
addFixup({
if (mytree != null) {
- val mysym = if (tree.hasSymbol) importSymbol(tree.symbol) else NoSymbol
+ val mysym = if (tree.hasSymbolField) importSymbol(tree.symbol) else NoSymbol
val mytpe = importType(tree.tpe)
mytree match {
case mytt: TypeTree =>
val tt = tree.asInstanceOf[from.TypeTree]
- if (mytree.hasSymbol) mytt.symbol = mysym
+ if (mytree.hasSymbolField) mytt.symbol = mysym
if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe)
if (tt.original != null) mytt.setOriginal(importTree(tt.original))
case _ =>
- if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol)
+ if (mytree.hasSymbolField) mytree.symbol = importSymbol(tree.symbol)
mytree.tpe = importType(tree.tpe)
}
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index fb165ab50f..b4f03cfdd1 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -546,8 +546,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
case _ => print(value.toString)
}
case tree: Tree =>
- val hasSymbol = tree.hasSymbol && tree.symbol != NoSymbol
- val isError = hasSymbol && tree.symbol.name.toString == nme.ERROR.toString
+ val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
+ val isError = hasSymbolField && tree.symbol.name.toString == nme.ERROR.toString
printProduct(
tree,
preamble = _ => {
@@ -560,7 +560,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
if (isError) print("<")
print(name)
if (isError) print(": error>")
- } else if (hasSymbol) {
+ } else if (hasSymbolField) {
tree match {
case _: Ident | _: Select | _: SelectFromTypeTree => print(tree.symbol)
case _ => print(tree.symbol.name)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index d7962eb62b..f7f12de98a 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -8,7 +8,7 @@ package internal
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
-import util.Statistics
+import util.{ Statistics, shortClassOfInstance }
import Flags._
import scala.annotation.tailrec
import scala.reflect.io.AbstractFile
@@ -182,7 +182,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (isGADTSkolem) " (this is a GADT skolem)"
else ""
- def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$")
+ def shortSymbolClass = shortClassOfInstance(this)
def symbolCreationString: String = (
"%s%25s | %-40s | %s".format(
if (settings.uniqid.value) "%06d | ".format(id) else "",
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index db062d138f..d4a22886dd 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -397,19 +397,31 @@ abstract class TreeInfo {
case _ => false
}
- /** Does this CaseDef catch Throwable? */
- def catchesThrowable(cdef: CaseDef) = catchesAllOf(cdef, ThrowableClass.tpe)
+ private def hasNoSymbol(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- /** Does this CaseDef catch everything of a certain Type? */
- def catchesAllOf(cdef: CaseDef, threshold: Type) = {
- def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
+ /** If this CaseDef assigns a name to its top-level pattern,
+ * in the form 'expr @ pattern' or 'expr: pattern', returns
+ * the name. Otherwise, nme.NO_NAME.
+ *
+ * Note: in the case of Constant patterns such as 'case x @ "" =>',
+ * the pattern matcher eliminates the binding and inlines the constant,
+ * so as far as this method is likely to be able to determine,
+ * the name is NO_NAME.
+ */
+ def assignedNameOfPattern(cdef: CaseDef): Name = cdef.pat match {
+ case Bind(name, _) => name
+ case Ident(name) => name
+ case _ => nme.NO_NAME
+ }
+
+ /** Does this CaseDef catch Throwable? */
+ def catchesThrowable(cdef: CaseDef) = (
cdef.guard.isEmpty && (unbind(cdef.pat) match {
case Ident(nme.WILDCARD) => true
- case i@Ident(name) => unbound(i)
- case Typed(_, tpt) => (tpt.tpe != null) && (threshold <:< tpt.tpe)
+ case i@Ident(name) => hasNoSymbol(i)
case _ => false
})
- }
+ )
/** Is this pattern node a catch-all or type-test pattern? */
def isCatchCase(cdef: CaseDef) = cdef match {
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 0f133c2306..d74a78ebda 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -31,7 +31,8 @@ trait Trees extends api.Trees { self: SymbolTable =>
def symbol: Symbol = null //!!!OPT!!! symbol is about 3% of hot compile times -- megamorphic dispatch?
def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) }
def setSymbol(sym: Symbol): this.type = { symbol = sym; this }
- def hasSymbol = false
+ def hasSymbolField = false
+ @deprecated("Use hasSymbolField", "2.11.0") def hasSymbol = hasSymbolField
def isDef = false
@@ -62,7 +63,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
private[scala] def copyAttrs(tree: Tree): this.type = {
rawatt = tree.rawatt
tpe = tree.tpe
- if (hasSymbol) symbol = tree.symbol
+ if (hasSymbolField) symbol = tree.symbol
this
}
@@ -210,7 +211,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
trait TypTree extends Tree with TypTreeApi
abstract class SymTree extends Tree with SymTreeContextApi {
- override def hasSymbol = true
+ override def hasSymbolField = true
override var symbol: Symbol = NoSymbol
}
@@ -1412,7 +1413,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe)
- if (tree.hasSymbol) {
+ if (tree.hasSymbolField) {
subst(from, to)
tree match {
case Ident(name0) if tree.symbol != NoSymbol =>
diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala
index 281ade8134..e4ad8559e2 100644
--- a/src/reflect/scala/reflect/internal/util/StringOps.scala
+++ b/src/reflect/scala/reflect/internal/util/StringOps.scala
@@ -34,6 +34,14 @@ trait StringOps {
s.substring(0, idx + 1)
}
}
+ def longestCommonPrefix(xs: List[String]): String = {
+ if (xs.isEmpty || xs.contains("")) ""
+ else xs.head.head match {
+ case ch =>
+ if (xs.tail forall (_.head == ch)) "" + ch + longestCommonPrefix(xs map (_.tail))
+ else ""
+ }
+ }
def decompose(str: String, sep: Char): List[String] = {
def ws(start: Int): List[String] =
diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala
new file mode 100644
index 0000000000..83c8bf67ba
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/util/package.scala
@@ -0,0 +1,34 @@
+package scala
+package reflect
+package internal
+
+package object util {
+ import StringOps.longestCommonPrefix
+
+ // Shorten a name like Symbols$FooSymbol to FooSymbol.
+ private def shortenName(name: String): String = {
+ if (name == "") return ""
+ val segments = (name split '$').toList
+ val last = segments.last
+
+ if (last.length == 0)
+ segments takeRight 2 mkString "$"
+ else
+ last
+ }
+
+ def shortClassOfInstance(x: AnyRef): String = shortClass(x.getClass)
+ def shortClass(clazz: Class[_]): String = {
+ val name: String = (clazz.getName split '.').last
+ def isModule = name endsWith "$" // object
+ def isAnon = (name split '$').last forall (_.isDigit) // anonymous class
+
+ if (isModule)
+ (name split '$' filterNot (_ == "")).last + "$"
+ else if (isAnon) {
+ val parents = clazz.getSuperclass :: clazz.getInterfaces.toList
+ parents map (c => shortClass(c)) mkString " with "
+ }
+ else shortenName(name)
+ }
+}