Skip to content

Commit

Permalink
Merge pull request #350 from sjrd/fix-source-files
Browse files Browse the repository at this point in the history
Fix reading of source file information.
  • Loading branch information
sjrd authored Sep 26, 2023
2 parents 0671ba8 + 1dc86f2 commit 96e4a7d
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 97 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ lazy val tastyQuery =

// private[tastyquery], not an issue
ProblemFilters.exclude[IncompatibleMethTypeProblem]("tastyquery.Symbols#ClassSymbol.createRefinedClassSymbol"),
ProblemFilters.exclude[DirectMissingMethodProblem]("tastyquery.Symbols#ClassSymbol.createRefinedClassSymbol"),
ProblemFilters.exclude[DirectMissingMethodProblem]("tastyquery.Types#PolyType.fromParamsSymbols"),
ProblemFilters.exclude[DirectMissingMethodProblem]("tastyquery.Types#TypeLambda.fromParamsSymbols"),
ProblemFilters.exclude[DirectMissingMethodProblem]("tastyquery.Types#TypeLambdaTypeCompanion.fromParamsSymbols"),
Expand Down
9 changes: 0 additions & 9 deletions tasty-query/shared/src/main/scala/tastyquery/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1635,15 +1635,6 @@ object Symbols {
private[tastyquery] def createNotDeclaration(name: TypeName, owner: Symbol): ClassSymbol =
ClassSymbol(name, owner)

private[tastyquery] def createRefinedClassSymbol(
owner: Symbol,
objectType: TypeRef,
flags: FlagSet,
pos: SourcePosition
): ClassSymbol =
// TODO Store the `pos`
createRefinedClassSymbol(owner, objectType, flags)

private[tastyquery] def createRefinedClassSymbol(owner: Symbol, objectType: TypeRef, flags: FlagSet): ClassSymbol =
val cls = ClassSymbol(tpnme.RefinedClassMagic, owner) // by-pass `owner.addDeclIfDeclaringSym`
cls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

package tastyquery.reader.tasties

import scala.annotation.tailrec

import scala.collection.mutable
import scala.compiletime.uninitialized

import dotty.tools.tasty.TastyBuffer.{Addr, NameRef}
import dotty.tools.tasty.TastyFormat.SOURCE
Expand All @@ -22,7 +23,8 @@ import tastyquery.reader.ReaderContext.rctx
private[reader] class PositionUnpickler(reader: TastyReader, nameAtRef: TastyUnpickler.NameTable)(using ReaderContext) {
import reader.*

private val mySourcePositions = mutable.HashMap.empty[Addr, SourcePosition]
private val mySpans = mutable.HashMap.empty[Addr, Span]
private val mySourceFiles = mutable.HashMap.empty[Addr, SourceFile]
private var isDefined = false

def ensureDefined(): Unit =
Expand All @@ -36,57 +38,58 @@ private[reader] class PositionUnpickler(reader: TastyReader, nameAtRef: TastyUnp
myLineSizes(i) += readNat()
i += 1

/* Read the source positions
* There are spans and SOURCE directives. A source directive applies to
* the span *just before it* and the following. This is a peculiarity due
* to how dotc maintains the addresses of spans and sources. For us, it
* makes the unpickling algorithm a bit messy.
/* Read the spans and SOURCE directives.
*
* SOURCE directives inherit their `curAddress` from the previous span entry.
* They will apply to the tree at that address and all its subtree.
*/

var noSourceSeenYet = true
var curSource = SourceFile.NoSource
var curAddress = 0
var curStart = 0
var curEnd = 0

var eof = false
var header = readInt()
while !eof do
val addressDelta = header >> 3
val hasStart = (header & 4) != 0
val hasEnd = (header & 2) != 0
val hasPoint = (header & 1) != 0

curAddress += addressDelta
assert(curAddress >= 0)
if hasStart then curStart += readInt()
if hasEnd then curEnd += readInt()
val span =
if hasPoint then Span(curStart, curEnd, curStart + readInt())
else Span(curStart, curEnd)

if isAtEnd then eof = true
while !isAtEnd do
val header = readInt()
if header == SOURCE then
val path = nameAtRef.simple(readNameRef()).toString()
val source = rctx.getSourceFile(path)
mySourceFiles(Addr(curAddress)) = source

// Attach the line sizes to the first source file we encounter
if noSourceSeenYet then
source.setLineSizes(myLineSizes)
noSourceSeenYet = false
else
header = readInt()
if header == SOURCE then
val path = nameAtRef.simple(readNameRef()).toString()
curSource = rctx.getSourceFile(path)
if noSourceSeenYet then
curSource.setLineSizes(myLineSizes)
noSourceSeenYet = false

if isAtEnd then eof = true
else header = readInt()
val addressDelta = header >> 3
val hasStart = (header & 4) != 0
val hasEnd = (header & 2) != 0
val hasPoint = (header & 1) != 0

curAddress += addressDelta
assert(curAddress >= 0)
if hasStart then curStart += readInt()
if hasEnd then curEnd += readInt()
val span =
if hasPoint then Span(curStart, curEnd, curStart + readInt())
else Span(curStart, curEnd)
mySpans(Addr(curAddress)) = span
end if

mySourcePositions(Addr(curAddress)) = new SourcePosition(curSource, span)
end while

isDefined = true
}
end ensureDefined

def sourcePositionAt(addr: Addr): SourcePosition =
def spanAt(addr: Addr): Span =
ensureDefined()
mySpans.getOrElse(addr, NoSpan)

def hasSourceFileAt(addr: Addr): Boolean =
ensureDefined()
mySourceFiles.contains(addr)

def sourceFileAt(addr: Addr, default: SourceFile): SourceFile =
ensureDefined()
mySourcePositions.getOrElse(addr, SourcePosition.NoPosition)
mySourceFiles.getOrElse(addr, default)
}
Loading

0 comments on commit 96e4a7d

Please sign in to comment.