@@ -349,43 +349,45 @@ object Parsers {
349349 if in.isNewLine then in.nextToken() else accept(SEMI )
350350
351351 /** Parse statement separators and end markers. Ensure that there is at least
352- * one statement separator unless the next token terminates a statement´ sequence.
353- * @param stats the statements parsed to far
352+ * one statement separator unless the next token terminates a statement sequence.
353+ * @param stats the statements parsed so far
354354 * @param noPrevStat true if there was no immediately preceding statement parsed
355355 * @param what a string indicating what kind of statement is parsed
356356 * @param altEnd a token that is also considered as a terminator of the statement
357- * sequence (the default `EOF` already assumes to terminate a statement
357+ * sequence (the default `EOF` is already assumed to terminate a statement
358358 * sequence).
359359 * @return true if the statement sequence continues, false if it terminates.
360360 */
361361 def statSepOrEnd [T <: Tree ](stats : ListBuffer [T ], noPrevStat : Boolean = false , what : String = " statement" , altEnd : Token = EOF ): Boolean =
362+ inline def stopping = false
363+ inline def continuing = true
362364 def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
363365 if isStatSep then
364366 in.nextToken()
365- recur(true , endSeen)
367+ recur(sepSeen = true , endSeen)
366368 else if in.token == END then
367369 if endSeen then syntaxError(em " duplicate end marker " )
368370 checkEndMarker(stats)
369371 recur(sepSeen, endSeen = true )
370372 else if isStatSeqEnd || in.token == altEnd then
371- false
373+ stopping
372374 else if sepSeen || endSeen then
373- true
375+ continuing
374376 else
375377 val found = in.token
376378 val statFollows = mustStartStatTokens.contains(found)
377379 syntaxError(
378380 if noPrevStat then IllegalStartOfStatement (what, isModifier, statFollows)
379381 else em " end of $what expected but ${showToken(found)} found " )
380- if mustStartStatTokens.contains(found) then
381- false // it's a statement that might be legal in an outer context
382+ if statFollows then
383+ stopping // it's a statement that might be legal in an outer context
382384 else
383385 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
384386 skip()
385- true
387+ continuing
386388
387389 in.observeOutdented()
388- recur(false , false )
390+ recur(sepSeen = false , endSeen = false )
389391 end statSepOrEnd
390392
391393 def rewriteNotice (version : SourceVersion = `3.0-migration`, additionalOption : String = " " ) =
@@ -1566,15 +1568,23 @@ object Parsers {
15661568 if MigrationVersion .Scala2to3 .needsPatch then
15671569 patch(source, Span (in.offset), " " )
15681570
1569- def possibleTemplateStart (isNew : Boolean = false ): Unit =
1571+ def possibleTemplateStart (): Unit =
1572+ possiblyNewTemplateStart(): Unit
1573+
1574+ /** Return true on trivial end */
1575+ def possiblyNewTemplateStart (): Boolean =
15701576 in.observeColonEOL(inTemplate = true )
15711577 if in.token == COLONeol then
1572- if in.lookahead.token == END then in.token = NEWLINE
1578+ if in.lookahead.token == END then
1579+ in.token = NEWLINE
1580+ true
15731581 else
15741582 in.nextToken()
15751583 if in.token != LBRACE then acceptIndent()
1584+ false
15761585 else
15771586 newLineOptWhenFollowedBy(LBRACE )
1587+ false
15781588
15791589 def checkEndMarker [T <: Tree ](stats : ListBuffer [T ]): Unit =
15801590
@@ -1599,6 +1609,10 @@ object Parsers {
15991609 case _ : ParsedTry => in.token == TRY
16001610 case _ : Match => in.token == MATCH
16011611 case _ : New => in.token == NEW
1612+ case _ : Apply =>
1613+ methPart(stat) match
1614+ case Select (_ : New , nme.CONSTRUCTOR ) => in.token == NEW
1615+ case _ => false
16021616 case _ : (ForYield | ForDo ) => in.token == FOR
16031617 case _ => false
16041618
@@ -2915,15 +2929,22 @@ object Parsers {
29152929 val parents =
29162930 if in.isNestedStart then Nil
29172931 else constrApps(exclude = COMMA )
2918- possibleTemplateStart(isNew = true )
2919- parents match {
2920- case parent :: Nil if ! in.isNestedStart =>
2921- reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent)
2922- case tkn if in.token == INDENT =>
2923- New (templateBodyOpt(emptyConstructor, parents, Nil ))
2924- case _ =>
2925- New (reposition(templateBodyOpt(emptyConstructor, parents, Nil )))
2926- }
2932+ val colonized = possiblyNewTemplateStart()
2933+ parents match
2934+ case parent :: Nil if ! in.isNestedStart =>
2935+ reposition :
2936+ if colonized then New (Template (emptyConstructor, parents, derived = Nil , self = EmptyValDef , body = Nil ))
2937+ else if parent.isType then ensureApplied(wrapNew(parent))
2938+ else parent
2939+ case parents =>
2940+ // With brace syntax, the last token consumed by a parser is }, but with indent syntax,
2941+ // the last token consumed by a parser is OUTDENT, which causes mismatching spans, so don't reposition.
2942+ val indented = in.token == INDENT
2943+ val body =
2944+ val bo = templateBodyOpt(emptyConstructor, parents, derived = Nil )
2945+ if ! indented then reposition(bo) else bo
2946+ New (body)
2947+ end newExpr
29272948
29282949 /** ExprsInParens ::= ExprInParens {`,' ExprInParens}
29292950 * | NamedExprInParens {‘,’ NamedExprInParens}
0 commit comments