@@ -13,9 +13,10 @@ import Chars._
1313import scala .annotation .internal .sharable
1414import scala .collection .mutable
1515import scala .collection .mutable .ArrayBuffer
16+ import scala .util .chaining .given
1617
17- import java .io .IOException
1818import java .nio .charset .StandardCharsets
19+ import java .nio .file .{FileSystemException , NoSuchFileException }
1920import java .util .Optional
2021import java .util .concurrent .atomic .AtomicInteger
2122import 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 ]()) {
0 commit comments