@@ -533,11 +533,11 @@ object Parsers:
533533 def inBrackets [T ](body : => T ): T = enclosed(LBRACKET , body)
534534
535535 def inBracesOrIndented [T ](body : => T , inStatSeq : Boolean = false , rewriteWithColon : Boolean = false ): T =
536- val followsArrow = in.last.token == ARROW
537536 if in.token == INDENT then
538537 // braces are always optional after `=>` so none should be inserted
539- val rewriteToBraces = in.rewriteNoIndent && ! followsArrow
540- val rewriteToIndent = in.rewriteToIndent && ! followsArrow
538+ val afterArrow = testChars(in.lastOffset - 3 , " =>" )
539+ val rewriteToBraces = in.rewriteNoIndent && ! afterArrow
540+ val rewriteToIndent = in.rewriteToIndent && ! afterArrow
541541 if rewriteToBraces then indentedToBraces(body)
542542 else if rewriteToIndent then enclosed(INDENT , toIndentedRegion(body))
543543 else enclosed(INDENT , body)
@@ -614,6 +614,11 @@ object Parsers:
614614/* -------- REWRITES ----------------------------------------------------------- */
615615
616616 object IndentRewriteState :
617+ assert(in.rewriteToIndent)
618+
619+ /** A copy of the previous token */
620+ var prev : TokenData = Scanners .newTokenData
621+
617622 /** The last offset where a colon at the end of line would be required if a subsequent { ... }
618623 * block would be converted to an indentation region. */
619624 var possibleColonOffset : Int = - 1
@@ -705,8 +710,8 @@ object Parsers:
705710 val (start, end) = blankLinesAround(offset, offset + 1 )
706711 if testChar(end, Chars .LF ) then
707712 if testChar(start - 1 , Chars .LF ) then (start, end + 1 ) // skip the whole line
708- else (start, end) // skip the end of line
709- else (offset, end) // skip from last to end of token
713+ else (start, end) // skip from previous char to end of line
714+ else (offset, end) // skip from token to next char
710715
711716 /** Expand the current span to its surrounding blank space */
712717 def blankLinesAround (start : Offset , end : Offset ): (Offset , Offset ) =
@@ -720,18 +725,18 @@ object Parsers:
720725 * 4. there is at least one token between the braces
721726 * 5. the closing brace is also at the end of the line, or it is followed by one of
722727 * `then`, `else`, `do`, `catch`, `finally`, `yield`, or `match`.
723- * 6. the opening brace does not follow a closing `}`
728+ * 6. the opening brace does not follow a closing brace
724729 * 7. last token is not a leading operator
725730 * 8. not a block in a sequence of statements
726- * 9. cannot rewrite to colon after a NEWLINE, e.g.
731+ * 9. cannot rewrite if colon required after a NEWLINE, e.g.
727732 * true ||
728- * { // NEWLINE inserted between || and {
733+ * {
729734 * false
730735 * }
731736 */
732737 def bracesToIndented [T ](body : => T , inStatSeq : Boolean , rewriteWithColon : Boolean ): T =
733738 import IndentRewriteState .*
734- val lastSaved = in.last .saveCopy
739+ val prevSaved = prev .saveCopy
735740 val lastOffsetSaved = in.lastOffset
736741 val underColonSyntax = possibleColonOffset == in.lastOffset
737742 val colonRequired = rewriteWithColon || underColonSyntax
@@ -741,9 +746,10 @@ object Parsers:
741746 case r : InBraces => true
742747 case _ => false
743748 var canRewrite = isBracesOrIndented(in.currentRegion) && // test (1)
744- lastSaved.token != RBRACE && // test (6)
745- ! (lastSaved.isOperator && lastSaved.isAfterLineEnd) && // test (7)
746- ! inStatSeq // test (8)
749+ prevSaved.token != RBRACE && // test (6)
750+ ! (prevSaved.isOperator && prevSaved.isAfterLineEnd) && // test (7)
751+ ! inStatSeq && // test (8)
752+ (! colonRequired || ! in.isAfterLineEnd) // test (9)
747753 val t = enclosed(LBRACE , {
748754 if in.isAfterLineEnd && in.token != RBRACE then // test (2)(4)
749755 toIndentedRegion :
@@ -753,17 +759,16 @@ object Parsers:
753759 canRewrite = false
754760 body
755761 })
756- canRewrite &= (in.isAfterLineEnd || in.token == EOF || statCtdTokens.contains(in.token)) && // test (5)
757- (! colonRequired || ! lastSaved.isNewLine) // test (9)
762+ canRewrite &= (in.isAfterLineEnd || in.token == EOF || statCtdTokens.contains(in.token)) // test (5)
758763 if canRewrite && (! underColonSyntax || Feature .fewerBracesEnabled) then
759- val (startClosing, endClosing) = elimRegion(in.last.offset )
764+ val (startClosing, endClosing) = elimRegion(in.lastOffset - 1 )
760765 // patch over the added indentation to remove braces
761766 patchOver(source, Span (startOpening, endOpening), " " )
762767 patchOver(source, Span (startClosing, endClosing), " " )
763768 if colonRequired then
764- if lastSaved .token == IDENTIFIER && lastSaved .isOperator then
765- patch(Span (lastSaved .offset, lastSaved.offset + lastSaved.name.length ), s " ` ${lastSaved .name}`: " )
766- else if lastSaved .token == IDENTIFIER && lastSaved .name.last == '_' then
769+ if prevSaved .token == IDENTIFIER && prevSaved .isOperator then
770+ patch(Span (prevSaved .offset, lastOffsetSaved ), s " ` ${prevSaved .name}`: " )
771+ else if prevSaved .token == IDENTIFIER && prevSaved .name.last == '_' then
767772 patch(Span (lastOffsetSaved), " :" )
768773 else patch(Span (lastOffsetSaved), " :" )
769774 else
@@ -816,7 +821,9 @@ object Parsers:
816821 maximumIndent = None
817822
818823 def nextToken (): Unit =
819- if in.rewriteToIndent then patchIndent()
824+ if in.rewriteToIndent then
825+ IndentRewriteState .prev = in.saveCopy
826+ patchIndent()
820827 in.nextToken()
821828
822829 def skipToken (): Offset =
@@ -838,7 +845,7 @@ object Parsers:
838845 val preFill = if (closingStartsLine || endStr.isEmpty) " " else " "
839846 val postFill = if (in.lastOffset == in.offset) " " else " "
840847 val (startClosing, endClosing) =
841- if (closingStartsLine && endStr.isEmpty) elimRegion(in.last.offset )
848+ if (closingStartsLine && endStr.isEmpty) elimRegion(in.lastOffset - 1 )
842849 else (in.lastOffset - 1 , in.lastOffset)
843850 patch(source, Span (startClosing, endClosing), s " $preFill$endStr$postFill" )
844851
@@ -1336,7 +1343,8 @@ object Parsers:
13361343 syntaxErrorOrIncomplete(em " indented definitions expected, ${in} found " )
13371344
13381345 def colonAtEOLOpt (): Unit =
1339- IndentRewriteState .possibleColonOffset = in.lastOffset
1346+ if in.rewriteToIndent then
1347+ IndentRewriteState .possibleColonOffset = in.lastOffset
13401348 in.observeColonEOL(inTemplate = false )
13411349 if in.token == COLONeol then
13421350 nextToken()
@@ -2062,7 +2070,7 @@ object Parsers:
20622070
20632071 def subExpr () = subPart(expr)
20642072
2065- def expr (location : Location , inStatSeq : Boolean = false ): Tree =
2073+ def expr (location : Location , inStatSeq : Boolean = false ): Tree = {
20662074 val start = in.offset
20672075 in.token match
20682076 case IMPLICIT =>
@@ -2385,7 +2393,7 @@ object Parsers:
23852393 * Quoted ::= ‘'’ ‘{’ Block ‘}’
23862394 * | ‘'’ ‘[’ Type ‘]’
23872395 */
2388- def simpleExpr (location : Location , inStatSeq : Boolean = false ): Tree =
2396+ def simpleExpr (location : Location , inStatSeq : Boolean = false ): Tree = {
23892397 var canApply = true
23902398 val t = in.token match
23912399 case XMLSTART =>
@@ -2557,12 +2565,13 @@ object Parsers:
25572565
25582566 /** BlockExpr ::= <<< (CaseClauses | Block) >>>
25592567 */
2560- def blockExpr (inStatSeq : Boolean = false ): Tree = atSpan(in.offset):
2568+ def blockExpr (inStatSeq : Boolean = false ): Tree = atSpan(in.offset) {
25612569 val simplify = in.token == INDENT
25622570 inDefScopeBraces({
25632571 if (in.token == CASE ) Match (EmptyTree , caseClauses(() => caseClause()))
25642572 else block(simplify)
25652573 }, inStatSeq = inStatSeq)
2574+ }
25662575
25672576 /** Block ::= BlockStatSeq
25682577 * @note Return tree does not have a defined span.
@@ -2731,7 +2740,7 @@ object Parsers:
27312740 rejectWildcardType(infixType())
27322741 CaseDef (pat, EmptyTree , atSpan(accept(ARROW )) {
27332742 val t = indentedRegionAfterArrow(rejectWildcardType(typ()), inCaseDef = true )
2734- if in.token == SEMI then nextToken()
2743+ if in.token == SEMI then in. nextToken()
27352744 newLinesOptWhenFollowedBy(CASE )
27362745 t
27372746 })
@@ -4181,7 +4190,7 @@ object Parsers:
41814190 def skipBracesHook (): Option [Tree ] =
41824191 if (in.token == XMLSTART ) Some (xmlLiteral()) else None
41834192
4184- override def blockExpr (inStatSeq : Boolean ): Tree =
4193+ override def blockExpr (inStatSeq : Boolean ): Tree = {
41854194 skipBraces()
41864195 EmptyTree
41874196
0 commit comments