Skip to content

Commit 049904a

Browse files
committed
modify spans of statements with end markers
1 parent 65187a3 commit 049904a

File tree

4 files changed

+37
-26
lines changed

4 files changed

+37
-26
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ object desugar {
182182
tpt = TypeTree(defn.UnitType),
183183
rhs = setterRhs
184184
).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy))
185-
.dropEndIndex() // the end marker should only appear on the getter definition
185+
.dropEndMarker() // the end marker should only appear on the getter definition
186186
Thicket(vdef1, setter)
187187
}
188188
else vdef1
@@ -875,7 +875,6 @@ object desugar {
875875
val modul = ValDef(moduleName, clsRef, New(clsRef, Nil))
876876
.withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags)
877877
.withSpan(mdef.span.startPos)
878-
.withEndIndex(copyFrom = mdef) // copy over the end marker position to the module val
879878
val ValDef(selfName, selfTpt, _) = impl.self
880879
val selfMods = impl.self.mods
881880
if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos)
@@ -885,6 +884,7 @@ object desugar {
885884
val clsTmpl = cpy.Template(impl)(self = clsSelf, body = impl.body)
886885
val cls = TypeDef(clsName, clsTmpl)
887886
.withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags)
887+
.withEndMarker(copyFrom = mdef) // copy over the end marker position to the module class def
888888
Thicket(modul, classDef(cls).withSpan(mdef.span))
889889
}
890890
}

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -327,42 +327,45 @@ object Trees {
327327

328328
extension (mdef: untpd.DefTree) def mods: untpd.Modifiers = mdef.rawMods
329329

330-
/** PackageDef | NamedDefTree */
331-
sealed trait WithEndMarker:
332-
self: Attachment.Container =>
330+
sealed trait WithEndMarker[-T >: Untyped]:
331+
self: PackageDef[T] | NamedDefTree[T] =>
333332

334333
import WithEndMarker.*
335334

336335
final def endSpan(using Context): Span =
337-
self.getAttachment(EndIndex) match
338-
case Some(end) =>
339-
val realName = srcName.stripModuleClassSuffix.lastPart
340-
Span(end - realName.length, end)
341-
case none => NoSpan
336+
if hasEndMarker then
337+
val realName = srcName.stripModuleClassSuffix.lastPart
338+
span.withStart(span.end - realName.length)
339+
else
340+
NoSpan
342341

343342
protected def srcName(using Context): Name
344343

345-
final def withEndIndex(index: Int): self.type =
346-
self.withAttachment(EndIndex, index)
344+
final def withEndMarker(): self.type =
345+
self.withAttachment(HasEndMarker, ())
347346

348-
final def withEndIndex(copyFrom: WithEndMarker): self.type =
349-
copyFrom.endIndex.foreach(withEndIndex)
350-
this
347+
final def withEndMarker(copyFrom: WithEndMarker[T @uncheckedVariance]): self.type =
348+
if copyFrom.hasEndMarker then
349+
this.withEndMarker()
350+
else
351+
this
351352

352-
final def dropEndIndex(): self.type =
353-
self.removeAttachment(EndIndex)
353+
final def dropEndMarker(): self.type =
354+
self.removeAttachment(HasEndMarker)
354355
this
355356

356-
protected def endIndex: Option[Int] = self.getAttachment(EndIndex)
357+
protected def hasEndMarker: Boolean = self.hasAttachment(HasEndMarker)
357358

358359
object WithEndMarker:
359-
/** Property key for trees with an `end` marker */
360-
private val EndIndex: Property.StickyKey[Int] = Property.StickyKey()
360+
/** Property key that signals the tree was terminated
361+
* with an `end` marker in the source code
362+
*/
363+
private val HasEndMarker: Property.StickyKey[Unit] = Property.StickyKey()
361364

362365
end WithEndMarker
363366

364367
abstract class NamedDefTree[-T >: Untyped](implicit @constructorOnly src: SourceFile)
365-
extends NameTree[T] with DefTree[T] with WithEndMarker {
368+
extends NameTree[T] with DefTree[T] with WithEndMarker[T] {
366369
type ThisTree[-T >: Untyped] <: NamedDefTree[T]
367370

368371
protected def srcName(using Context): Name =
@@ -897,7 +900,7 @@ object Trees {
897900

898901
/** package pid { stats } */
899902
case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @constructorOnly src: SourceFile)
900-
extends ProxyTree[T] with WithEndMarker {
903+
extends ProxyTree[T] with WithEndMarker[T] {
901904
type ThisTree[-T >: Untyped] = PackageDef[T]
902905
def forwardTo: RefTree[T] = pid
903906
protected def srcName(using Context): Name = pid.name
@@ -1092,6 +1095,8 @@ object Trees {
10921095
type Annotated = Trees.Annotated[T]
10931096
type Thicket = Trees.Thicket[T]
10941097

1098+
type WithEndMarker = Trees.WithEndMarker[T]
1099+
10951100
@sharable val EmptyTree: Thicket = genericEmptyTree
10961101
@sharable val EmptyValDef: ValDef = genericEmptyValDef
10971102
@sharable val ContextualEmptyTree: Thicket = new EmptyTree() // an empty tree marking a contextual closure

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ object Parsers {
12751275

12761276
def checkEndMarker[T <: Tree](stats: ListBuffer[T]): Unit =
12771277

1278-
def matches(stat: Tree): Boolean = stat match
1278+
def matches(stat: T): Boolean = stat match
12791279
case stat: MemberDef if !stat.name.isEmpty =>
12801280
if stat.name == nme.CONSTRUCTOR then in.token == THIS
12811281
else in.isIdent && in.name == stat.name.toTermName
@@ -1293,14 +1293,20 @@ object Parsers {
12931293
case _: (ForYield | ForDo) => in.token == FOR
12941294
case _ => false
12951295

1296-
def matchesAndSetEnd(stat: Tree): Boolean = {
1296+
def matchesAndSetEnd(stat: T): Boolean = {
12971297
val didMatch = matches(stat)
12981298
if didMatch then
12991299
stat match
13001300
case stat: WithEndMarker =>
1301-
stat.withEndIndex(index = in.lastCharOffset)
1301+
stat.withEndMarker()
13021302
case _ =>
13031303
()
1304+
1305+
// VERY SNEAKY MUTATION HERE:
1306+
// `withSpan` can clone the tree, so we must replace the last statment
1307+
stats.dropRightInPlace(1)
1308+
stats.addOne(stat.withSpan(stat.span.withEnd(in.lastCharOffset)))
1309+
end if
13041310
didMatch
13051311
}
13061312

compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ class ExtractSemanticDB extends Phase:
240240
traverseChildren(tree)
241241

242242
tree match
243-
case tree: WithEndMarker =>
243+
case tree: WithEndMarker[t] =>
244244
val endSpan = tree.endSpan
245245
if endSpan.exists then
246246
registerUseGuarded(None, tree.symbol, endSpan, tree.source)

0 commit comments

Comments
 (0)