Skip to content

Commit 84fdce2

Browse files
committed
use enum for file extensions.
This also removes the dead code method "findClass", it is never used, and it would quickly become unperformant with so many file extensions to consider.
1 parent f61026d commit 84fdce2

26 files changed

+161
-155
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import core.Comments.{ContextDoc, ContextDocstrings}
66
import core.Contexts.*
77
import core.{MacroClassLoader, TypeError}
88
import dotty.tools.dotc.ast.Positioned
9-
import dotty.tools.io.AbstractFile
9+
import dotty.tools.io.{AbstractFile, FileExtension}
1010
import reporting.*
1111
import core.Decorators.*
1212
import config.Feature
@@ -98,9 +98,9 @@ class Driver {
9898
if !file.exists then
9999
report.error(em"File does not exist: ${file.path}")
100100
None
101-
else file.extension match
102-
case "jar" => Some(file.path)
103-
case "tasty" =>
101+
else file.ext match
102+
case FileExtension.Jar => Some(file.path)
103+
case FileExtension.Tasty =>
104104
TastyFileUtil.getClassPath(file) match
105105
case Some(classpath) => Some(classpath)
106106
case _ =>

compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,6 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
3333
packageIndex.getOrElseUpdate(pkg.dottedString, aggregates.filter(_.hasPackage(pkg)))
3434
}
3535

36-
override def findClass(className: String): Option[ClassRepresentation] = {
37-
val (pkg, _) = PackageNameUtils.separatePkgAndClassNames(className)
38-
39-
def findEntry(isSource: Boolean): Option[ClassRepresentation] =
40-
aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClass(className)).collectFirst {
41-
case Some(s: SourceFileEntry) if isSource => s
42-
case Some(s: ClassFileEntry) if !isSource => s
43-
}
44-
45-
val classEntry = findEntry(isSource = false)
46-
val sourceEntry = findEntry(isSource = true)
47-
48-
(classEntry, sourceEntry) match {
49-
case (Some(c: ClassFileEntry), Some(s: SourceFileEntry)) => Some(ClassAndSourceFilesEntry(c.file, s.file))
50-
case (c @ Some(_), _) => c
51-
case (_, s) => s
52-
}
53-
}
54-
5536
override def asURLs: Seq[URL] = aggregates.flatMap(_.asURLs)
5637

5738
override def asClassPathStrings: Seq[String] = aggregates.map(_.asClassPathString).distinct

compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -274,21 +274,17 @@ final class CtSymClassPath(ctSym: java.nio.file.Path, release: Int) extends Clas
274274
}
275275

276276
case class DirectoryClassPath(dir: JFile) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths {
277-
override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl.apply
278277

279278
def findClassFile(className: String): Option[AbstractFile] = {
280279
val relativePath = FileUtils.dirPath(className)
281-
val tastyFile = new JFile(dir, relativePath + ".tasty")
282-
if tastyFile.exists then Some(tastyFile.toPath.toPlainFile)
283-
else
284-
val classFile = new JFile(dir, relativePath + ".class")
285-
if classFile.exists then Some(classFile.toPath.toPlainFile)
286-
else None
280+
val classFile = new JFile(dir, relativePath + ".class")
281+
if classFile.exists then Some(classFile.toPath.toPlainFile)
282+
else None
287283
}
288284

289285
protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file)
290286
protected def isMatchingFile(f: JFile): Boolean =
291-
f.isTasty || (f.isClass && f.classToTasty.isEmpty)
287+
f.isTasty || (f.isClass && !f.hasSiblingTasty)
292288

293289
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
294290
}
@@ -299,16 +295,5 @@ case class DirectorySourcePath(dir: JFile) extends JFileDirectoryLookup[SourceFi
299295
protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file)
300296
protected def isMatchingFile(f: JFile): Boolean = endsScalaOrJava(f.getName)
301297

