diff --git a/tasty-query/shared/src/main/scala/tastyquery/reader/tasties/TreeUnpickler.scala b/tasty-query/shared/src/main/scala/tastyquery/reader/tasties/TreeUnpickler.scala index ccc97a32..a6de7eee 100644 --- a/tasty-query/shared/src/main/scala/tastyquery/reader/tasties/TreeUnpickler.scala +++ b/tasty-query/shared/src/main/scala/tastyquery/reader/tasties/TreeUnpickler.scala @@ -1154,7 +1154,7 @@ private[tasties] class TreeUnpickler private ( val simpleName = tpe match case tpe: PackageRef => tpe.fullyQualifiedName.simpleName case tpe: TermRef => extractUnsignedName(tpe.name) // fallback for incomplete or invalid programs - Ident(simpleName)(tpe)(span) + Ident(simpleName)(tpe)(spn) case TERMREFdirect => val spn = span reader.readByte() @@ -1699,7 +1699,8 @@ private[tasties] class TreeUnpickler private ( case tag if isTypeTreeTag(tag) => throw TastyFormatException(s"Unexpected type tree tag ${astTagToString(tag)} $posErrorMsg") case _ => - TypeWrapper(readNonEmptyPrefix())(span) + val spn = span + TypeWrapper(readNonEmptyPrefix())(spn) } private def readInlinedCaller(end: Addr)(using SourceFile): Option[TypeIdent | SelectTypeTree] = diff --git a/tasty-query/shared/src/test/scala/tastyquery/PositionSuite.scala b/tasty-query/shared/src/test/scala/tastyquery/PositionSuite.scala index bf91060b..75dd7c3b 100644 --- a/tasty-query/shared/src/test/scala/tastyquery/PositionSuite.scala +++ b/tasty-query/shared/src/test/scala/tastyquery/PositionSuite.scala @@ -309,6 +309,37 @@ class PositionSuite extends RestrictedUnpicklingSuite { assertEquals(collectCode[TypeApply](tree), List("Seq", "Seq[Int]", "A[Int, Seq[String]]")) } + testUnpickle("inferred-type-arg", "simple_trees.InferredTypeArgs") { tree => + /* + * The inferred `Int` type argument in `id(42)` is encoded as a non-tree-tagged type (a `TYPEREF`). When tasty-query + * reads it, it must capture `span` before consuming the type bytes, otherwise the resulting `TypeWrapper` gets the + * position of whatever node comes next. + */ + val idName = termName("id") + val typeApply = findTree(tree) { + case typeApply @ TypeApply(Select(_, SignedName(`idName`, _, _)), _) => typeApply + case typeApply @ TypeApply(Select(_, `idName`), _) => typeApply + } + + val typeArg = typeApply.args match { + case (typeWrapper: TypeWrapper) :: Nil => typeWrapper + case other => fail(s"expected a single TypeWrapper, got: $other") + } + + assertEquals(posToCode(typeArg.pos), Some("id")) + } + + testUnpickle("package-ref-ident", "simple_trees.PackageRefIdent") { tree => + /* + * The leading `scala` in `scala.Predef.identity(1)` is an `Ident` with a `TermRef` type pickled as TERMREFpkg. The + * unpickler must use the span captured before `readPackageRef` advances the reader, otherwise the `Ident` inherits + * the position of the next entry. + */ + val scalaIdentifier = findTree(tree) { case identifier @ Ident(SimpleName("scala")) => identifier } + + assertEquals(posToCode(scalaIdentifier.pos), Some("scala")) + } + testUnpickle("type-ident", "simple_trees.Typed") { tree => assertEquals(collectCode[TypeIdent](tree), List("Int")) } @@ -369,12 +400,6 @@ class PositionSuite extends RestrictedUnpicklingSuite { collectCode[TypeDefinitionTree](tree), List( "Int", - /* The following makes no sense; it is the position of the type def - * of `type AbstractType`. It's probably dotc's auto-assigning of - * positions that goes wild. - */ - """type AbstractType - | type AbstractWithBounds >: Null <: Product""".stripMargin, ">: Null <: Product", "Int", "Null <: Product = Null", @@ -388,7 +413,6 @@ class PositionSuite extends RestrictedUnpicklingSuite { collectCode[TypeDefinitionTree](tree), List( "[X] =>> List[X]", - "X] =>> List[X]", // TODO Improve this "List[X]" ) ) diff --git a/test-sources/src/main/scala/simple_trees/InferredTypeArgs.scala b/test-sources/src/main/scala/simple_trees/InferredTypeArgs.scala new file mode 100644 index 00000000..36bbadde --- /dev/null +++ b/test-sources/src/main/scala/simple_trees/InferredTypeArgs.scala @@ -0,0 +1,7 @@ +package simple_trees + +class InferredTypeArgs { + def id[T](x: T): T = x + + val a = id(42) +} diff --git a/test-sources/src/main/scala/simple_trees/PackageRefIdent.scala b/test-sources/src/main/scala/simple_trees/PackageRefIdent.scala new file mode 100644 index 00000000..b2d387de --- /dev/null +++ b/test-sources/src/main/scala/simple_trees/PackageRefIdent.scala @@ -0,0 +1,5 @@ +package simple_trees + +class PackageRefIdent { + val x = scala.Predef.identity(1) +}