Skip to content

Commit

Permalink
Have -new-syntax and -old-syntax options enforce syntax version
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Aug 12, 2019
1 parent 6d6180d commit 0657db9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class ScalaSettings extends Settings.SettingGroup {
val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.") withAbbreviation "--no-warnings"
val fromTasty: Setting[Boolean] = BooleanSetting("-from-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.") withAbbreviation "--from-tasty"

val newSyntax: Setting[Boolean] = BooleanSetting("-new-syntax", "When used with -rewrite, produces control expressions without parentheses")
val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "when used with -rewrite, produces control expressions with parentheses")
val newSyntax: Setting[Boolean] = BooleanSetting("-new-syntax", "Require `then` and `do` in control expressions")
val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "Require `(...)` around conditions")

/** Decompiler settings */
val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.") withAbbreviation "--print-tasty"
Expand Down
40 changes: 33 additions & 7 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,31 @@ object Parsers {
accept(SEMI)
}

def rewriteNotice(additionalOption: String = "") = {
val optionStr = if (additionalOption.isEmpty) "" else " " ++ additionalOption
i"\nThis construct can be rewritten automatically under$optionStr -rewrite."
}

def syntaxVersionError(option: String, span: Span) = {
syntaxError(em"""This construct is not allowed under $option.${rewriteNotice(option)}""", span)
}

def rewriteToNewSyntax(span: Span = Span(in.offset)): Boolean = {
if (in.newSyntax) {
if (in.rewrite) return true
syntaxVersionError("-new-syntax", span)
}
false
}

def rewriteToOldSyntax(span: Span = Span(in.offset)): Boolean = {
if (in.oldSyntax) {
if (in.rewrite) return true
syntaxVersionError("-old-syntax", span)
}
false
}

def errorTermTree: Literal = atSpan(in.offset) { Literal(Constant(null)) }

private[this] var inFunReturnType = false
Expand Down Expand Up @@ -1367,15 +1392,15 @@ object Parsers {
expr1Rest(postfixExprRest(simpleExprRest(t)), Location.ElseWhere)
}
if (in.token == altToken) {
if (in.rewriteOldSyntax) revertToParens(t)
if (rewriteToOldSyntax()) revertToParens(t)
in.nextToken()
}
else if (in.rewriteNewSyntax)
else if (rewriteToNewSyntax(t.span))
dropParensOrBraces(t.span.start, s"${tokenString(altToken)}")
t
} else {
val t = inSepRegion(LPAREN, RPAREN)(expr())
if (in.rewriteOldSyntax) revertToParens(t)
if (rewriteToOldSyntax(t.span.startPos)) revertToParens(t)
accept(altToken)
t
}
Expand Down Expand Up @@ -1469,7 +1494,7 @@ object Parsers {
in.errorOrMigrationWarning(
i"""`do <body> while <cond>' is no longer supported,
|use `while ({<body> ; <cond>}) ()' instead.
|The statement can be rewritten automatically under -language:Scala2 -rewrite.
|${rewriteNotice("-language:Scala2")}
""")
val start = in.skipToken()
atSpan(start) {
Expand Down Expand Up @@ -2009,7 +2034,8 @@ object Parsers {
val closingOnNewLine = in.isAfterLineEnd()
accept(leading + 1)
openParens.change(leading, -1)
if (in.rewriteNewSyntax && enumsOnNewLine == (leading == LBRACE)) { // Don't rewrite if that would change meaning of newlines
if (rewriteToNewSyntax(Span(start)) && enumsOnNewLine == (leading == LBRACE)) {
// Don't rewrite if that would change meaning of newlines
newLinesOpt()
dropParensOrBraces(start, if (in.token == YIELD || in.token == DO) "" else "do")
}
Expand All @@ -2024,7 +2050,7 @@ object Parsers {
val ts = // If we use indent syntax, the distinction below should no longer be necessary
if (impliedBraces) enumerators()
else inSepRegion(LPAREN, RPAREN)(enumerators())
if (in.rewriteOldSyntax && ts.nonEmpty) {
if (rewriteToOldSyntax(Span(start)) && ts.nonEmpty) {
if (impliedBraces) {
patch(source, Span(forEnd), " {")
patch(source, Span(in.offset), "} ")
Expand All @@ -2042,7 +2068,7 @@ object Parsers {
ForYield(enums, expr())
}
else if (in.token == DO) {
if (in.rewriteOldSyntax) dropTerminator()
if (rewriteToOldSyntax()) dropTerminator()
in.nextToken()
ForDo(enums, expr())
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ object Scanners {
val keepComments: Boolean = !ctx.settings.YdropComments.value

val rewrite = ctx.settings.rewrite.value.isDefined
val rewriteNewSyntax = rewrite && ctx.settings.newSyntax.value
val rewriteOldSyntax = rewrite && ctx.settings.oldSyntax.value
val oldSyntax = ctx.settings.oldSyntax.value
val newSyntax = ctx.settings.newSyntax.value

/** All doc comments kept by their end position in a `Map` */
private[this] var docstringMap: SortedMap[Int, Comment] = SortedMap.empty
Expand All @@ -237,7 +237,7 @@ object Scanners {
def nextPos: Int = (lookahead.getc(): @switch) match {
case ' ' | '\t' => nextPos
case CR | LF | FF =>
// if we encounter line delimitng whitespace we don't count it, since
// if we encounter line delimiting whitespace we don't count it, since
// it seems not to affect positions in source
nextPos - 1
case _ => lookahead.charOffset - 1
Expand Down

0 comments on commit 0657db9

Please sign in to comment.