Skip to content

Commit 56c8e7b

Browse files
committed
Support TypeApplication in Synthetic
1 parent d519682 commit 56c8e7b

File tree

3 files changed

+171
-8
lines changed

3 files changed

+171
-8
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,11 @@ class ExtractSemanticDB extends Phase:
245245
registerUseGuarded(None, alt.symbol.companionClass, sel.imported.span, tree.source)
246246
case tree: Inlined =>
247247
traverse(tree.call)
248+
249+
case tree: TypeApply =>
250+
synth.tryFindSynthetic(tree).foreach(synthetics.addOne)
251+
traverseChildren(tree)
252+
248253
case tree: TypeTree =>
249254
tree.typeOpt match
250255
// Any types could be appear inside of `TypeTree`, but

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,45 @@ import scala.collection.mutable
1111
class SyntheticsExtractor:
1212
import Scala3.{_, given}
1313

14+
val visited = collection.mutable.HashSet[Tree]()
15+
1416
def tryFindSynthetic(tree: Tree)(using Context, SemanticSymbolBuilder, TypeOps): Option[s.Synthetic] =
1517
extension (synth: s.Synthetic)
1618
def toOpt: Some[s.Synthetic] = Some(synth)
1719

18-
if tree.span.isSynthetic then
20+
val forSynthetic = tree match // not yet supported (for synthetics)
21+
case tree: Apply if isForSynthetic(tree) => true
22+
case tree: TypeApply if isForSynthetic(tree) => true
23+
case _ => false
24+
25+
if visited.contains(tree) || forSynthetic then None
26+
else
1927
tree match
20-
case tree: Apply if isForSynthetic(tree) =>
21-
None // not yet supported (for synthetics)
28+
case tree: Apply if isForSynthetic(tree) => None
29+
case tree: TypeApply
30+
if tree.span.isSynthetic &&
31+
tree.args.forall(arg => !arg.symbol.is(Scala2x)) &&
32+
!tree.span.isZeroExtent =>
33+
visited.add(tree)
34+
val fnTree = tree.fun match
35+
// Something like `List.apply[Int](1,2,3)`
36+
case select @ Select(qual, _) if isSyntheticName(select) =>
37+
s.SelectTree(
38+
s.OriginalTree(range(qual.span, tree.source)),
39+
Some(select.toSemanticId)
40+
)
41+
case _ =>
42+
s.OriginalTree(
43+
range(tree.fun.span, tree.source)
44+
)
45+
val targs = tree.args.map(targ => targ.tpe.toSemanticType(targ.symbol)(using LinkMode.SymlinkChildren))
46+
s.Synthetic(
47+
range(tree.span, tree.source),
48+
s.TypeApplyTree(
49+
fnTree, targs
50+
)
51+
).toOpt
52+
2253
case tree: Apply
2354
if tree.args.nonEmpty &&
2455
tree.args.forall(arg =>
@@ -46,7 +77,6 @@ class SyntheticsExtractor:
4677
).toOpt
4778

4879
case _ => None
49-
else None
5080

5181
private given TreeOps: AnyRef with
5282
extension (tree: Tree)
@@ -95,4 +125,15 @@ class SyntheticsExtractor:
95125
case select: Select => isForComprehensionSyntheticName(select)
96126
case _ => false
97127

128+
private def isSyntheticName(select: Select): Boolean =
129+
select.span.toSynthetic == select.qualifier.span.toSynthetic && (
130+
select.name == nme.apply ||
131+
select.name == nme.update ||
132+
select.name == nme.foreach ||
133+
select.name == nme.withFilter ||
134+
select.name == nme.flatMap ||
135+
select.name == nme.map ||
136+
select.name == nme.unapplySeq ||
137+
select.name == nme.unapply)
138+
98139
end SyntheticsExtractor

0 commit comments

Comments
 (0)