Skip to content

Commit 1d0776a

Browse files
committed
Clean up SourceFile creation and error handling
1 parent 6f3fe05 commit 1d0776a

File tree

4 files changed

+18
-31
lines changed

4 files changed

+18
-31
lines changed

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
308308
def sourceFile(source: String, isJava: Boolean): SourceFile = {
309309
val uuid = java.util.UUID.randomUUID().toString
310310
val ext = if (isJava) ".java" else ".scala"
311-
val virtualFile = new VirtualFile(s"compileFromString-$uuid.$ext")
312-
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, StandardCharsets.UTF_8.nn.name)) // buffering is still advised by javadoc
313-
writer.write(source)
314-
writer.close()
315-
new SourceFile(virtualFile, Codec.UTF8)
311+
val name = s"compileFromString-$uuid.$ext"
312+
SourceFile.virtual(name, source)
316313
}
317314
val sources =
318315
scalaSources.map(sourceFile(_, isJava = false)) ++

compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,8 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
299299

300300
private def toSource(uri: URI, sourceCode: String): SourceFile = {
301301
val path = Paths.get(uri)
302-
val virtualFile = new VirtualFile(path.getFileName.toString, path.toString)
303-
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, StandardCharsets.UTF_8.name))
304-
writer.write(sourceCode)
305-
writer.close()
306-
new SourceFile(virtualFile, Codec.UTF8)
302+
val name = path.getFileName.toString // path.toString, no API for path
303+
SourceFile.virtual(name, sourceCode)
307304
}
308305

309306
/**

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

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import Chars._
1313
import scala.annotation.internal.sharable
1414
import scala.collection.mutable
1515
import scala.collection.mutable.ArrayBuffer
16+
import scala.util.chaining.given
1617

17-
import java.io.IOException
1818
import java.nio.charset.StandardCharsets
19+
import java.nio.file.{FileSystemException, NoSuchFileException}
1920
import java.util.Optional
2021
import java.util.concurrent.atomic.AtomicInteger
2122
import java.util.regex.Pattern
@@ -71,15 +72,6 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
7172

7273
def maybeIncomplete: Boolean = _maybeInComplete
7374

74-
def this(file: AbstractFile, codec: Codec) =
75-
// It would be cleaner to check if the file exists instead of catching
76-
// an exception, but it turns out that Files.exists is remarkably slow,
77-
// at least on Java 8 (https://rules.sonarsource.com/java/tag/performance/RSPEC-3725),
78-
// this is significant enough to show up in our benchmarks.
79-
this(file,
80-
try new String(file.toByteArray, codec.charSet).toCharArray
81-
catch case _: java.nio.file.NoSuchFileException => Array[Char]())
82-
8375
/** Tab increment; can be overridden */
8476
def tabInc: Int = 8
8577

@@ -226,9 +218,8 @@ object SourceFile {
226218
implicit def fromContext(using Context): SourceFile = ctx.source
227219

228220
def virtual(name: String, content: String, maybeIncomplete: Boolean = false) =
229-
val src = new SourceFile(new VirtualFile(name, content.getBytes(StandardCharsets.UTF_8)), scala.io.Codec.UTF8)
230-
src._maybeInComplete = maybeIncomplete
231-
src
221+
SourceFile(new VirtualFile(name, content.getBytes(StandardCharsets.UTF_8)), content.toCharArray)
222+
.tap(_._maybeInComplete = maybeIncomplete)
232223

233224
/** Returns the relative path of `source` within the `reference` path
234225
*
@@ -273,17 +264,20 @@ object SourceFile {
273264
ScriptSourceFile.hasScriptHeader(content)
274265

275266
def apply(file: AbstractFile | Null, codec: Codec): SourceFile =
276-
// see note above re: Files.exists is remarkably slow
267+
// Files.exists is slow on Java 8 (https://rules.sonarsource.com/java/tag/performance/RSPEC-3725),
268+
// so cope with failure; also deal with path prefix "Not a directory".
277269
val chars =
278-
try
279-
new String(file.toByteArray, codec.charSet).toCharArray
280-
catch
281-
case _: java.nio.file.NoSuchFileException => Array[Char]()
270+
try new String(file.toByteArray, codec.charSet).toCharArray
271+
catch
272+
case _: NoSuchFileException => Array.empty[Char]
273+
case fse: FileSystemException if fse.getMessage.endsWith("Not a directory") => Array.empty[Char]
282274

283275
if isScript(file, chars) then
284276
ScriptSourceFile(file, chars)
285277
else
286-
new SourceFile(file, chars)
278+
SourceFile(file, chars)
279+
280+
def apply(file: AbstractFile | Null, computeContent: => Array[Char]): SourceFile = new SourceFile(file, computeContent)
287281
}
288282

289283
@sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) {

scaladoc/src/dotty/tools/scaladoc/DocContext.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ def throwableToString(t: Throwable)(using CompilerContext): String =
4040

4141
private def sourcePostionFor(f: File)(using CompilerContext) =
4242
val relPath = relativePath(f.toPath)
43-
val virtualFile = new VirtualFile(relPath.toString, relPath.toString)
44-
val sourceFile = new SourceFile(virtualFile, Codec.UTF8)
43+
val sourceFile = SourceFile.virtual(relPath.toString, content = "")
4544
SourcePosition(sourceFile, Spans.NoSpan)
4645

4746
// TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling

0 commit comments

Comments
 (0)