From 81cda70db72046901e8ca5f8c958224cafdf1bf4 Mon Sep 17 00:00:00 2001 From: Enno Runne Date: Tue, 14 Feb 2017 21:16:47 +0100 Subject: Change '... expected but found ...' to Message --- .../src/dotty/tools/dotc/parsing/Parsers.scala | 14 +++----- compiler/src/dotty/tools/dotc/parsing/Tokens.scala | 4 ++- .../tools/dotc/reporting/diagnostic/Message.scala | 2 ++ .../tools/dotc/reporting/diagnostic/messages.scala | 37 ++++++++++++++++++++-- 4 files changed, 45 insertions(+), 12 deletions(-) (limited to 'compiler/src/dotty/tools') diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 9f4cdbd35..45ae842b6 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -110,7 +110,8 @@ object Parsers { */ def syntaxError(msg: => Message, offset: Int = in.offset): Unit = if (offset > lastErrorOffset) { - syntaxError(msg, Position(offset)) + val length = if (in.name != null) in.name.show.length else 0 + syntaxError(msg, Position(offset, offset + length)) lastErrorOffset = in.offset } @@ -249,11 +250,6 @@ object Parsers { lastErrorOffset = in.offset } // DEBUG - private def expectedMsg(token: Int): String = - expectedMessage(showToken(token)) - private def expectedMessage(what: String): String = - s"$what expected but ${showToken(in.token)} found" - /** Consume one token of the specified type, or * signal an error if it is not there. * @@ -262,7 +258,7 @@ object Parsers { def accept(token: Int): Int = { val offset = in.offset if (in.token != token) { - syntaxErrorOrIncomplete(expectedMsg(token)) + syntaxErrorOrIncomplete(ExpectedTokenButFound(token, in.token, in.name)) } if (in.token == token) in.nextToken() offset @@ -474,7 +470,7 @@ object Parsers { in.nextToken() name } else { - syntaxErrorOrIncomplete(expectedMsg(IDENTIFIER)) + syntaxErrorOrIncomplete(ExpectedTokenButFound(IDENTIFIER, in.token, in.name)) nme.ERROR } @@ -1055,7 +1051,7 @@ object Parsers { case Block(Nil, EmptyTree) => assert(handlerStart != -1) syntaxError( - new EmptyCatchBlock(body), + EmptyCatchBlock(body), Position(handlerStart, endOffset(handler)) ) case _ => diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 280832ef3..8d42e525a 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -17,7 +17,7 @@ abstract class TokensCommon { def showToken(token: Int) = { val str = tokenString(token) - if (keywords contains token) s"'$str'" else str + if (isKeyword(token)) s"'$str'" else str } val tokenString, debugString = new Array[String](maxToken + 1) @@ -114,6 +114,8 @@ abstract class TokensCommon { val keywords: TokenSet + def isKeyword(token: Token): Boolean = keywords contains token + /** parentheses */ final val LPAREN = 90; enter(LPAREN, "'('") final val RPAREN = 91; enter(RPAREN, "')'") diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala index 2497fb216..ab1222dab 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala @@ -119,6 +119,8 @@ class ExtendMessage(_msg: () => Message)(f: String => String) { self => class NoExplanation(val msg: String) extends Message(NoExplanation.ID) { val explanation = "" val kind = "" + + override def toString(): String = s"NoExplanation($msg)" } /** The extractor for `NoExplanation` can be used to check whether any error diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 4d61f21cf..94611e10d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -4,10 +4,17 @@ package reporting package diagnostic import dotc.core._ -import Contexts.Context, Decorators._, Symbols._, Names._, NameOps._, Types._ +import Contexts.Context +import Decorators._ +import Symbols._ +import Names._ +import NameOps._ +import Types._ import util.SourcePosition import config.Settings.Setting -import interfaces.Diagnostic.{ERROR, WARNING, INFO} +import interfaces.Diagnostic.{ERROR, INFO, WARNING} +import dotc.parsing.Scanners.Token +import dotc.parsing.Tokens import printing.Highlighting._ import printing.Formatting @@ -1053,4 +1060,30 @@ object messages { |""".stripMargin } + case class ExpectedTokenButFound(expected: Token, found: Token, foundName: TermName)(implicit ctx: Context) + extends Message(40) { + val kind = "Syntax" + + private val expectedText = + if (Tokens.isIdentifier(expected)) "an identifier" + else Tokens.showToken(expected) + + private val foundText = + if (foundName != null) hl"`${foundName.show}`" + else Tokens.showToken(found) + + val msg = hl"""${expectedText} expected, but ${foundText} found""" + + private val ifKeyword = + if (Tokens.isIdentifier(expected) && Tokens.isKeyword(found)) + s""" + |If you necessarily want to use $foundText as identifier, you may put it in backticks.""".stripMargin + else + "" + + val explanation = + s"""|The text ${foundText} may not occur at that position, the compiler expected ${expectedText}.$ifKeyword + |""".stripMargin + } + } -- cgit v1.2.3