diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser')
6 files changed, 186 insertions, 95 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index 52b8a51a79..46d533b037 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -12,7 +12,7 @@ import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable import scala.tools.nsc.util.CharArrayReader import scala.tools.nsc.ast.parser.xml.{MarkupParserCommon, Utility} -import scala.reflect.internal.Chars.{ SU, LF } +import scala.reflect.internal.Chars.SU // XXX/Note: many/most of the functions in here are almost direct cut and pastes // from another file - scala.xml.parsing.MarkupParser, it looks like. @@ -261,7 +261,7 @@ trait MarkupParsers { def coalesce(): ArrayBuffer[Tree] = { def copy() = { val buf = new ArrayBuffer[Tree] - var acc = new StringBuilder + val acc = new StringBuilder var pos: Position = NoPosition def emit() = if (acc.nonEmpty) { appendText(pos, buf, acc.toString) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 308669256d..0cdba861a5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -9,10 +9,9 @@ package scala.tools.nsc package ast.parser -import scala.collection.{ mutable, immutable } -import mutable.{ ListBuffer, StringBuilder } +import scala.collection.mutable +import mutable.ListBuffer import scala.reflect.internal.{ Precedence, ModifierFlags => Flags } -import scala.reflect.internal.Chars.{ isScalaLetter } import scala.reflect.internal.util.{ SourceFile, Position, FreshNameCreator, ListOfNil } import Tokens._ @@ -40,7 +39,7 @@ trait ParsersCommon extends ScannersCommon { self => */ abstract class ParserCommon { val in: ScannerCommon - def deprecationWarning(off: Offset, msg: String): Unit + def deprecationWarning(off: Offset, msg: String, since: String): Unit def accept(token: Token): Int /** Methods inParensOrError and similar take a second argument which, should @@ -155,7 +154,7 @@ self => // suppress warnings; silent abort on errors def warning(offset: Offset, msg: String): Unit = () - def deprecationWarning(offset: Offset, msg: String): Unit = () + def deprecationWarning(offset: Offset, msg: String, since: String): Unit = () def syntaxError(offset: Offset, msg: String): Unit = throw new MalformedInput(offset, msg) def incompleteInputError(msg: String): Unit = throw new MalformedInput(source.content.length - 1, msg) @@ -207,8 +206,8 @@ self => override def warning(offset: Offset, msg: String): Unit = reporter.warning(o2p(offset), msg) - override def deprecationWarning(offset: Offset, msg: String): Unit = - currentRun.reporting.deprecationWarning(o2p(offset), msg) + override def deprecationWarning(offset: Offset, msg: String, since: String): Unit = + currentRun.reporting.deprecationWarning(o2p(offset), msg, since) private var smartParsing = false @inline private def withSmartParsing[T](body: => T): T = { @@ -685,6 +684,15 @@ self => } def isLiteral = isLiteralToken(in.token) + def isSimpleExprIntroToken(token: Token): Boolean = isLiteralToken(token) || (token match { + case IDENTIFIER | BACKQUOTED_IDENT | + THIS | SUPER | NEW | USCORE | + LPAREN | LBRACE | XMLSTART => true + case _ => false + }) + + def isSimpleExprIntro: Boolean = isExprIntroToken(in.token) + def isExprIntroToken(token: Token): Boolean = isLiteralToken(token) || (token match { case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE | @@ -1255,8 +1263,8 @@ self => case CHARLIT => in.charVal case INTLIT => in.intVal(isNegated).toInt case LONGLIT => in.intVal(isNegated) - case FLOATLIT => in.floatVal(isNegated).toFloat - case DOUBLELIT => in.floatVal(isNegated) + case FLOATLIT => in.floatVal(isNegated) + case DOUBLELIT => in.doubleVal(isNegated) case STRINGLIT | STRINGPART => in.strVal.intern() case TRUE => true case FALSE => false @@ -1636,11 +1644,14 @@ self => def prefixExpr(): Tree = { if (isUnaryOp) { atPos(in.offset) { - val name = nme.toUnaryName(rawIdent().toTermName) - if (name == nme.UNARY_- && isNumericLit) - simpleExprRest(literal(isNegated = true), canApply = true) - else - Select(stripParens(simpleExpr()), name) + if (lookingAhead(isSimpleExprIntro)) { + val uname = nme.toUnaryName(rawIdent().toTermName) + if (uname == nme.UNARY_- && isNumericLit) + simpleExprRest(literal(isNegated = true), canApply = true) + else + Select(stripParens(simpleExpr()), uname) + } + else simpleExpr() } } else simpleExpr() @@ -1722,9 +1733,7 @@ self => } simpleExprRest(app, canApply = true) case USCORE => - atPos(t.pos.start, in.skipToken()) { - Typed(stripParens(t), Function(Nil, EmptyTree)) - } + atPos(t.pos.start, in.skipToken()) { makeMethodValue(stripParens(t)) } case _ => t } @@ -1833,7 +1842,7 @@ self => val hasEq = in.token == EQUALS if (hasVal) { - if (hasEq) deprecationWarning(in.offset, "val keyword in for comprehension is deprecated") + if (hasEq) deprecationWarning(in.offset, "val keyword in for comprehension is deprecated", "2.10.0") else syntaxError(in.offset, "val in for comprehension must be followed by assignment") } @@ -1912,19 +1921,20 @@ self => } /** {{{ - * Pattern1 ::= varid `:' TypePat + * Pattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | Pattern2 - * SeqPattern1 ::= varid `:' TypePat + * SeqPattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | [SeqPattern2] * }}} */ def pattern1(): Tree = pattern2() match { case p @ Ident(name) if in.token == COLON => - if (treeInfo.isVarPattern(p)) + if (nme.isVariableName(name)) { + p.removeAttachment[BackquotedIdentifierAttachment.type] atPos(p.pos.start, in.skipToken())(Typed(p, compoundType())) - else { + } else { syntaxError(in.offset, "Pattern variables must start with a lower-case letter. (SLS 8.1.1.)") p } @@ -1932,10 +1942,9 @@ self => } /** {{{ - * Pattern2 ::= varid [ @ Pattern3 ] + * Pattern2 ::= id @ Pattern3 + * | `_' @ Pattern3 * | Pattern3 - * SeqPattern2 ::= varid [ @ SeqPattern3 ] - * | SeqPattern3 * }}} */ def pattern2(): Tree = { @@ -1946,7 +1955,7 @@ self => case Ident(nme.WILDCARD) => in.nextToken() pattern3() - case Ident(name) if treeInfo.isVarPattern(p) => + case Ident(name) => in.nextToken() atPos(p.pos.start) { Bind(name, pattern3()) } case _ => p @@ -1975,8 +1984,8 @@ self => case _ => EmptyTree } def loop(top: Tree): Tree = reducePatternStack(base, top) match { - case next if isIdentExcept(raw.BAR) => pushOpInfo(next) ; loop(simplePattern(badPattern3)) - case next => next + case next if isIdent && !isRawBar => pushOpInfo(next) ; loop(simplePattern(badPattern3)) + case next => next } checkWildStar orElse stripParens(loop(top)) } @@ -2227,31 +2236,57 @@ self => * }}} */ def paramClauses(owner: Name, contextBounds: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = { - var implicitmod = 0 - var caseParam = ofCaseClass - def paramClause(): List[ValDef] = { - if (in.token == RPAREN) - return Nil - - if (in.token == IMPLICIT) { - in.nextToken() - implicitmod = Flags.IMPLICIT - } - commaSeparated(param(owner, implicitmod, caseParam )) - } - val vds = new ListBuffer[List[ValDef]] + var implicitSection = -1 + var implicitOffset = -1 + var warnAt = -1 + var caseParam = ofCaseClass + val vds = new ListBuffer[List[ValDef]] val start = in.offset + def paramClause(): List[ValDef] = if (in.token == RPAREN) Nil else { + val implicitmod = + if (in.token == IMPLICIT) { + if (implicitOffset == -1) { implicitOffset = in.offset ; implicitSection = vds.length } + else if (warnAt == -1) warnAt = in.offset + in.nextToken() + Flags.IMPLICIT + } else 0 + commaSeparated(param(owner, implicitmod, caseParam)) + } newLineOptWhenFollowedBy(LPAREN) - if (ofCaseClass && in.token != LPAREN) - syntaxError(in.lastOffset, "case classes without a parameter list are not allowed;\n"+ - "use either case objects or case classes with an explicit `()' as a parameter list.") - while (implicitmod == 0 && in.token == LPAREN) { + while (in.token == LPAREN) { in.nextToken() vds += paramClause() accept(RPAREN) caseParam = false newLineOptWhenFollowedBy(LPAREN) } + if (ofCaseClass) { + if (vds.isEmpty) + syntaxError(start, s"case classes must have a parameter list; try 'case class ${owner.encoded + }()' or 'case object ${owner.encoded}'") + else if (vds.head.nonEmpty && vds.head.head.mods.isImplicit) { + if (settings.isScala213) + syntaxError(start, s"case classes must have a non-implicit parameter list; try 'case class ${ + owner.encoded}()${ vds.map(vs => "(...)").mkString }'") + else { + deprecationWarning(start, s"case classes should have a non-implicit parameter list; adapting to 'case class ${ + owner.encoded}()${ vds.map(vs => "(...)").mkString }'", "2.12.2") + vds.insert(0, List.empty[ValDef]) + vds(1) = vds(1).map(vd => copyValDef(vd)(mods = vd.mods & ~Flags.CASEACCESSOR)) + if (implicitSection != -1) implicitSection += 1 + } + } + } + if (implicitSection != -1 && implicitSection != vds.length - 1) + syntaxError(implicitOffset, "an implicit parameter section must be last") + if (warnAt != -1) + syntaxError(warnAt, "multiple implicit parameter sections are not allowed") + else if (settings.warnExtraImplicit) { + // guard against anomalous class C(private implicit val x: Int)(implicit s: String) + val ttl = vds.count { case ValDef(mods, _, _, _) :: _ => mods.isImplicit ; case _ => false } + if (ttl > 1) + warning(in.offset, s"$ttl parameter sections are effectively implicit") + } val result = vds.toList if (owner == nme.CONSTRUCTOR && (result.isEmpty || (result.head take 1 exists (_.mods.isImplicit)))) { in.token match { @@ -2369,7 +2404,7 @@ self => while (in.token == VIEWBOUND) { val msg = "Use an implicit parameter instead.\nExample: Instead of `def f[A <% Int](a: A)` use `def f[A](a: A)(implicit ev: A => Int)`." if (settings.future) - deprecationWarning(in.offset, s"View bounds are deprecated. $msg") + deprecationWarning(in.offset, s"View bounds are deprecated. $msg", "2.12.0") contextBoundBuf += atPos(in.skipToken())(makeFunctionTypeTree(List(Ident(pname)), typ())) } while (in.token == COLON) { @@ -2663,14 +2698,14 @@ self => if (isStatSep || in.token == RBRACE) { if (restype.isEmpty) { if (settings.future) - deprecationWarning(in.lastOffset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit`.") + deprecationWarning(in.lastOffset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit`.", "2.12.0") restype = scalaUnitConstr } newmods |= Flags.DEFERRED EmptyTree } else if (restype.isEmpty && in.token == LBRACE) { if (settings.future) - deprecationWarning(in.offset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit =`.") + deprecationWarning(in.offset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit =`.", "2.12.0") restype = scalaUnitConstr blockExpr() } else { @@ -2820,11 +2855,6 @@ self => if (mods.isTrait) (Modifiers(Flags.TRAIT), List()) else (accessModifierOpt(), paramClauses(name, classContextBounds, ofCaseClass = mods.isCase)) var mods1 = mods - if (mods.isTrait) { - if (settings.YvirtClasses && in.token == SUBTYPE) mods1 |= Flags.DEFERRED - } else if (in.token == SUBTYPE) { - syntaxError("classes are not allowed to be virtual", skipIt = false) - } val template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss, tstart) val result = gen.mkClassDef(mods1, name, tparams, template) // Context bounds generate implicit parameters (part of the template) with types @@ -2937,7 +2967,7 @@ self => case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => copyValDef(vdef)(mods = mods | Flags.PRESUPER) case tdef @ TypeDef(mods, name, tparams, rhs) => - deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.") + deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.", "2.11.0") treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs) case docdef @ DocDef(comm, rhs) => treeCopy.DocDef(docdef, comm, rhs) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index cd41c75298..3ed1570c1c 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -10,7 +10,7 @@ import scala.reflect.internal.util._ import scala.reflect.internal.Chars._ import Tokens._ import scala.annotation.{ switch, tailrec } -import scala.collection.{ mutable, immutable } +import scala.collection.mutable import mutable.{ ListBuffer, ArrayBuffer } import scala.tools.nsc.ast.parser.xml.Utility.isNameStart import scala.language.postfixOps @@ -35,7 +35,28 @@ trait ScannersCommon { // things to fill in, in addition to buf, decodeUni which come from CharArrayReader def error(off: Offset, msg: String): Unit def incompleteInputError(off: Offset, msg: String): Unit - def deprecationWarning(off: Offset, msg: String): Unit + def deprecationWarning(off: Offset, msg: String, since: String): Unit + } + + // Hooks for ScaladocUnitScanner and ScaladocJavaUnitScanner + trait DocScanner { + protected def beginDocComment(prefix: String): Unit = {} + protected def processCommentChar(): Unit = {} + protected def finishDocComment(): Unit = {} + + private var lastDoc: DocComment = null + // get last doc comment + def flushDoc(): DocComment = try lastDoc finally lastDoc = null + def registerDocComment(raw: String, pos: Position) = { + lastDoc = DocComment(raw, pos) + signalParsedDocComment(raw, pos) + } + + /** To prevent doc comments attached to expressions from leaking out of scope + * onto the next documentable entity, they are discarded upon passing a right + * brace, bracket, or parenthesis. + */ + def discardDocBuffer(): Unit = {} } def createKeywordArray(keywords: Seq[(Name, Token)], defaultToken: Token): (Token, Array[Token]) = { @@ -103,11 +124,11 @@ trait Scanners extends ScannersCommon { } } - abstract class Scanner extends CharArrayReader with TokenData with ScannerData with ScannerCommon { + abstract class Scanner extends CharArrayReader with TokenData with ScannerData with ScannerCommon with DocScanner { private def isDigit(c: Char) = java.lang.Character isDigit c private var openComments = 0 - protected def putCommentChar(): Unit = nextChar() + final protected def putCommentChar(): Unit = { processCommentChar(); nextChar() } @tailrec private def skipLineComment(): Unit = ch match { case SU | CR | LF => @@ -134,8 +155,6 @@ trait Scanners extends ScannersCommon { case SU => incompleteInputError("unclosed comment") case _ => putCommentChar() ; skipNestedComments() } - def skipDocComment(): Unit = skipNestedComments() - def skipBlockComment(): Unit = skipNestedComments() private def skipToCommentEnd(isLineComment: Boolean): Unit = { nextChar() @@ -147,27 +166,23 @@ trait Scanners extends ScannersCommon { // Check for the amazing corner case of /**/ if (ch == '/') nextChar() - else - skipDocComment() + else { + beginDocComment("/**") + skipNestedComments() + } } - else skipBlockComment() + else skipNestedComments() } } /** @pre ch == '/' * Returns true if a comment was skipped. */ - def skipComment(): Boolean = ch match { - case '/' | '*' => skipToCommentEnd(isLineComment = ch == '/') ; true + final def skipComment(): Boolean = ch match { + case '/' | '*' => skipToCommentEnd(isLineComment = ch == '/') ; finishDocComment(); true case _ => false } - def flushDoc(): DocComment = null - /** To prevent doc comments attached to expressions from leaking out of scope - * onto the next documentable entity, they are discarded upon passing a right - * brace, bracket, or parenthesis. - */ - def discardDocBuffer(): Unit = () def isAtEnd = charOffset >= buf.length @@ -208,7 +223,7 @@ trait Scanners extends ScannersCommon { if (name == nme.MACROkw) syntaxError(s"$name is now a reserved word; usage as an identifier is disallowed") else if (emitIdentifierDeprecationWarnings) - deprecationWarning(s"$name is now a reserved word; usage as an identifier is deprecated") + deprecationWarning(s"$name is a reserved word (since 2.10.0); usage as an identifier is deprecated", "2.10.0") } } } @@ -246,6 +261,14 @@ trait Scanners extends ScannersCommon { private def inMultiLineInterpolation = inStringInterpolation && sepRegions.tail.nonEmpty && sepRegions.tail.head == STRINGPART + /** Are we in a `${ }` block? such that RBRACE exits back into multiline string. */ + private def inMultiLineInterpolatedExpression = { + sepRegions match { + case RBRACE :: STRINGLIT :: STRINGPART :: rest => true + case _ => false + } + } + /** read next token and return last offset */ def skipToken(): Offset = { @@ -312,7 +335,7 @@ trait Scanners extends ScannersCommon { lastOffset -= 1 } if (inStringInterpolation) fetchStringPart() else fetchToken() - if(token == ERROR) { + if (token == ERROR) { if (inMultiLineInterpolation) sepRegions = sepRegions.tail.tail else if (inStringInterpolation) @@ -363,6 +386,17 @@ trait Scanners extends ScannersCommon { next copyFrom this this copyFrom prev } + } else if (token == COMMA) { + // SIP-27 Trailing Comma (multi-line only) support + // If a comma is followed by a new line & then a closing paren, bracket or brace + // then it is a trailing comma and is ignored + val saved = new ScannerData {} copyFrom this + fetchToken() + if (afterLineEnd() && (token == RPAREN || token == RBRACKET || token == RBRACE)) { + /* skip the trailing comma */ + } else if (token == EOF) { // e.g. when the REPL is parsing "val List(x, y, _*," + /* skip the trailing comma */ + } else this copyFrom saved } // print("["+this+"]") @@ -515,7 +549,7 @@ trait Scanners extends ScannersCommon { charLitOr(getIdentRest) else if (isOperatorPart(ch) && (ch != '\\')) charLitOr(getOperatorRest) - else { + else if (!isAtEnd && (ch != SU && ch != CR && ch != LF || isUnicodeEscape)) { getLitChar() if (ch == '\'') { nextChar() @@ -525,6 +559,8 @@ trait Scanners extends ScannersCommon { syntaxError("unclosed character literal") } } + else + syntaxError("unclosed character literal") } fetchSingleQuote() case '.' => @@ -545,7 +581,8 @@ trait Scanners extends ScannersCommon { case ')' => nextChar(); token = RPAREN case '}' => - nextChar(); token = RBRACE + if (inMultiLineInterpolatedExpression) nextRawChar() else nextChar() + token = RBRACE case '[' => nextChar(); token = LBRACKET case ']' => @@ -690,7 +727,7 @@ trait Scanners extends ScannersCommon { private def unclosedStringLit(): Unit = syntaxError("unclosed string literal") - private def getRawStringLit(): Unit = { + @tailrec private def getRawStringLit(): Unit = { if (ch == '\"') { nextRawChar() if (isTripleQuote()) { @@ -707,7 +744,7 @@ trait Scanners extends ScannersCommon { } } - @scala.annotation.tailrec private def getStringPart(multiLine: Boolean): Unit = { + @tailrec private def getStringPart(multiLine: Boolean): Unit = { def finishStringPart() = { setStrVal() token = STRINGPART @@ -822,7 +859,7 @@ trait Scanners extends ScannersCommon { if (settings.future) syntaxError(start, msg("unsupported")) else - deprecationWarning(start, msg("deprecated")) + deprecationWarning(start, msg("deprecated"), "2.11.0") putChar(oct.toChar) } else { ch match { @@ -946,23 +983,45 @@ trait Scanners extends ScannersCommon { def intVal: Long = intVal(negated = false) - /** Convert current strVal, base to double value + private val zeroFloat = raw"[0.]+(?:[eE][+-]?[0-9]+)?[fFdD]?".r + + /** Convert current strVal, base to float value. */ - def floatVal(negated: Boolean): Double = { - val limit: Double = if (token == DOUBLELIT) Double.MaxValue else Float.MaxValue + def floatVal(negated: Boolean): Float = { try { - val value: Double = java.lang.Double.valueOf(strVal).doubleValue() - if (value > limit) + val value: Float = java.lang.Float.parseFloat(strVal) + if (value > Float.MaxValue) syntaxError("floating point number too large") + if (value == 0.0f && !zeroFloat.pattern.matcher(strVal).matches) + syntaxError("floating point number too small") if (negated) -value else value } catch { case _: NumberFormatException => syntaxError("malformed floating point number") + 0.0f + } + } + + def floatVal: Float = floatVal(negated = false) + + /** Convert current strVal, base to double value. + */ + def doubleVal(negated: Boolean): Double = { + try { + val value: Double = java.lang.Double.parseDouble(strVal) + if (value > Double.MaxValue) + syntaxError("double precision floating point number too large") + if (value == 0.0d && !zeroFloat.pattern.matcher(strVal).matches) + syntaxError("double precision floating point number too small") + if (negated) -value else value + } catch { + case _: NumberFormatException => + syntaxError("malformed double precision floating point number") 0.0 } } - def floatVal: Double = floatVal(negated = false) + def doubleVal: Double = doubleVal(negated = false) def checkNoLetter(): Unit = { if (isIdentifierPart(ch) && ch >= ' ') @@ -1032,7 +1091,7 @@ trait Scanners extends ScannersCommon { /** generate an error at the current token offset */ def syntaxError(msg: String): Unit = syntaxError(offset, msg) - def deprecationWarning(msg: String): Unit = deprecationWarning(offset, msg) + def deprecationWarning(msg: String, since: String): Unit = deprecationWarning(offset, msg, since) /** signal an error where the input ended in the middle of a token */ def incompleteInputError(msg: String): Unit = { @@ -1202,8 +1261,8 @@ trait Scanners extends ScannersCommon { override val decodeUni: Boolean = !settings.nouescape // suppress warnings, throw exception on errors - def deprecationWarning(off: Offset, msg: String): Unit = () - def error (off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) + def deprecationWarning(off: Offset, msg: String, since: String): Unit = () + def error(off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) def incompleteInputError(off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) } @@ -1212,9 +1271,9 @@ trait Scanners extends ScannersCommon { class UnitScanner(val unit: CompilationUnit, patches: List[BracePatch]) extends SourceFileScanner(unit.source) { def this(unit: CompilationUnit) = this(unit, List()) - override def deprecationWarning(off: Offset, msg: String) = currentRun.reporting.deprecationWarning(unit.position(off), msg) - override def error (off: Offset, msg: String) = reporter.error(unit.position(off), msg) - override def incompleteInputError(off: Offset, msg: String) = currentRun.parsing.incompleteInputError(unit.position(off), msg) + override def deprecationWarning(off: Offset, msg: String, since: String) = currentRun.reporting.deprecationWarning(unit.position(off), msg, since) + override def error(off: Offset, msg: String) = reporter.error(unit.position(off), msg) + override def incompleteInputError(off: Offset, msg: String) = currentRun.parsing.incompleteInputError(unit.position(off), msg) private var bracePatches: List[BracePatch] = patches diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index 67241ef639..c3c3ee9d47 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package ast.parser -import scala.collection.{ mutable, immutable } +import scala.collection.mutable import symtab.Flags.MUTABLE import scala.reflect.internal.util.ListOfNil import scala.reflect.internal.util.StringOps.splitWhere diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala index df2073785b..e0667b5a3e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala @@ -82,7 +82,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse } private def initialUnitBody(unit: CompilationUnit): Tree = { - if (unit.isJava) new JavaUnitParser(unit).parse() + if (unit.isJava) newJavaUnitParser(unit).parse() else if (currentRun.parsing.incompleteHandled) newUnitParser(unit).parse() else newUnitParser(unit).smartParse() } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 45f731686a..7866fcf2dc 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package ast.parser import symtab.Flags._ -import scala.collection.mutable.ListBuffer import scala.reflect.internal.util.{Position, SourceFile, FreshNameCreator} /** Methods for building trees, used in the parser. All the trees @@ -36,6 +35,9 @@ abstract class TreeBuilder { def repeatedApplication(tpe: Tree): Tree = AppliedTypeTree(rootScalaDot(tpnme.REPEATED_PARAM_CLASS_NAME), List(tpe)) + // represents `expr _`, as specified in Method Values of spec/06-expressions.md + def makeMethodValue(expr: Tree): Tree = Typed(expr, Function(Nil, EmptyTree)) + def makeImportSelector(name: Name, nameOffset: Int): ImportSelector = ImportSelector(name, nameOffset, name, nameOffset) |