Skip to content

Add compilation unit info to ClassSymbol #19010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
16 changes: 14 additions & 2 deletions compiler/src/dotty/tools/dotc/core/CompilationUnitInfo.scala
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
package dotty.tools.dotc.core

import dotty.tools.io.AbstractFile
import dotty.tools.tasty.TastyVersion

/** Information about the compilation unit of a class symbol.
*
* @param associatedFile The source or class file from which this class or
* the class containing this symbol was generated,
* null if not applicable.
* @param tastyVersion The TASTy version (major, minor, experimental)
*/
class CompilationUnitInfo(
val associatedFile: AbstractFile,
private var tastyVersionOpt: Option[TastyVersion],
) {

def tastyVersion: Option[TastyVersion] = tastyVersionOpt

/** Sets the TASTy version. Used to initialize the TASTy version when
* Loading a TASTy file in TastyLoader.
*/
def initTastyVersion(version: TastyVersion): Unit =
tastyVersionOpt = Some(version)

override def toString(): String =
s"CompilationUnitInfo($associatedFile)"
s"CompilationUnitInfo($associatedFile, $tastyVersion)"
}

object CompilationUnitInfo:
def apply(assocFile: AbstractFile | Null): CompilationUnitInfo | Null =
if assocFile == null then null
else new CompilationUnitInfo(assocFile)
else new CompilationUnitInfo(assocFile, tastyVersionOpt = None) // TODO use current TASTy version
8 changes: 7 additions & 1 deletion compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,12 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {

class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {

def compilationUnitInfo: CompilationUnitInfo | Null = CompilationUnitInfo(tastyFile)
private val compUnitInfo = new CompilationUnitInfo(
tastyFile,
tastyVersionOpt = None // set on doComplete
)

def compilationUnitInfo: CompilationUnitInfo | Null = compUnitInfo

def description(using Context): String = "TASTy file " + tastyFile.toString

Expand All @@ -427,6 +432,7 @@ class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
val (classRoot, moduleRoot) = rootDenots(root.asClass)
val tastyBytes = tastyFile.toByteArray
val unpickler = new tasty.DottyUnpickler(tastyBytes)
compUnitInfo.initTastyVersion(unpickler.tastyVersion)
unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource))
if mayLoadTreesFromTasty then
classRoot.classSymbol.rootTreeOrProvider = unpickler
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import TreeUnpickler.UnpickleMode

import dotty.tools.tasty.TastyReader
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}
import dotty.tools.tasty.TastyVersion

object DottyUnpickler {

Expand Down Expand Up @@ -55,6 +56,13 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
private val attributeUnpicklerOpt = unpickler.unpickle(new AttributesSectionUnpickler)
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)).get

def tastyVersion: TastyVersion =
TastyVersion(
unpickler.header.majorVersion,
unpickler.header.minorVersion,
unpickler.header.experimentalVersion,
)

/** Enter all toplevel classes and objects into their scopes
* @param roots a set of SymDenotations that should be overwritten by unpickling
*/
Expand Down
5 changes: 2 additions & 3 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ package tasty

import scala.language.unsafeNulls

import dotty.tools.tasty.{TastyFormat, TastyBuffer, TastyReader, TastyHeaderUnpickler, UnpicklerConfig}
import TastyHeaderUnpickler.TastyVersion
import dotty.tools.tasty.{TastyFormat, TastyVersion, TastyBuffer, TastyReader, TastyHeaderUnpickler, UnpicklerConfig}
import TastyFormat.NameTags.*, TastyFormat.nameTagToString
import TastyBuffer.NameRef

Expand Down Expand Up @@ -122,7 +121,7 @@ class TastyUnpickler(reader: TastyReader) {
result
}

new TastyHeaderUnpickler(scala3CompilerConfig, reader).readHeader()
val header = new TastyHeaderUnpickler(scala3CompilerConfig, reader).readFullHeader()

locally {
until(readEnd()) { nameAtRef.add(readNameContents()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import dotty.tools.tasty.TastyBuffer
import dotty.tools.tasty.TastyReader
import dotty.tools.tasty.UnpickleException
import dotty.tools.tasty.TastyHeaderUnpickler
import dotty.tools.tasty.TastyHeaderUnpickler.TastyVersion
import dotty.tools.tasty.TastyVersion
import dotty.tools.tasty.UnpicklerConfig

class TastyHeaderUnpicklerTest {
Expand Down
24 changes: 0 additions & 24 deletions tasty/src/dotty/tools/tasty/TastyHeaderUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package dotty.tools.tasty
import java.util.UUID

import TastyFormat.{MajorVersion, MinorVersion, ExperimentalVersion, header}
import TastyHeaderUnpickler.TastyVersion

/**
* The Tasty Header consists of four fields:
Expand Down Expand Up @@ -214,27 +213,4 @@ object TastyHeaderUnpickler {
BackwardIncompatibleExperimental
else ForwardIncompatible
}

case class TastyVersion(major: Int, minor: Int, experimental: Int) {
def isExperimental: Boolean = experimental > 0

def nextStable: TastyVersion = copy(experimental = 0)

def minStable: TastyVersion = copy(minor = 0, experimental = 0)

def show: String = {
val suffix = if (isExperimental) s"-experimental-$experimental" else ""
s"$major.$minor$suffix"
}

def kind: String =
if (isExperimental) "experimental TASTy" else "TASTy"

def validRange: String = {
val min = TastyVersion(major, 0, 0)
val max = if (experimental == 0) this else TastyVersion(major, minor - 1, 0)
val extra = Option.when(experimental > 0)(this)
s"stable TASTy from ${min.show} to ${max.show}${extra.fold("")(e => s", or exactly ${e.show}")}"
}
}
}
24 changes: 24 additions & 0 deletions tasty/src/dotty/tools/tasty/TastyVersion.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dotty.tools.tasty

case class TastyVersion(major: Int, minor: Int, experimental: Int) {
def isExperimental: Boolean = experimental > 0

def nextStable: TastyVersion = copy(experimental = 0)

def minStable: TastyVersion = copy(minor = 0, experimental = 0)

def show: String = {
val suffix = if (isExperimental) s"-experimental-$experimental" else ""
s"$major.$minor$suffix"
}

def kind: String =
if (isExperimental) "experimental TASTy" else "TASTy"

def validRange: String = {
val min = TastyVersion(major, 0, 0)
val max = if (experimental == 0) this else TastyVersion(major, minor - 1, 0)
val extra = Option.when(experimental > 0)(this)
s"stable TASTy from ${min.show} to ${max.show}${extra.fold("")(e => s", or exactly ${e.show}")}"
}
}