302-
override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className) map SourceFileEntryImpl.apply
303-
304-
private def findSourceFile(className: String): Option[AbstractFile] = {
305-
val relativePath = FileUtils.dirPath(className)
306-
val sourceFile = LazyList("scala", "java")
307-
.map(ext => new JFile(dir, relativePath + "." + ext))
308-
.collectFirst { case file if file.exists() => file }
309-
310-
sourceFile.map(_.toPath.toPlainFile)
311-
}
312-
313298
private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = files(inPackage)
314299
}

compiler/src/dotty/tools/dotc/classpath/FileUtils.scala

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import scala.language.unsafeNulls
88

99
import java.io.{File => JFile, FileFilter}
1010
import java.net.URL
11-
import dotty.tools.io.AbstractFile
11+
import dotty.tools.io.{AbstractFile, FileExtension}
1212

1313
/**
1414
* Common methods related to Java files and abstract files used in the context of classpath
@@ -17,49 +17,52 @@ object FileUtils {
1717
extension (file: AbstractFile) {
1818
def isPackage: Boolean = file.isDirectory && mayBeValidPackage(file.name)
1919

20-
def isClass: Boolean = !file.isDirectory && hasClassExtension && !file.name.endsWith("$class.class")
21-
// FIXME: drop last condition when we stop being compatible with Scala 2.11
20+
def isClass: Boolean = !file.isDirectory && hasClassExtension
2221

23-
def hasClassExtension: Boolean = file.hasExtension("class")
22+
def hasClassExtension: Boolean = file.hasExtension(FileExtension.Class)
2423

25-
def hasTastyExtension: Boolean = file.hasExtension("tasty")
24+
def hasTastyExtension: Boolean = file.hasExtension(FileExtension.Tasty)
2625

2726
def isTasty: Boolean = !file.isDirectory && hasTastyExtension
2827

2928
def isScalaBinary: Boolean = file.isClass || file.isTasty
3029

31-
def isScalaOrJavaSource: Boolean = !file.isDirectory && (file.hasExtension("scala") || file.hasExtension("java"))
30+
def isScalaOrJavaSource: Boolean = !file.isDirectory && (file.hasExtension(FileExtension.Scala) || file.hasExtension(FileExtension.Java))
3231

3332
// TODO do we need to check also other files using ZipMagicNumber like in scala.tools.nsc.io.Jar.isJarOrZip?
34-
def isJarOrZip: Boolean = file.hasExtension("jar") || file.hasExtension("zip")
33+
def isJarOrZip: Boolean = file.ext.isJarOrZip
3534

3635
/**
3736
* Safe method returning a sequence containing one URL representing this file, when underlying file exists,
3837
* and returning given default value in other case
3938
*/
4039
def toURLs(default: => Seq[URL] = Seq.empty): Seq[URL] = if (file.file == null) default else Seq(file.toURL)
4140

42-
/** Returns the tasty file associated with this class file */
43-
def classToTasty: Option[AbstractFile] =
44-
assert(file.isClass, s"non-class: $file")
45-
val tastyName = classNameToTasty(file.name)
46-
Option(file.resolveSibling(tastyName))
41+
/**
42+
* Returns if there is an existing sibling `.tasty` file.
43+
*/
44+
def hasSiblingTasty: Boolean =
45+
assert(file.hasClassExtension, s"non-class: $file")
46+
file.resolveSibling(classNameToTasty(file.name)) != null
4747
}
4848

