Skip to content

Commit d8b6169

Browse files
Merge pull request #9859 from dotty-staging/fix-#9746
Fix #9746: Require `then` in new conditional syntax
2 parents 28f4d90 + 1c02510 commit d8b6169

File tree

10 files changed

+52
-63
lines changed

10 files changed

+52
-63
lines changed

community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ class CommunityBuildTest:
375375
@Test def betterfiles = projects.betterfiles.run()
376376
@Test def catsEffect2 = projects.catsEffect2.run()
377377
@Test def catsEffect3 = projects.catsEffect3.run()
378-
@Test def dottyCpsAsync = projects.dottyCpsAsync.run()
378+
// Temporarily disabled until problem discovered in comments to #9449 is fixed
379+
// @Test def dottyCpsAsync = projects.dottyCpsAsync.run()
379380
@Test def effpi = projects.effpi.run()
380381
@Test def endpoints4s = projects.endpoints4s.run()
381382
@Test def fastparse = projects.fastparse.run()

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,6 @@ object Parsers {
357357
offset
358358
}
359359

360-
def reportMissing(expected: Token): Unit =
361-
syntaxError(ExpectedTokenButFound(expected, in.token))
362-
363360
/** semi = nl {nl} | `;'
364361
* nl = `\n' // where allowed
365362
*/
@@ -1825,7 +1822,7 @@ object Parsers {
18251822
* the initially parsed (...) region?
18261823
*/
18271824
def toBeContinued(altToken: Token): Boolean =
1828-
if in.token == altToken || in.isNewLine || migrateTo3 then
1825+
if in.isNewLine || migrateTo3 then
18291826
false // a newline token means the expression is finished
18301827
else if !in.canStartStatTokens.contains(in.token)
18311828
|| in.isLeadingInfixOperator(inConditional = true)
@@ -1835,37 +1832,27 @@ object Parsers {
18351832
followedByToken(altToken) // scan ahead to see whether we find a `then` or `do`
18361833

18371834
def condExpr(altToken: Token): Tree =
1838-
if in.token == LPAREN then
1839-
var t: Tree = atSpan(in.offset) { Parens(inParens(exprInParens())) }
1840-
val enclosedInParens = !toBeContinued(altToken)
1841-
if !enclosedInParens then
1842-
t = inSepRegion(InCond) {
1843-
expr1Rest(postfixExprRest(simpleExprRest(t)), Location.ElseWhere)
1844-
}
1845-
if in.token == altToken then
1846-
if rewriteToOldSyntax() then revertToParens(t)
1847-
in.nextToken()
1835+
val t: Tree =
1836+
if in.token == LPAREN then
1837+
var t: Tree = atSpan(in.offset) { Parens(inParens(exprInParens())) }
1838+
if in.token != altToken then
1839+
if toBeContinued(altToken) then
1840+
t = inSepRegion(InCond) {
1841+
expr1Rest(postfixExprRest(simpleExprRest(t)), Location.ElseWhere)
1842+
}
1843+
else
1844+
if rewriteToNewSyntax(t.span) then
1845+
dropParensOrBraces(t.span.start, s"${tokenString(altToken)}")
1846+
in.observeIndented()
1847+
return t
1848+
t
1849+
else if in.isNestedStart then
1850+
try expr() finally newLinesOpt()
18481851
else
1849-
if (altToken == THEN || enclosedInParens) && in.isNewLine then
1850-
in.observeIndented()
1851-
if !enclosedInParens && in.token != INDENT then reportMissing(altToken)
1852-
if (rewriteToNewSyntax(t.span))
1853-
dropParensOrBraces(t.span.start, s"${tokenString(altToken)}")
1854-
t
1855-
else
1856-
val t =
1857-
if in.isNestedStart then
1858-
try expr() finally newLinesOpt()
1859-
else
1860-
inSepRegion(InCond)(expr())
1861-
if rewriteToOldSyntax(t.span.startPos) then
1862-
revertToParens(t)
1863-
if altToken == THEN && in.isNewLine then
1864-
// don't require a `then` at the end of a line
1865-
in.observeIndented()
1866-
if in.token != INDENT then accept(altToken)
1867-
t
1868-
end condExpr
1852+
inSepRegion(InCond)(expr())
1853+
if rewriteToOldSyntax(t.span.startPos) then revertToParens(t)
1854+
accept(altToken)
1855+
t
18691856

18701857
/** Expr ::= [`implicit'] FunParams (‘=>’ | ‘?=>’) Expr
18711858
* | Expr1

compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ class ExtractSemanticDB extends Phase:
546546

547547
extension (sym: Symbol):
548548
private def adjustIfCtorTyparam(using Context) =
549-
if sym.isType && sym.owner.exists && sym.owner.isConstructor
549+
if sym.isType && sym.owner.exists && sym.owner.isConstructor then
550550
matchingMemberType(sym, sym.owner.owner)
551551
else
552552
sym
@@ -557,20 +557,20 @@ class ExtractSemanticDB extends Phase:
557557
/**Necessary because not all of the eventual flags are propagated from the Tree to the symbol yet.
558558
*/
559559
private def symbolKinds(tree: NamedDefTree)(using Context): Set[SymbolKind] =
560-
if tree.symbol.isSelfSym
560+
if tree.symbol.isSelfSym then
561561
Set.empty
562562
else
563563
val symkinds = mutable.HashSet.empty[SymbolKind]
564564
tree match
565565
case tree: ValDef =>
566-
if !tree.symbol.is(Param)
566+
if !tree.symbol.is(Param) then
567567
symkinds += (if tree.mods is Mutable then SymbolKind.Var else SymbolKind.Val)
568-
if tree.rhs.isEmpty && !tree.symbol.isOneOf(TermParam | CaseAccessor | ParamAccessor)
568+
if tree.rhs.isEmpty && !tree.symbol.isOneOf(TermParam | CaseAccessor | ParamAccessor) then
569569
symkinds += SymbolKind.Abstract
570570
case tree: DefDef =>
571-
if tree.isSetterDef
571+
if tree.isSetterDef then
572572
symkinds += SymbolKind.Setter
573-
else if tree.rhs.isEmpty
573+
else if tree.rhs.isEmpty then
574574
symkinds += SymbolKind.Abstract
575575
case tree: Bind =>
576576
symkinds += SymbolKind.Val
@@ -584,7 +584,7 @@ class ExtractSemanticDB extends Phase:
584584
vparams <- vparamss
585585
vparam <- vparams
586586
do
587-
if !excludeSymbol(vparam.symbol)
587+
if !excludeSymbol(vparam.symbol) then
588588
traverseAnnotsOfDefinition(vparam.symbol)
589589
val symkinds =
590590
getters.get(vparam.name).fold(SymbolKind.emptySet)(getter =>

compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ object Scala3:
5858
displaySymbol(symbol.owner)
5959
else if symbol.is(ModuleClass) then
6060
displaySymbol(symbol.sourceModule)
61-
else if symbol == defn.RootPackage
61+
else if symbol == defn.RootPackage then
6262
RootPackageName
63-
else if symbol.isEmptyPackage
63+
else if symbol.isEmptyPackage then
6464
EmptyPackageName
6565
else
6666
symbol.name.show
@@ -131,7 +131,7 @@ object Scala3:
131131
def unapply(symbolInfo: SymbolInformation): Option[Int] = symbolInfo.symbol match
132132
case locals(ints) =>
133133
val bi = BigInt(ints)
134-
if bi.isValidInt
134+
if bi.isValidInt then
135135
Some(bi.toInt)
136136
else
137137
None
@@ -242,14 +242,14 @@ object Scala3:
242242
while i < len do
243243
val a = o1.charAt(i)
244244
val b = o2.charAt(i)
245-
if a.isDigit && b.isDigit
245+
if a.isDigit && b.isDigit then
246246
val byDigit = Integer.compare(toDigit(o1, i), toDigit(o2, i))
247247
if (byDigit != 0) return byDigit
248248
else
249249
i = seekNonDigit(o1, i)
250250
else
251251
val result = Character.compare(a, b)
252-
if result != 0
252+
if result != 0 then
253253
return result
254254
i += 1
255255
end while

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ object Erasure {
647647
if defn.specialErasure.contains(owner) then
648648
assert(sym.isConstructor, s"${sym.showLocated}")
649649
defn.specialErasure(owner)
650-
else if defn.isSyntheticFunctionClass(owner)
650+
else if defn.isSyntheticFunctionClass(owner) then
651651
defn.erasedFunctionClass(owner)
652652
else
653653
owner

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1471,7 +1471,7 @@ trait Applications extends Compatibility {
14711471
case tp1: MethodType => // (1)
14721472
tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType]
14731473
|| {
1474-
if tp1.isVarArgsMethod
1474+
if tp1.isVarArgsMethod then
14751475
tp2.isVarArgsMethod
14761476
&& isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType)
14771477
else

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,7 @@ class Typer extends Namer
21462146
&& !cls.isAllOf(PrivateLocal)
21472147
&& effectiveOwner.is(Trait)
21482148
&& !effectiveOwner.derivesFrom(defn.ObjectClass)
2149+
then
21492150
report.error(i"$cls cannot be defined in universal $effectiveOwner", cdef.srcPos)
21502151

21512152
// Temporarily set the typed class def as root tree so that we have at least some

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class DottyLanguageServer extends LanguageServer
6565
private[this] var myDependentProjects: mutable.Map[ProjectConfig, mutable.Set[ProjectConfig]] = _
6666

6767
def drivers: Map[ProjectConfig, InteractiveDriver] = thisServer.synchronized {
68-
if myDrivers == null
68+
if myDrivers == null then
6969
assert(rootUri != null, "`drivers` cannot be called before `initialize`")
7070
val configFile = new File(new URI(rootUri + '/' + IDE_CONFIG_FILE))
7171
val configs: List[ProjectConfig] = (new ObjectMapper).readValue(configFile, classOf[Array[ProjectConfig]]).toList
@@ -102,12 +102,12 @@ class DottyLanguageServer extends LanguageServer
102102
System.gc()
103103
for ((_, driver, opened) <- driverConfigs; (uri, source) <- opened)
104104
driver.run(uri, source)
105-
if Memory.isCritical()
105+
if Memory.isCritical() then
106106
println(s"WARNING: Insufficient memory to run Scala language server on these projects.")
107107
}
108108

109109
private def checkMemory() =
110-
if Memory.isCritical()
110+
if Memory.isCritical() then
111111
CompletableFutures.computeAsync { _ => restart() }
112112

113113
/** The configuration of the project that owns `uri`. */
@@ -149,7 +149,7 @@ class DottyLanguageServer extends LanguageServer
149149

150150
/** A mapping from project `p` to the set of projects that transitively depend on `p`. */
151151
def dependentProjects: Map[ProjectConfig, Set[ProjectConfig]] = thisServer.synchronized {
152-
if myDependentProjects == null
152+
if myDependentProjects == null then
153153
val idToConfig = drivers.keys.map(k => k.id -> k).toMap
154154
val allProjects = drivers.keySet
155155

@@ -192,7 +192,7 @@ class DottyLanguageServer extends LanguageServer
192192
throw ex
193193
}
194194
}
195-
if synchronize
195+
if synchronize then
196196
thisServer.synchronized { computation() }
197197
else
198198
computation()
@@ -829,15 +829,15 @@ object DottyLanguageServer {
829829
def completionItemKind(sym: Symbol)(implicit ctx: Context): lsp4j.CompletionItemKind = {
830830
import lsp4j.{CompletionItemKind => CIK}
831831

832-
if sym.is(Package) || sym.is(Module)
832+
if sym.is(Package) || sym.is(Module) then
833833
CIK.Module // No CompletionItemKind.Package (https://github.com/Microsoft/language-server-protocol/issues/155)
834-
else if sym.isConstructor
834+
else if sym.isConstructor then
835835
CIK.Constructor
836-
else if sym.isClass
836+
else if sym.isClass then
837837
CIK.Class
838-
else if sym.is(Mutable)
838+
else if sym.is(Mutable) then
839839
CIK.Variable
840-
else if sym.is(Method)
840+
else if sym.is(Method) then
841841
CIK.Method
842842
else
843843
CIK.Field
@@ -861,7 +861,7 @@ object DottyLanguageServer {
861861
}
862862

863863
def markupContent(content: String): lsp4j.MarkupContent = {
864-
if content.isEmpty
864+
if content.isEmpty then
865865
null
866866
else {
867867
val markup = new lsp4j.MarkupContent

tests/neg/i8731.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ object test:
66
case _ => () // error: missing parameter type
77
end match
88

9-
if 3 == 3
9+
if 3 == 3 then
1010
()
1111
end if
1212
else // error: illegal start of definition

tests/pos/indent.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ object Test:
1919
println("world")
2020
33
2121
val y1 =
22-
if x > 0
22+
if x > 0 then
2323
1
2424
else
2525
2
2626
val y2 =
27-
if (y > 0) && y < 0
27+
if (y > 0) && y < 0 then
2828
1
2929
else
3030
2

0 commit comments

Comments
 (0)