Skip to content

Commit a34b7b8

Browse files
authored
Revert "Port classpath improvements"
1 parent 0246f72 commit a34b7b8

8 files changed

+119
-167
lines changed

Diff for: compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala

+28-43
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ package dotc.classpath
66

77
import java.net.URL
88
import scala.collection.mutable.ArrayBuffer
9-
import scala.collection.immutable.ArraySeq
10-
11-
import dotty.tools.io.{ AbstractFile, ClassPath, ClassRepresentation, EfficientClassPath }
9+
import dotty.tools.io.{ AbstractFile, ClassPath, ClassRepresentation }
1210

1311
/**
1412
* A classpath unifying multiple class- and sourcepath entries.
@@ -21,20 +19,20 @@ import dotty.tools.io.{ AbstractFile, ClassPath, ClassRepresentation, EfficientC
2119
case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
2220
override def findClassFile(className: String): Option[AbstractFile] = {
2321
val (pkg, _) = PackageNameUtils.separatePkgAndClassNames(className)
24-
aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClassFile(className)).collectFirst {
22+
aggregatesForPackage(pkg).iterator.map(_.findClassFile(className)).collectFirst {
2523
case Some(x) => x
2624
}
2725
}
2826
private val packageIndex: collection.mutable.Map[String, Seq[ClassPath]] = collection.mutable.Map()
29-
private def aggregatesForPackage(pkg: PackageName): Seq[ClassPath] = packageIndex.synchronized {
30-
packageIndex.getOrElseUpdate(pkg.dottedString, aggregates.filter(_.hasPackage(pkg)))
27+
private def aggregatesForPackage(pkg: String): Seq[ClassPath] = packageIndex.synchronized {
28+
packageIndex.getOrElseUpdate(pkg, aggregates.filter(_.hasPackage(pkg)))
3129
}
3230

3331
override def findClass(className: String): Option[ClassRepresentation] = {
3432
val (pkg, _) = PackageNameUtils.separatePkgAndClassNames(className)
3533

3634
def findEntry(isSource: Boolean): Option[ClassRepresentation] =
37-
aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClass(className)).collectFirst {
35+
aggregatesForPackage(pkg).iterator.map(_.findClass(className)).collectFirst {
3836
case Some(s: SourceFileEntry) if isSource => s
3937
case Some(s: ClassFileEntry) if !isSource => s
4038
}
@@ -55,47 +53,31 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
5553

5654
override def asSourcePathString: String = ClassPath.join(aggregates map (_.asSourcePathString): _*)
5755

58-
override private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = {
56+
override private[dotty] def packages(inPackage: String): Seq[PackageEntry] = {
5957
val aggregatedPackages = aggregates.flatMap(_.packages(inPackage)).distinct
6058
aggregatedPackages
6159
}
6260

63-
override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] =
61+
override private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] =
6462
getDistinctEntries(_.classes(inPackage))
6563

66-
override private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] =
64+
override private[dotty] def sources(inPackage: String): Seq[SourceFileEntry] =
6765
getDistinctEntries(_.sources(inPackage))
6866

69-
override private[dotty] def hasPackage(pkg: PackageName): Boolean = aggregates.exists(_.hasPackage(pkg))
70-
override private[dotty] def list(inPackage: PackageName): ClassPathEntries = {
71-
val packages: java.util.HashSet[PackageEntry] = new java.util.HashSet[PackageEntry]()
72-
val classesAndSourcesBuffer = collection.mutable.ArrayBuffer[ClassRepresentation]()
73-
val onPackage: PackageEntry => Unit = packages.add(_)
74-
val onClassesAndSources: ClassRepresentation => Unit = classesAndSourcesBuffer += _
75-
76-
aggregates.foreach { cp =>
77-
try {
78-
cp match {
79-
case ecp: EfficientClassPath =>
80-
ecp.list(inPackage, onPackage, onClassesAndSources)
81-
case _ =>
82-
val entries = cp.list(inPackage)
83-
entries._1.foreach(entry => packages.add(entry))
84-
classesAndSourcesBuffer ++= entries._2
85-
}
86-
} catch {
67+
override private[dotty] def hasPackage(pkg: String): Boolean = aggregates.exists(_.hasPackage(pkg))
68+
override private[dotty] def list(inPackage: String): ClassPathEntries = {
69+
val (packages, classesAndSources) = aggregates.map { cp =>
70+
try
71+
cp.list(inPackage).toTuple
72+
catch {
8773
case ex: java.io.IOException =>
88-
val e = FatalError(ex.getMessage)
74+
val e = new FatalError(ex.getMessage)
8975
e.initCause(ex)
9076
throw e
9177
}
92-
}
93-
94-
val distinctPackages: Seq[PackageEntry] = {
95-
val arr = packages.toArray(new Array[PackageEntry](packages.size()))
96-
ArraySeq.unsafeWrapArray(arr)
97-
}
98-
val distinctClassesAndSources = mergeClassesAndSources(classesAndSourcesBuffer)
78+
}.unzip
79+
val distinctPackages = packages.flatten.distinct
80+
val distinctClassesAndSources = mergeClassesAndSources(classesAndSources: _*)
9981
ClassPathEntries(distinctPackages, distinctClassesAndSources)
10082
}
10183

@@ -104,16 +86,19 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
10486
* creates an entry containing both of them. If there would be more than one class or source
10587
* entries for the same class it always would use the first entry of each type found on a classpath.
10688
*/
107-
private def mergeClassesAndSources(entries: scala.collection.Seq[ClassRepresentation]): Seq[ClassRepresentation] = {
89+
private def mergeClassesAndSources(entries: scala.collection.Seq[ClassRepresentation]*): Seq[ClassRepresentation] = {
10890
// based on the implementation from MergedClassPath
10991
var count = 0
110-
val indices = new collection.mutable.HashMap[String, Int]()
111-
val mergedEntries = new ArrayBuffer[ClassRepresentation](entries.size)
92+
val indices = collection.mutable.HashMap[String, Int]()
93+
val mergedEntries = new ArrayBuffer[ClassRepresentation](1024)
94+
11295
for {
113-
entry <- entries
114-
} {
96+
partOfEntries <- entries
97+
entry <- partOfEntries
98+
}
99+
{
115100
val name = entry.name
116-
if (indices.contains(name)) {
101+
if (indices contains name) {
117102
val index = indices(name)
118103
val existing = mergedEntries(index)
119104

@@ -128,7 +113,7 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath {
128113
count += 1
129114
}
130115
}
131-
if (mergedEntries.isEmpty) Nil else mergedEntries.toIndexedSeq
116+
mergedEntries.toIndexedSeq
132117
}
133118

134119
private def getDistinctEntries[EntryType <: ClassRepresentation](getEntries: ClassPath => Seq[EntryType]): Seq[EntryType] = {

Diff for: compiler/src/dotty/tools/dotc/classpath/ClassPath.scala

+2-21
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ case class ClassPathEntries(packages: scala.collection.Seq[PackageEntry], classe
1010
def toTuple: (scala.collection.Seq[PackageEntry], scala.collection.Seq[ClassRepresentation]) = (packages, classesAndSources)
1111
}
1212

13-
object ClassPathEntries {
14-
val empty = ClassPathEntries(Seq.empty, Seq.empty)
15-
}
16-
1713
trait ClassFileEntry extends ClassRepresentation {
1814
def file: AbstractFile
1915
}
@@ -22,21 +18,6 @@ trait SourceFileEntry extends ClassRepresentation {
2218
def file: AbstractFile
2319
}
2420

25-
case class PackageName(dottedString: String) {
26-
def isRoot: Boolean = dottedString.isEmpty
27-
val dirPathTrailingSlash: String = FileUtils.dirPath(dottedString) + "/"
28-
29-
def entryName(entry: String): String = {
30-
if (isRoot) entry else {
31-
val builder = new java.lang.StringBuilder(dottedString.length + 1 + entry.length)
32-
builder.append(dottedString)
33-
builder.append('.')
34-
builder.append(entry)
35-
builder.toString
36-
}
37-
}
38-
}
39-
4021
trait PackageEntry {
4122
def name: String
4223
}
@@ -69,10 +50,10 @@ private[dotty] case class PackageEntryImpl(name: String) extends PackageEntry
6950

7051
private[dotty] trait NoSourcePaths {
7152
def asSourcePathString: String = ""
72-
private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = Seq.empty
53+
private[dotty] def sources(inPackage: String): Seq[SourceFileEntry] = Seq.empty
7354
}
7455

7556
private[dotty] trait NoClassPaths {
7657
def findClassFile(className: String): Option[AbstractFile] = None
77-
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = Seq.empty
58+
private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] = Seq.empty
7859
}

Diff for: compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala

+38-35
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import java.io.{File => JFile}
77
import java.net.URL
88
import java.nio.file.{FileSystems, Files}
99

10-
import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation, EfficientClassPath}
10+
import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation}
1111
import FileUtils._
12-
1312
import scala.collection.JavaConverters._
14-
import scala.collection.immutable.ArraySeq
1513

1614
/**
1715
* A trait allowing to look for classpath entries in directories. It provides common logic for
@@ -20,7 +18,7 @@ import scala.collection.immutable.ArraySeq
2018
* when we have a name of a package.
2119
* It abstracts over the file representation to work with both JFile and AbstractFile.
2220
*/
23-
trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends EfficientClassPath {
21+
trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends ClassPath {
2422
type F
2523

2624
val dir: F
@@ -35,24 +33,27 @@ trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends EfficientCla
3533
protected def createFileEntry(file: AbstractFile): FileEntryType
3634
protected def isMatchingFile(f: F): Boolean
3735

38-
private def getDirectory(forPackage: PackageName): Option[F] =
39-
if (forPackage.isRoot)
36+
private def getDirectory(forPackage: String): Option[F] =
37+
if (forPackage == ClassPath.RootPackage)
4038
Some(dir)
41-
else
42-
getSubDir(forPackage.dirPathTrailingSlash)
39+
else {
40+
val packageDirName = FileUtils.dirPath(forPackage)
41+
getSubDir(packageDirName)
42+
}
4343

44-
override private[dotty] def hasPackage(pkg: PackageName): Boolean = getDirectory(pkg).isDefined
44+
override private[dotty] def hasPackage(pkg: String): Boolean = getDirectory(pkg).isDefined
4545

46-
private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = {
46+
private[dotty] def packages(inPackage: String): Seq[PackageEntry] = {
4747
val dirForPackage = getDirectory(inPackage)
4848
val nestedDirs: Array[F] = dirForPackage match {
4949
case None => emptyFiles
5050
case Some(directory) => listChildren(directory, Some(isPackage))
5151
}
52-
ArraySeq.unsafeWrapArray(nestedDirs).map(f => PackageEntryImpl(inPackage.entryName(getName(f))))
52+
val prefix = PackageNameUtils.packagePrefix(inPackage)
53+
nestedDirs.toIndexedSeq.map(f => PackageEntryImpl(prefix + getName(f)))
5354
}
5455

55-
protected def files(inPackage: PackageName): Seq[FileEntryType] = {
56+
protected def files(inPackage: String): Seq[FileEntryType] = {
5657
val dirForPackage = getDirectory(inPackage)
5758
val files: Array[F] = dirForPackage match {
5859
case None => emptyFiles
@@ -61,18 +62,21 @@ trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends EfficientCla
6162
files.iterator.map(f => createFileEntry(toAbstractFile(f))).toSeq
6263
}
6364

64-
override def list(inPackage: PackageName, onPackageEntry: PackageEntry => Unit, onClassesAndSources: ClassRepresentation => Unit): Unit = {
65+
private[dotty] def list(inPackage: String): ClassPathEntries = {
6566
val dirForPackage = getDirectory(inPackage)
66-
dirForPackage match {
67-
case None =>
68-
case Some(directory) =>
69-
for (file <- listChildren(directory)) {
70-
if (isPackage(file))
71-
onPackageEntry(PackageEntryImpl(inPackage.entryName(getName(file))))
72-
else if (isMatchingFile(file))
73-
onClassesAndSources(createFileEntry(toAbstractFile(file)))
74-
}
67+
val files: Array[F] = dirForPackage match {
68+
case None => emptyFiles
69+
case Some(directory) => listChildren(directory)
7570
}
71+
val packagePrefix = PackageNameUtils.packagePrefix(inPackage)
72+
val packageBuf = collection.mutable.ArrayBuffer.empty[PackageEntry]
73+
val fileBuf = collection.mutable.ArrayBuffer.empty[FileEntryType]
74+
for (file <- files)
75+
if (isPackage(file))
76+
packageBuf += PackageEntryImpl(packagePrefix + getName(file))
77+
else if (isMatchingFile(file))
78+
fileBuf += createFileEntry(toAbstractFile(file))
79+
ClassPathEntries(packageBuf, fileBuf)
7680
}
7781
}
7882

@@ -155,25 +159,24 @@ final class JrtClassPath(fs: java.nio.file.FileSystem) extends ClassPath with No
155159
}
156160

157161
/** Empty string represents root package */
158-
override private[dotty] def hasPackage(pkg: PackageName): Boolean = packageToModuleBases.contains(pkg.dottedString)
162+
override private[dotty] def hasPackage(pkg: String): Boolean = packageToModuleBases.contains(pkg)
159163

160-
override private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = {
164+
override private[dotty] def packages(inPackage: String): Seq[PackageEntry] = {
161165
def matches(packageDottedName: String) =
162166
if (packageDottedName.contains("."))
163-
packageOf(packageDottedName) == inPackage.dottedString
164-
else inPackage.isRoot
167+
packageOf(packageDottedName) == inPackage
168+
else inPackage == ""
165169
packageToModuleBases.keysIterator.filter(matches).map(PackageEntryImpl(_)).toVector
166170
}
167-
168-
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] =
169-
if (inPackage.isRoot) Nil
171+
private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] =
172+
if (inPackage == "") Nil
170173
else
171-
packageToModuleBases.getOrElse(inPackage.dottedString, Nil).flatMap(x =>
172-
Files.list(x.resolve(inPackage.dirPathTrailingSlash)).iterator().asScala.filter(_.getFileName.toString.endsWith(".class"))).map(x =>
174+
packageToModuleBases.getOrElse(inPackage, Nil).flatMap(x =>
175+
Files.list(x.resolve(FileUtils.dirPath(inPackage))).iterator().asScala.filter(_.getFileName.toString.endsWith(".class"))).map(x =>
173176
ClassFileEntryImpl(new PlainFile(new dotty.tools.io.File(x)))).toVector
174177

175-
override private[dotty] def list(inPackage: PackageName): ClassPathEntries =
176-
if (inPackage.isRoot) ClassPathEntries(packages(inPackage), Nil)
178+
override private[dotty] def list(inPackage: String): ClassPathEntries =
179+
if (inPackage == "") ClassPathEntries(packages(inPackage), Nil)
177180
else ClassPathEntries(packages(inPackage), classes(inPackage))
178181

179182
def asURLs: Seq[URL] = Seq(new URL("jrt:/"))
@@ -211,7 +214,7 @@ case class DirectoryClassPath(dir: JFile) extends JFileDirectoryLookup[ClassFile
211214
protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file)
212215
protected def isMatchingFile(f: JFile): Boolean = f.isClass
213216

214-
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
217+
private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage)
215218
}
216219

217220
case class DirectorySourcePath(dir: JFile) extends JFileDirectoryLookup[SourceFileEntryImpl] with NoClassPaths {
@@ -235,5 +238,5 @@ case class DirectorySourcePath(dir: JFile) extends JFileDirectoryLookup[SourceFi
235238
}
236239
}
237240

238-
private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = files(inPackage)
241+
private[dotty] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage)
239242
}

Diff for: compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi
4545
Option(lookupPath(dir)(relativePath.split(java.io.File.separator).toIndexedSeq, directory = false))
4646
}
4747

48-
private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
48+
private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage)
4949