4949
extension (file: JFile) {
5050
def isPackage: Boolean = file.isDirectory && mayBeValidPackage(file.getName)
5151

52-
def isClass: Boolean = file.isFile && file.getName.endsWith(SUFFIX_CLASS) && !file.getName.endsWith("$class.class")
53-
// FIXME: drop last condition when we stop being compatible with Scala 2.11
52+
def isClass: Boolean = file.isFile && hasClassExtension
53+
54+
def hasClassExtension: Boolean = file.getName.endsWith(SUFFIX_CLASS)
5455

5556
def isTasty: Boolean = file.isFile && file.getName.endsWith(SUFFIX_TASTY)
5657

57-
/** Returns the tasty file associated with this class file */
58-
def classToTasty: Option[JFile] =
59-
assert(file.isClass, s"non-class: $file")
60-
val tastyName = classNameToTasty(file.getName.stripSuffix(".class"))
61-
val tastyPath = file.toPath.resolveSibling(tastyName)
62-
if java.nio.file.Files.exists(tastyPath) then Some(tastyPath.toFile) else None
58+
/**
59+
* Returns if there is an existing sibling `.tasty` file.
60+
*/
61+
def hasSiblingTasty: Boolean =
62+
assert(file.hasClassExtension, s"non-class: $file")
63+
val path = file.toPath
64+
val tastyPath = path.resolveSibling(classNameToTasty(file.getName))
65+
java.nio.file.Files.exists(tastyPath)
6366

6467
}
6568

compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,17 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi
3838
def asURLs: Seq[URL] = Seq(new URI(dir.name).toURL)
3939
def asClassPathStrings: Seq[String] = Seq(dir.path)
4040

41-
override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl.apply
42-
4341
def findClassFile(className: String): Option[AbstractFile] = {
4442
val pathSeq = FileUtils.dirPath(className).split(java.io.File.separator)
4543
val parentDir = lookupPath(dir)(pathSeq.init.toSeq, directory = true)
46-
if parentDir == null then return None
44+
if parentDir == null then None
4745
else
48-
Option(lookupPath(parentDir)(pathSeq.last + ".tasty" :: Nil, directory = false))
49-
.orElse(Option(lookupPath(parentDir)(pathSeq.last + ".class" :: Nil, directory = false)))
46+
Option(lookupPath(parentDir)(pathSeq.last + ".class" :: Nil, directory = false))
5047
}
5148

5249
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
5350

5451
protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file)
5552
protected def isMatchingFile(f: AbstractFile): Boolean =
56-
f.isTasty || (f.isClass && f.classToTasty.isEmpty)
53+
f.isTasty || (f.isClass && !f.hasSiblingTasty)
5754
}

compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,14 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory {
4545
with NoSourcePaths {
4646

4747
override def findClassFile(className: String): Option[AbstractFile] =
48-
findClass(className).map(_.file)
49-
50-
// This method is performance sensitive as it is used by SBT's ExtractDependencies phase.
51-
override def findClass(className: String): Option[ClassFileEntryImpl] = {
5248
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
53-
val binaries = files(PackageName(pkg), simpleClassName + ".tasty", simpleClassName + ".class")
54-
binaries.find(_.file.isTasty).orElse(binaries.find(_.file.isClass))
55-
}
49+
file(PackageName(pkg), simpleClassName + ".class").map(_.file)
5650

5751
override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
5852

5953
override protected def createFileEntry(file: FileZipArchive#Entry): ClassFileEntryImpl = ClassFileEntryImpl(file)
6054
override protected def isRequiredFileType(file: AbstractFile): Boolean =
61-
file.isTasty || (file.isClass && file.classToTasty.isEmpty)
55+
file.isTasty || (file.isClass && !file.hasSiblingTasty)
6256
}
6357

6458
/**

compiler/src/dotty/tools/dotc/classpath/ZipArchiveFileLookup.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ trait ZipArchiveFileLookup[FileEntryType <: ClassRepresentation] extends Efficie
4343
}
4444
yield createFileEntry(entry)
4545

46-
protected def files(inPackage: PackageName, names: String*): Seq[FileEntryType] =
47-
for {
48-
dirEntry <- findDirEntry(inPackage).toSeq
49-
name <- names
50-
entry <- Option(dirEntry.lookupName(name, directory = false))
51-
if isRequiredFileType(entry)
52-
}
53-
yield createFileEntry(entry)
54-
5546
protected def file(inPackage: PackageName, name: String): Option[FileEntryType] =
5647
for {
5748
dirEntry <- findDirEntry(inPackage)

compiler/src/dotty/tools/dotc/config/Settings.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import scala.language.unsafeNulls
55

66
import core.Contexts.*
77

8-
import dotty.tools.io.{AbstractFile, Directory, JarArchive, PlainDirectory}
8+
import dotty.tools.io.{AbstractFile, Directory, JarArchive, PlainDirectory, FileExtension}
99

1010
import annotation.tailrec
1111
import collection.mutable.ArrayBuffer
@@ -162,7 +162,7 @@ object Settings:
162162
else setString(arg2, args2)
163163
case (OutputTag, arg :: args) =>
164164
val path = Directory(arg)
165-
val isJar = path.extension == "jar"
165+
val isJar = path.ext == FileExtension.Jar
166166
if (!isJar && !path.isDirectory)
167167
fail(s"'$arg' does not exist or is not a directory or .jar file", args)
168168
else {

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import java.nio.channels.ClosedByInterruptException
77

88
import scala.util.control.NonFatal
99

10-
import dotty.tools.dotc.classpath.FileUtils.isTasty
10+
import dotty.tools.dotc.classpath.FileUtils.hasTastyExtension
1111
import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile }
1212
import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions
1313

@@ -199,7 +199,7 @@ object SymbolLoaders {
199199
enterToplevelsFromSource(owner, nameOf(classRep), src)
200200
case (Some(bin), _) =>
201201
val completer =
202-
if bin.isTasty then ctx.platform.newTastyLoader(bin)
202+
if bin.hasTastyExtension then ctx.platform.newTastyLoader(bin)
203203
else ctx.platform.newClassLoader(bin)
204204
enterClassAndModule(owner, nameOf(classRep), completer)
205205
}

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import scala.annotation.switch
2323
import typer.Checking.checkNonCyclic
2424
import io.{AbstractFile, ZipArchive}
2525
import scala.util.control.NonFatal
26-
import dotty.tools.dotc.classpath.FileUtils.classToTasty
26+
import dotty.tools.dotc.classpath.FileUtils.hasSiblingTasty
2727

2828
import scala.compiletime.uninitialized
2929

@@ -1142,7 +1142,7 @@ class ClassfileParser(
11421142

11431143
if (scan(tpnme.TASTYATTR)) {
11441144
val hint =
1145-
if classfile.classToTasty.isDefined then "This is likely a bug in the compiler. Please report."
1145+
if classfile.hasSiblingTasty then "This is likely a bug in the compiler. Please report."
11461146
else "This `.tasty` file is missing. Try cleaning the project to fix this issue."
11471147
report.error(s"Loading Scala 3 binary from $classfile. It should have been loaded from `.tasty` file. $hint", NoSourcePosition)
11481148
return None

compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import util.Spans.offsetToInt
1212
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}
1313
import java.nio.file.{Files, Paths}
1414
import dotty.tools.io.{JarArchive, Path}
15+
import dotty.tools.dotc.classpath.FileUtils.hasTastyExtension
1516

1617
object TastyPrinter:
1718

@@ -47,7 +48,7 @@ object TastyPrinter:
4748
else if arg.endsWith(".jar") then
4849
val jar = JarArchive.open(Path(arg), create = false)
4950
try
50-
for file <- jar.iterator() if file.name.endsWith(".tasty") do
51+
for file <- jar.iterator() if file.hasTastyExtension do
5152
printTasty(s"$arg ${file.path}", file.toByteArray)
5253
finally jar.close()
5354
else

compiler/src/dotty/tools/dotc/fromtasty/Debug.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.language.unsafeNulls
66

77
import scala.util.control.NonFatal
88

9-
import dotty.tools.io.Directory
9+
import dotty.tools.io.{Directory, FileExtension}
1010

1111
import java.io.{File => JFile}
1212
import java.nio.file.{Files, Paths}
@@ -40,7 +40,7 @@ object Debug {
4040

4141
val tastyFiles =
4242
Directory(fromSourcesOut).walk
43-
.filter(x => x.isFile && "tasty".equalsIgnoreCase(x.extension))
43+
.filter(x => x.isFile && x.ext == FileExtension.Tasty)
4444
.map(_.toString)
4545
.toList
4646

compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package fromtasty
44

55
import scala.language.unsafeNulls
66

7-
import io.{JarArchive, AbstractFile, Path}
7+
import io.{JarArchive, AbstractFile, Path, FileExtension}
88
import core.Contexts.*
99
import core.Decorators.em
1010
import java.io.File
@@ -19,14 +19,14 @@ class TASTYRun(comp: Compiler, ictx: Context) extends Run(comp, ictx) {
1919
val fromTastyIgnoreList = ctx.settings.YfromTastyIgnoreList.value.toSet
2020
// Resolve class names of tasty and jar files
2121
val classNames = files.flatMap { file =>
22-
file.extension match
23-
case "jar" =>
22+
file.ext match
23+
case FileExtension.Jar =>
2424
JarArchive.open(Path(file.path), create = false).allFileNames()
2525
.map(_.stripPrefix(File.separator)) // change paths from absolute to relative
26-
.filter(e => Path.extension(e) == "tasty" && !fromTastyIgnoreList(e))
26+
.filter(e => Path.fileExtension(e) == FileExtension.Tasty && !fromTastyIgnoreList(e))
2727
.map(e => e.stripSuffix(".tasty").replace(File.separator, "."))
2828
.toList
29-
case "tasty" => TastyFileUtil.getClassName(file)
29+
case FileExtension.Tasty => TastyFileUtil.getClassName(file)
3030
case _ =>
3131
report.error(em"File extension is not `tasty` or `jar`: ${file.path}")
3232
Nil

compiler/src/dotty/tools/dotc/fromtasty/TastyFileUtil.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import scala.language.unsafeNulls
55

66
import dotty.tools.dotc.core.tasty.TastyClassName
77
import dotty.tools.dotc.core.StdNames.nme.EMPTY_PACKAGE
8-
import dotty.tools.io.AbstractFile
8+
import dotty.tools.io.{AbstractFile, FileExtension}
9+
import dotty.tools.dotc.classpath.FileUtils.hasTastyExtension
910

1011
object TastyFileUtil {
1112
/** Get the class path of a tasty file
@@ -34,7 +35,7 @@ object TastyFileUtil {
3435
*/
3536
def getClassName(file: AbstractFile): Option[String] = {
3637
assert(file.exists)
37-
assert(file.extension == "tasty")
38+
assert(file.hasTastyExtension)
3839
val bytes = file.toByteArray
3940
val names = new TastyClassName(bytes).readName()
4041
names.map { case (packageName, className) =>

compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import NameOps.*
1919
import inlines.Inlines
2020
import transform.ValueClasses
2121
import transform.SymUtils.*
22-
import dotty.tools.io.File
22+
import dotty.tools.io.{File, FileExtension}
2323
import java.io.PrintWriter
2424

2525

@@ -74,7 +74,7 @@ class ExtractAPI extends Phase {
7474

7575
if (ctx.settings.YdumpSbtInc.value) {
7676
// Append to existing file that should have been created by ExtractDependencies
77-
val pw = new PrintWriter(File(sourceFile.file.jpath).changeExtension("inc").toFile
77+
val pw = new PrintWriter(File(sourceFile.file.jpath).changeExtension(FileExtension.Inc).toFile
7878
.bufferedWriter(append = true), true)
7979
try {
8080
classes.foreach(source => pw.println(DefaultShowAPI(source)))

0 commit comments

Comments
 (0)