Skip to content

Commit 012036b

Browse files
Merge pull request #8765 from dotty-staging/add-repl-indent
Fix #8762: Make REPL work with indented code
2 parents 755a81f + f5b10b6 commit 012036b

File tree

6 files changed

+24
-13
lines changed

6 files changed

+24
-13
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ node_modules
2626

2727
# VS Code
2828
.vscode/
29+
.metals/
2930

3031
# Scala-IDE specific
3132
.scala_dependencies

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ object Parsers {
12861286
if in.token == COLONEOL then
12871287
in.nextToken()
12881288
if in.token != INDENT then
1289-
syntaxError(i"indented definitions expected")
1289+
syntaxErrorOrIncomplete(i"indented definitions expected")
12901290
else
12911291
newLineOptWhenFollowedBy(LBRACE)
12921292

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ object Scanners {
530530
def observeColonEOL(): Unit =
531531
if token == COLON then
532532
lookahead()
533-
val atEOL = isAfterLineEnd
533+
val atEOL = isAfterLineEnd || token == EOF
534534
reset()
535535
if atEOL then token = COLONEOL
536536

@@ -567,6 +567,12 @@ object Scanners {
567567
this.copyFrom(prev)
568568
}
569569

570+
def closeIndented() = currentRegion match
571+
case r: Indented if !r.isOutermost =>
572+
insert(OUTDENT, offset)
573+
currentRegion = r.outer
574+
case _ =>
575+
570576
/** - Join CASE + CLASS => CASECLASS, CASE + OBJECT => CASEOBJECT, SEMI + ELSE => ELSE, COLON + <EOL> => COLONEOL
571577
* - Insert missing OUTDENTs at EOF
572578
*/
@@ -607,13 +613,10 @@ object Scanners {
607613
reset()
608614
case COLON =>
609615
if colonSyntax then observeColonEOL()
610-
case EOF | RBRACE | RPAREN | RBRACKET =>
611-
currentRegion match {
612-
case r: Indented if !r.isOutermost =>
613-
insert(OUTDENT, offset)
614-
currentRegion = r.outer
615-
case _ =>
616-
}
616+
case RBRACE | RPAREN | RBRACKET =>
617+
closeIndented()
618+
case EOF if !source.maybeIncomplete =>
619+
closeIndented()
617620
case _ =>
618621
}
619622
}

compiler/src/dotty/tools/dotc/util/SourceFile.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
4848
myContent
4949
}
5050

51+
private var _maybeInComplete: Boolean = false
52+
53+
def maybeIncomplete: Boolean = _maybeInComplete
54+
5155
def this(file: AbstractFile, codec: Codec) = this(file, new String(file.toByteArray, codec.charSet).toCharArray)
5256

5357
/** Tab increment; can be overridden */
@@ -200,7 +204,10 @@ object SourceFile {
200204

201205
def fromId(id: Int): SourceFile = sourceOfChunk(id >> ChunkSizeLog)
202206

203-
def virtual(name: String, content: String) = new SourceFile(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8)
207+
def virtual(name: String, content: String, maybeIncomplete: Boolean = false) =
208+
val src = new SourceFile(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8)
209+
src._maybeInComplete = maybeIncomplete
210+
src
204211

205212
private final val ChunkSizeLog = 10
206213
private final val ChunkSize = 1 << ChunkSizeLog

compiler/src/dotty/tools/repl/ParseResult.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ object ParseResult {
147147
}
148148

149149
def apply(sourceCode: String)(implicit state: State): ParseResult =
150-
apply(SourceFile.virtual(str.REPL_SESSION_LINE + (state.objectIndex + 1), sourceCode))
150+
apply(SourceFile.virtual(str.REPL_SESSION_LINE + (state.objectIndex + 1), sourceCode, maybeIncomplete = true))
151151

152152
/** Check if the input is incomplete.
153153
*
@@ -159,7 +159,7 @@ object ParseResult {
159159
case CommandExtract(_) | "" => false
160160
case _ => {
161161
val reporter = newStoreReporter
162-
val source = SourceFile.virtual("<incomplete-handler>", sourceCode)
162+
val source = SourceFile.virtual("<incomplete-handler>", sourceCode, maybeIncomplete = true)
163163
val unit = CompilationUnit(source, mustExist = false)
164164
val localCtx = ctx.fresh
165165
.setCompilationUnit(unit)

compiler/src/dotty/tools/repl/ReplDriver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class ReplDriver(settings: Array[String],
176176
compiler
177177
.typeCheck(expr, errorsAllowed = true)
178178
.map { tree =>
179-
val file = SourceFile.virtual("<completions>", expr)
179+
val file = SourceFile.virtual("<completions>", expr, maybeIncomplete = true)
180180
val unit = CompilationUnit(file)(state.context)
181181
unit.tpdTree = tree
182182
implicit val ctx = state.context.fresh.setCompilationUnit(unit)

0 commit comments

Comments
 (0)