Skip to content

Commit f0d831d

Browse files
committed
Optimize Symbol#source
It's called more often now that we generation source positions. Time for some caching.
1 parent de43fb4 commit f0d831d

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -623,24 +623,16 @@ object Symbols {
623623
final def symbol(implicit ev: DontUseSymbolOnSymbol): Nothing = unsupported("symbol")
624624
type DontUseSymbolOnSymbol
625625

626-
def source(implicit ctx: Context): SourceFile =
626+
final def source(implicit ctx: Context): SourceFile =
627627
if (!defTree.isEmpty) defTree.source
628-
else {
629-
val file = associatedFile
630-
if (file != null && file.extension != "class") ctx.getSource(file)
631-
else {
632-
val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase))
633-
topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match {
634-
case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
635-
case Some(Constant(path: String)) => ctx.getSource(path)
636-
case none => NoSource
637-
}
638-
case none => NoSource
639-
}
640-
}
628+
else this match {
629+
case cls: ClassSymbol => cls.sourceOfClass
630+
case _ =>
631+
if (denot.is(Module)) denot.moduleClass.source
632+
else if (denot.exists) denot.owner.source
633+
else NoSource
641634
}
642635

643-
644636
/** A symbol related to `sym` that is defined in source code.
645637
*
646638
* @see enclosingSourceSymbols
@@ -771,6 +763,30 @@ object Symbols {
771763
if (assocFile != null || (this.owner is PackageClass) || this.isEffectiveRoot) assocFile
772764
else super.associatedFile
773765

766+
private[this] var mySource: SourceFile = NoSource
767+
768+
final def sourceOfClass(implicit ctx: Context): SourceFile = {
769+
if (!mySource.exists && !denot.is(Package))
770+
// this allows sources to be added in annotations after `sourceOfClass` is first called
771+
mySource = {
772+
val file = associatedFile
773+
if (file != null && file.extension != "class") ctx.getSource(file)
774+
else {
775+
def sourceFromTopLevel(implicit ctx: Context) =
776+
denot.topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match {
777+
case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
778+
case Some(Constant(path: String)) =>
779+
ctx.getSource(path)
780+
case none => NoSource
781+
}
782+
case none => NoSource
783+
}
784+
sourceFromTopLevel(ctx.withPhaseNoLater(ctx.flattenPhase))
785+
}
786+
}//.reporting(res => i"source of $this # $id in ${denot.owner} = $res")
787+
mySource
788+
}
789+
774790
final def classDenot(implicit ctx: Context): ClassDenotation =
775791
denot.asInstanceOf[ClassDenotation]
776792

0 commit comments

Comments
 (0)