diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-02-03 22:06:42 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-02-04 09:19:19 +1000 |
commit | da46355a90442636ee7634c31a69eae8e8b9cd42 (patch) | |
tree | eec9abbf057e3c5fd4566df6628f9693835cc536 /src | |
parent | 74e53cb4930fc3e02222d8be0f065ce8aaa71230 (diff) | |
parent | cc6fea6d30609b8879db1ecdbc288e4cdaa5b8d4 (diff) | |
download | scala-da46355a90442636ee7634c31a69eae8e8b9cd42.tar.gz scala-da46355a90442636ee7634c31a69eae8e8b9cd42.tar.bz2 scala-da46355a90442636ee7634c31a69eae8e8b9cd42.zip |
Merge commit 'cc6fea6' into merge/2.11.x-to-2.12.x-20160203
Conflicts:
build.sbt
scripts/jobs/integrate/bootstrap
Diffstat (limited to 'src')
6 files changed, 79 insertions, 53 deletions
diff --git a/src/compiler/scala/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/reflect/quasiquotes/Parsers.scala index 6972c4070c..c695f438a4 100644 --- a/src/compiler/scala/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/reflect/quasiquotes/Parsers.scala @@ -56,6 +56,10 @@ trait Parsers { self: Quasiquotes => override implicit lazy val fresh: FreshNameCreator = new FreshNameCreator(nme.QUASIQUOTE_PREFIX) + // Do not check for tuple arity. The placeholders can support arbitrary tuple sizes. + override def makeSafeTupleTerm(trees: List[Tree], offset: Offset): Tree = treeBuilder.makeTupleTerm(trees) + override def makeSafeTupleType(trees: List[Tree], offset: Offset): Tree = treeBuilder.makeTupleType(trees) + override val treeBuilder = new ParserTreeBuilder { override implicit def fresh: FreshNameCreator = parser.fresh diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 1d96b940ae..831a0412cd 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -774,7 +774,58 @@ self => @inline final def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, sepFirst = true, part) def readAnnots(part: => Tree): List[Tree] = tokenSeparated(AT, sepFirst = true, part) -/* --------- OPERAND/OPERATOR STACK --------------------------------------- */ + /** Create a tuple type Tree. If the arity is not supported, a syntax error is emitted. */ + def makeSafeTupleType(elems: List[Tree], offset: Offset) = { + if (checkTupleSize(elems, offset)) makeTupleType(elems) + else makeTupleType(Nil) // create a dummy node; makeTupleType(elems) would fail + } + + /** Create a tuple term Tree. If the arity is not supported, a syntax error is emitted. */ + def makeSafeTupleTerm(elems: List[Tree], offset: Offset) = { + checkTupleSize(elems, offset) + makeTupleTerm(elems) + } + + private[this] def checkTupleSize(elems: List[Tree], offset: Offset): Boolean = + if (elems.lengthCompare(definitions.MaxTupleArity) > 0) { + syntaxError(offset, "too many elements for tuple: "+elems.length+", allowed: "+definitions.MaxTupleArity, skipIt = false) + false + } else true + + /** Strip the artifitial `Parens` node to create a tuple term Tree. */ + def stripParens(t: Tree) = t match { + case Parens(ts) => atPos(t.pos) { makeSafeTupleTerm(ts, t.pos.point) } + case _ => t + } + + /** Create tree representing (unencoded) binary operation expression or pattern. */ + def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = { + require(isExpr || targs.isEmpty || targs.exists(_.isErroneous), s"Incompatible args to makeBinop: !isExpr but targs=$targs") + + def mkSelection(t: Tree) = { + def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode)) + if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs)) + } + def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args + val arguments = right match { + case Parens(args) => mkNamed(args) + case _ => List(right) + } + if (isExpr) { + if (treeInfo.isLeftAssoc(op)) { + Apply(mkSelection(left), arguments) + } else { + val x = freshTermName() + Block( + List(ValDef(Modifiers(symtab.Flags.SYNTHETIC | symtab.Flags.ARTIFACT), x, TypeTree(), stripParens(left))), + Apply(mkSelection(right), List(Ident(x)))) + } + } else { + Apply(Ident(op.encode), stripParens(left) :: arguments) + } + } + + /* --------- OPERAND/OPERATOR STACK --------------------------------------- */ /** Modes for infix types. */ object InfixMode extends Enumeration { @@ -878,7 +929,7 @@ self => atPos(start, in.skipToken()) { makeFunctionTypeTree(ts, typ()) } else { ts foreach checkNotByNameOrVarargs - val tuple = atPos(start) { makeTupleType(ts) } + val tuple = atPos(start) { makeSafeTupleType(ts, start) } infixTypeRest( compoundTypeRest( annotTypeRest( @@ -945,7 +996,7 @@ self => def simpleType(): Tree = { val start = in.offset simpleTypeRest(in.token match { - case LPAREN => atPos(start)(makeTupleType(inParens(types()))) + case LPAREN => atPos(start)(makeSafeTupleType(inParens(types()), start)) case USCORE => wildcardType(in.skipToken()) case _ => path(thisOK = false, typeOK = true) match { diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 6b564197a1..473a40f42a 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -42,44 +42,12 @@ abstract class TreeBuilder { def makeTupleType(elems: List[Tree]) = gen.mkTupleType(elems) - def stripParens(t: Tree) = t match { - case Parens(ts) => atPos(t.pos) { makeTupleTerm(ts) } - case _ => t - } - def makeAnnotated(t: Tree, annot: Tree): Tree = atPos(annot.pos union t.pos)(Annotated(annot, t)) def makeSelfDef(name: TermName, tpt: Tree): ValDef = ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree) - /** Create tree representing (unencoded) binary operation expression or pattern. */ - def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = { - require(isExpr || targs.isEmpty || targs.exists(_.isErroneous), s"Incompatible args to makeBinop: !isExpr but targs=$targs") - - def mkSelection(t: Tree) = { - def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode)) - if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs)) - } - def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args - val arguments = right match { - case Parens(args) => mkNamed(args) - case _ => List(right) - } - if (isExpr) { - if (treeInfo.isLeftAssoc(op)) { - Apply(mkSelection(left), arguments) - } else { - val x = freshTermName() - Block( - List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))), - Apply(mkSelection(right), List(Ident(x)))) - } - } else { - Apply(Ident(op.encode), stripParens(left) :: arguments) - } - } - /** Tree for `od op`, start is start0 if od.pos is borked. */ def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = { val start = if (od.pos.isDefined) od.pos.start else start0 diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index f49536d351..e67e698a5c 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -36,6 +36,8 @@ import scala.reflect.ClassTag * * @author Philipp Haller, Heather Miller, Aleksandar Prokopec, Viktor Klang * + * @see [[http://docs.scala-lang.org/overviews/core/futures.html Futures and Promises]] + * * @define multipleCallbacks * Multiple callbacks may be registered; there is no guarantee that they will be * executed in a particular order. diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 4ff49c44d0..e099853463 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -157,6 +157,9 @@ object ManifestFactory { override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() + override protected def arrayClass[T](tp: Class[_]): Class[Array[T]] = + if (tp eq runtimeClass) classOf[Array[scala.runtime.BoxedUnit]].asInstanceOf[Class[Array[T]]] + else super.arrayClass(tp) private def readResolve(): Any = Manifest.Unit } diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala index fb4ed34571..f1c96636e2 100644 --- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala @@ -48,7 +48,7 @@ trait CommentFactoryBase { this: MemberLookupBase => groupNames0: Map[String,Body] = Map.empty, groupPrio0: Map[String,Body] = Map.empty ) : Comment = new Comment{ - val body = if(body0 isDefined) body0.get else Body(Seq.empty) + val body = body0 getOrElse Body(Seq.empty) val authors = authors0 val see = see0 val result = result0 @@ -83,13 +83,9 @@ trait CommentFactoryBase { this: MemberLookupBase => } val groupNames = groupNames0 flatMap { case (group, body) => - try { - body match { - case Body(List(Paragraph(Chain(List(Summary(Text(name))))))) if (!name.trim.contains("\n")) => List(group -> (name.trim)) - case _ => List() - } - } catch { - case _: java.lang.NumberFormatException => List() + body match { + case Body(List(Paragraph(Chain(List(Summary(Text(name))))))) if (!name.trim.contains("\n")) => List(group -> (name.trim)) + case _ => List() } } @@ -165,11 +161,11 @@ trait CommentFactoryBase { this: MemberLookupBase => private val SymbolTagRegex = new Regex("""\s*@(param|tparam|throws|groupdesc|groupname|groupprio)\s+(\S*)\s*(.*)""") - /** The start of a scaladoc code block */ + /** The start of a Scaladoc code block */ private val CodeBlockStartRegex = new Regex("""(.*?)((?:\{\{\{)|(?:\u000E<pre(?: [^>]*)?>\u000E))(.*)""") - /** The end of a scaladoc code block */ + /** The end of a Scaladoc code block */ private val CodeBlockEndRegex = new Regex("""(.*?)((?:\}\}\})|(?:\u000E</pre>\u000E))(.*)""") @@ -183,6 +179,8 @@ trait CommentFactoryBase { this: MemberLookupBase => private final case class SimpleTagKey(name: String) extends TagKey private final case class SymbolTagKey(name: String, symbol: String) extends TagKey + private val TrailingWhitespaceRegex = """\s+$""".r + /** Parses a raw comment string into a `Comment` object. * @param comment The expanded comment string (including start and end markers) to be parsed. * @param src The raw comment source string. @@ -192,8 +190,8 @@ trait CommentFactoryBase { this: MemberLookupBase => * start and end markers, line start markers and unnecessary whitespace. */ def clean(comment: String): List[String] = { def cleanLine(line: String): String = { - //replaceAll removes trailing whitespaces - line.replaceAll("""\s+$""", "") match { + // Remove trailing whitespaces + TrailingWhitespaceRegex.replaceAllIn(line, "") match { case CleanCommentLine(ctl) => ctl case tl => tl } @@ -321,7 +319,7 @@ trait CommentFactoryBase { this: MemberLookupBase => def oneTag(key: SimpleTagKey, filterEmpty: Boolean = true): Option[Body] = ((bodyTags remove key): @unchecked) match { case Some(r :: rs) if !(filterEmpty && r.blocks.isEmpty) => - if (!rs.isEmpty) reporter.warning(pos, "Only one '@" + key.name + "' tag is allowed") + if (!rs.isEmpty) reporter.warning(pos, s"Only one '@${key.name}' tag is allowed") Some(r) case _ => None } @@ -334,7 +332,7 @@ trait CommentFactoryBase { this: MemberLookupBase => bodyTags.keys.toSeq flatMap { case stk: SymbolTagKey if (stk.name == key.name) => Some(stk) case stk: SimpleTagKey if (stk.name == key.name) => - reporter.warning(pos, "Tag '@" + stk.name + "' must be followed by a symbol name") + reporter.warning(pos, s"Tag '@${stk.name}' must be followed by a symbol name") None case _ => None } @@ -342,7 +340,7 @@ trait CommentFactoryBase { this: MemberLookupBase => for (key <- keys) yield { val bs = (bodyTags remove key).get if (bs.length > 1) - reporter.warning(pos, "Only one '@" + key.name + "' tag for symbol " + key.symbol + " is allowed") + reporter.warning(pos, s"Only one '@${key.name}' tag for symbol ${key.symbol} is allowed") (key.symbol, bs.head) } Map.empty[String, Body] ++ (if (filterEmpty) pairs.filterNot(_._2.blocks.isEmpty) else pairs) @@ -389,7 +387,7 @@ trait CommentFactoryBase { this: MemberLookupBase => ) for ((key, _) <- bodyTags) - reporter.warning(pos, "Tag '@" + key.name + "' is not recognised") + reporter.warning(pos, s"Tag '@${key.name}' is not recognised") com @@ -424,7 +422,7 @@ trait CommentFactoryBase { this: MemberLookupBase => /* BLOCKS */ - /** {{{ block ::= code | title | hrule | para }}} */ + /** {{{ block ::= code | title | hrule | listBlock | para }}} */ def block(): Block = { if (checkSkipInitWhitespace("{{{")) code() @@ -459,7 +457,7 @@ trait CommentFactoryBase { this: MemberLookupBase => * nLine ::= nSpc listStyle para '\n' * }}} * Where n and m stand for the number of spaces. When `m > n`, a new list is nested. */ - def listBlock: Block = { + def listBlock(): Block = { /** Consumes one list item block and returns it, or None if the block is * not a list or a different list. */ |