5050
protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file)
5151
protected def isMatchingFile(f: AbstractFile): Boolean = f.isClass

Diff for: compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala

+11-10
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory {
4242

4343
override def findClassFile(className: String): Option[AbstractFile] = {
4444
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
45-
file(PackageName(pkg), simpleClassName + ".class").map(_.file)
45+
file(pkg, simpleClassName + ".class").map(_.file)
4646
}
4747

4848
// This method is performance sensitive as it is used by SBT's ExtractDependencies phase.
4949
override def findClass(className: String): Option[ClassRepresentation] = {
5050
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
51-
file(PackageName(pkg), simpleClassName + ".class")
51+
file(pkg, simpleClassName + ".class")
5252
}
5353

54-
override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage)
54+
override private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage)
5555

5656
override protected def createFileEntry(file: FileZipArchive#Entry): ClassFileEntryImpl = ClassFileEntryImpl(file)
5757
override protected def isRequiredFileType(file: AbstractFile): Boolean = file.isClass
@@ -67,7 +67,7 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory {
6767
private case class ManifestResourcesClassPath(file: ManifestResources) extends ClassPath with NoSourcePaths {
6868
override def findClassFile(className: String): Option[AbstractFile] = {
6969
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
70-
classes(PackageName(pkg)).find(_.name == simpleClassName).map(_.file)
70+
classes(pkg).find(_.name == simpleClassName).map(_.file)
7171
}
7272

7373
override def asClassPathStrings: Seq[String] = Seq(file.path)
@@ -118,20 +118,21 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory {
118118
packages
119119
}
120120

121-
override private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = cachedPackages.get(inPackage.dottedString) match {
121+
override private[dotty] def packages(inPackage: String): Seq[PackageEntry] = cachedPackages.get(inPackage) match {
122122
case None => Seq.empty
123123
case Some(PackageFileInfo(_, subpackages)) =>
124-
subpackages.map(packageFile => PackageEntryImpl(inPackage.entryName(packageFile.name)))
124+
val prefix = PackageNameUtils.packagePrefix(inPackage)
125+
subpackages.map(packageFile => PackageEntryImpl(prefix + packageFile.name))
125126
}
126127

127-
override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = cachedPackages.get(inPackage.dottedString) match {
128+
override private[dotty] def classes(inPackage: String): Seq[ClassFileEntry] = cachedPackages.get(inPackage) match {
128129
case None => Seq.empty
129130
case Some(PackageFileInfo(pkg, _)) =>
130131
(for (file <- pkg if file.isClass) yield ClassFileEntryImpl(file)).toSeq
131132
}
132133

133-
override private[dotty] def hasPackage(pkg: PackageName) = cachedPackages.contains(pkg.dottedString)
134-
override private[dotty] def list(inPackage: PackageName): ClassPathEntries = ClassPathEntries(packages(inPackage), classes(inPackage))
134+
override private[dotty] def hasPackage(pkg: String) = cachedPackages.contains(pkg)
135+
override private[dotty] def list(inPackage: String): ClassPathEntries = ClassPathEntries(packages(inPackage), classes(inPackage))
135136
}
136137

137138
private object ManifestResourcesClassPath {
@@ -163,7 +164,7 @@ object ZipAndJarSourcePathFactory extends ZipAndJarFileLookupFactory {
163164

164165
override def asSourcePathString: String = asClassPathString
165166

166-
override private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = files(inPackage)
167+
override private[dotty] def sources(inPackage: String): Seq[SourceFileEntry] = files(inPackage)
167168

168169
override protected def createFileEntry(file: FileZipArchive#Entry): SourceFileEntryImpl = SourceFileEntryImpl(file)
169170
override protected def isRequiredFileType(file: AbstractFile): Boolean = file.isScalaOrJavaSource

0 commit comments

Comments
 (0)