@@ -421,72 +421,80 @@ class DependencyRecorder {
421
421
usedNames.names.foreach:
422
422
case (usedName, scopes) =>
423
423
cb.usedName(className, usedName.toString, scopes)
424
- classDependencies.foreach(recordClassDependency(cb, _))
424
+ val siblingClassfiles = new mutable.HashMap [PlainFile , Path ]
425
+ classDependencies.foreach(recordClassDependency(cb, _, siblingClassfiles))
425
426
clear()
426
427
427
- private val _siblingClassfiles = new mutable.HashMap [PlainFile , Path ]
428
+ /** Clear all state. */
429
+ def clear (): Unit =
430
+ _usedNames.clear()
431
+ _classDependencies.clear()
432
+ lastOwner = NoSymbol
433
+ lastDepSource = NoSymbol
434
+ _responsibleForImports = NoSymbol
435
+
436
+ /** Handles dependency on given symbol by trying to figure out if represents a term
437
+ * that is coming from either source code (not necessarily compiled in this compilation
438
+ * run) or from class file and calls respective callback method.
439
+ */
440
+ private def recordClassDependency (cb : interfaces.IncrementalCallback , dep : ClassDependency ,
441
+ siblingClassfiles : mutable.Map [PlainFile , Path ])(using Context ): Unit = {
442
+ val fromClassName = classNameAsString(dep.fromClass)
443
+ val sourceFile = ctx.compilationUnit.source
428
444
429
- extension (pf : PlainFile )
430
- /** Constructs a sibling class to the `jpath`.
445
+ /** For a `.tasty` file, constructs a sibling class to the `jpath`.
431
446
* Does not validate if it exists as a real file.
447
+ *
448
+ * Because classpath scanning looks for tasty files first, `dep.fromClass` will be
449
+ * associated to a `.tasty` file. However Zinc records all dependencies either based on `.jar` or `.class` files,
450
+ * where classes are in directories on the filesystem.
451
+ *
452
+ * So if the dependency comes from an upstream `.tasty` file and it was not packaged in a jar, then
453
+ * we need to call this to resolve the classfile that will eventually exist at runtime.
454
+ *
432
455
* The way this works is that by the end of compilation analysis,
433
- * there should be a corresponding NonLocalClass sent to zinc with the same class file name.
456
+ * we should have called `cb.generatedNonLocalClass` with the same class file name.
434
457
*
435
458
* FIXME: we still need a way to resolve the correct classfile when we split tasty and classes between
436
459
* different outputs (e.g. stdlib-bootstrapped).
437
460
*/
438
- private def siblingClass : Path =
439
- _siblingClassfiles .getOrElseUpdate(pf, {
461
+ def cachedSiblingClass ( pf : PlainFile ) : Path =
462
+ siblingClassfiles .getOrElseUpdate(pf, {
440
463
val jpath = pf.jpath
441
464
jpath.getParent.resolve(jpath.getFileName.toString.stripSuffix(" .tasty" ) + " .class" )
442
465
})
443
466
444
- /** Clear all state. */
445
- def clear (): Unit =
446
- _usedNames.clear()
447
- _classDependencies.clear()
448
- _siblingClassfiles.clear()
449
- lastOwner = NoSymbol
450
- lastDepSource = NoSymbol
451
- _responsibleForImports = NoSymbol
452
-
453
- /** Handles dependency on given symbol by trying to figure out if represents a term
454
- * that is coming from either source code (not necessarily compiled in this compilation
455
- * run) or from class file and calls respective callback method.
456
- */
457
- private def recordClassDependency (cb : interfaces.IncrementalCallback , dep : ClassDependency )(using Context ): Unit = {
458
- val fromClassName = classNameAsString(dep.fromClass)
459
- val sourceFile = ctx.compilationUnit.source
460
-
461
467
def binaryDependency (path : Path , binaryClassName : String ) =
462
468
cb.binaryDependency(path, binaryClassName, fromClassName, sourceFile, dep.context)
463
469
464
- def processExternalDependency (depFile : AbstractFile , binaryClassName : String , convertTasty : Boolean ) = {
465
- depFile match {
466
- case ze : ZipArchive # Entry => // The dependency comes from a JAR
467
- ze.underlyingSource match
468
- case Some (zip) if zip.jpath != null =>
469
- binaryDependency(zip.jpath, binaryClassName)
470
- case _ =>
471
- case pf : PlainFile => // The dependency comes from a class file, Zinc handles JRT filesystem
472
- binaryDependency(if convertTasty then pf.siblingClass else pf.jpath, binaryClassName)
473
- case _ =>
474
- internalError(s " Ignoring dependency $depFile of unknown class ${depFile.getClass}} " , dep.fromClass.srcPos)
475
- }
476
- }
477
-
478
- val depFile = dep.toClass.associatedFile
470
+ val depClass = dep.toClass
471
+ val depFile = depClass.associatedFile
479
472
if depFile != null then {
480
473
// Cannot ignore inheritance relationship coming from the same source (see sbt/zinc#417)
481
474
def allowLocal = dep.context == DependencyByInheritance || dep.context == LocalDependencyByInheritance
482
- if depFile.hasTastyExtension then
483
- processExternalDependency(depFile, dep.toClass.binaryClassName, convertTasty = true )
484
- else if depFile.hasClassExtension then
485
- processExternalDependency(depFile, dep.toClass.binaryClassName, convertTasty = false )
475
+ val isTasty = depFile.hasTastyExtension
476
+
477
+ def processExternalDependency () = {
478
+ val binaryClassName = depClass.binaryClassName
479
+ depFile match {
480
+ case ze : ZipArchive # Entry => // The dependency comes from a JAR
481
+ ze.underlyingSource match
482
+ case Some (zip) if zip.jpath != null =>
483
+ binaryDependency(zip.jpath, binaryClassName)
484
+ case _ =>
485
+ case pf : PlainFile => // The dependency comes from a class file, Zinc handles JRT filesystem
486
+ binaryDependency(if isTasty then cachedSiblingClass(pf) else pf.jpath, binaryClassName)
487
+ case _ =>
488
+ internalError(s " Ignoring dependency $depFile of unknown class ${depFile.getClass}} " , dep.fromClass.srcPos)
489
+ }
490
+ }
491
+
492
+ if isTasty || depFile.hasClassExtension then
493
+ processExternalDependency()
486
494
else if allowLocal || depFile != sourceFile.file then
487
495
// We cannot ignore dependencies coming from the same source file because
488
496
// the dependency info needs to propagate. See source-dependencies/trait-trait-211.
489
- val toClassName = classNameAsString(dep.toClass )
497
+ val toClassName = classNameAsString(depClass )
490
498
cb.classDependency(toClassName, fromClassName, dep.context)
491
499
}
492
500
}
0 commit comments