Skip to content

Commit b964694

Browse files
committed
Resolve symbol occurrences of select type fields
1 parent 60c336e commit b964694

File tree

5 files changed

+100
-36
lines changed

5 files changed

+100
-36
lines changed

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,16 @@ class ExtractSemanticDB extends Phase:
109109
|| sym.isOldStyleImplicitConversion(forImplicitClassOnly = true)
110110

111111
/** Uses of this symbol where the reference has given span should be excluded from semanticdb */
112-
private def excludeUse(qualifier: Option[Symbol], sym: Symbol)(using Context): Boolean =
113-
!sym.exists
114-
|| excludeDefOrUse(sym)
115-
|| sym.isConstructor && sym.owner.isAnnotation
116-
|| sym == defn.Any_typeCast
117-
|| sym.owner == defn.OpsPackageClass
118-
|| qualifier.exists(excludeQual)
112+
private def excludeUse(qualifier: Option[Symbol], sym: SemanticSymbol)(using Context): Boolean =
113+
sym match
114+
case sym: Symbol =>
115+
!sym.exists
116+
|| excludeDefOrUse(sym)
117+
|| sym.isConstructor && sym.owner.isAnnotation
118+
|| sym == defn.Any_typeCast
119+
|| sym.owner == defn.OpsPackageClass
120+
|| qualifier.exists(excludeQual)
121+
case fake: FakeSymbol => false // do not exclude fake symbols
119122

120123
private def traverseAnnotsOfDefinition(sym: Symbol)(using Context): Unit =
121124
for annot <- sym.annotations do
@@ -232,7 +235,12 @@ class ExtractSemanticDB extends Phase:
232235
val sym = tree.symbol.adjustIfCtorTyparam
233236
if qualSpan.exists && qualSpan.hasLength then
234237
traverse(qual)
235-
registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source)
238+
if (sym != NoSymbol)
239+
registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source)
240+
else
241+
qual.symbol.info.lookupSym(tree.name).foreach(sym =>
242+
registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source)
243+
)
236244
case tree: Import =>
237245
if tree.span.exists && tree.span.hasLength then
238246
traverseChildren(tree)
@@ -329,11 +337,11 @@ class ExtractSemanticDB extends Phase:
329337
occurrences += occ
330338
generated += occ
331339

332-
private def registerUseGuarded(qualSym: Option[Symbol], sym: Symbol, span: Span, treeSource: SourceFile)(using Context) =
340+
private def registerUseGuarded(qualSym: Option[Symbol], sym: SemanticSymbol, span: Span, treeSource: SourceFile)(using Context) =
333341
if !excludeUse(qualSym, sym) && !span.isZeroExtent then
334342
registerUse(sym, span, treeSource)
335343

336-
private def registerUse(sym: Symbol, span: Span, treeSource: SourceFile)(using Context): Unit =
344+
private def registerUse(sym: SemanticSymbol, span: Span, treeSource: SourceFile)(using Context): Unit =
337345
registerUse(sym.symbolName, span, treeSource)
338346

339347
private def registerUse(symbol: String, span: Span, treeSource: SourceFile)(using Context): Unit =

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import core.StdNames.nme
1212
import SymbolInformation.{Kind => k}
1313
import dotty.tools.dotc.util.SourceFile
1414
import dotty.tools.dotc.util.Spans.Span
15+
import dotty.tools.dotc.core.Names.Designator
1516

1617
import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart}
1718

@@ -34,23 +35,30 @@ object Scala3:
3435
val (endLine, endCol) = lineCol(span.end)
3536
Some(Range(startLine, startCol, endLine, endCol))
3637

37-
def namePresentInSource(sym: Symbol, span: Span, source:SourceFile)(using Context): Boolean =
38+
def namePresentInSource(desig: Designator, span: Span, source:SourceFile)(using Context): Boolean =
3839
if !span.exists then false
3940
else
4041
val content = source.content()
4142
val (start, end) =
4243
if content.lift(span.end - 1).exists(_ == '`') then
4344
(span.start + 1, span.end - 1)
4445
else (span.start, span.end)
46+
// println(s"${start}, $end")
4547
val nameInSource = content.slice(start, end).mkString
4648
// for secondary constructors `this`
47-
if sym.isConstructor && nameInSource == nme.THISkw.toString then
48-
true
49-
else
50-
val target =
51-
if sym.isPackageObject then sym.owner
52-
else sym
53-
nameInSource == target.name.stripModuleClassSuffix.lastPart.toString
49+
desig match
50+
case sym: Symbol =>
51+
if sym.isConstructor && nameInSource == nme.THISkw.toString then
52+
true
53+
else
54+
val target =
55+
if sym.isPackageObject then sym.owner
56+
else sym
57+
nameInSource == target.name.stripModuleClassSuffix.lastPart.toString
58+
case name: Name =>
59+
// println(nameInSource)
60+
// println(name.mangledString)
61+
nameInSource == name.mangledString
5462

5563
sealed trait FakeSymbol {
5664
private[Scala3] var sname: Option[String] = None

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

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ class TypeOps:
6464
fakeSymbols.add(sym)
6565

6666
extension (tpe: Type)
67+
def lookupSym(name: Name)(using Context): Option[SemanticSymbol] = {
68+
def loop(tpe: Type): Option[SemanticSymbol] = tpe match
69+
case rt: RefinedType =>
70+
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
71+
case rec: RecType =>
72+
loop(rec.parent)
73+
case AndType(tp1, tp2) =>
74+
loop(tp1).orElse(loop(tp2))
75+
case OrType(tp1, tp2) =>
76+
loop(tp1).orElse(loop(tp2))
77+
case _ =>
78+
None
79+
loop(tpe)
80+
}
81+
6782
def toSemanticSig(using LinkMode, Context, SemanticSymbolBuilder)(sym: Symbol): s.Signature =
6883
def enterParamRef(tpe: Type): Unit =
6984
tpe match {
@@ -241,22 +256,8 @@ class TypeOps:
241256
// when TypeRef refers the refinement of RefinedType e.g.
242257
// TypeRef for `foo.B` in `trait T[A] { val foo: { type B = A } = ???; def bar(b: foo.B) = () }` has NoSymbol
243258
case TypeRef(pre, name: Name) =>
244-
def lookupSym(tpe: Type): Option[SemanticSymbol] = {
245-
tpe match {
246-
case rt: RefinedType =>
247-
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
248-
case rec: RecType =>
249-
lookupSym(rec.parent)
250-
case AndType(tp1, tp2) =>
251-
lookupSym(tp1).orElse(lookupSym(tp2))
252-
case OrType(tp1, tp2) =>
253-
lookupSym(tp1).orElse(lookupSym(tp2))
254-
case _ =>
255-
None
256-
}
257-
}
258259
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
259-
val maybeSym = lookupSym(pre.widen.dealias)
260+
val maybeSym = pre.widen.dealias.lookupSym(name)
260261
maybeSym match
261262
case Some(sym) =>
262263
s.TypeRef(spre, sym.symbolName, Seq.empty)

tests/semanticdb/expect/Advanced.expect.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Structural/*<-advanced::Structural#*/ {
1414
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = new { val x/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
1515
def s3/*<-advanced::Structural#s3().*/: { def m/*<-local6*/(x/*<-local5*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ } = new { def m/*<-local8*/(x/*<-local7*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
1616
def s4/*<-advanced::Structural#s4().*/(a/*<-advanced::Structural#s4().(a)*/: Int/*->scala::Int#*/): { val x/*<-local11*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
17-
trait T/*<-advanced::Structural#T#*/[A/*<-advanced::Structural#T#[A]*/] { val foo/*<-advanced::Structural#T#foo.*/: { type B/*<-local12*/ = A/*->advanced::Structural#T#[A]*/ } = ???/*->scala::Predef.`???`().*/; def bar/*<-advanced::Structural#T#bar().*/(b/*<-advanced::Structural#T#bar().(b)*/: foo/*->advanced::Structural#T#foo.*/.B) = () } // from tests/pos/t8177e.scala
17+
trait T/*<-advanced::Structural#T#*/[A/*<-advanced::Structural#T#[A]*/] { val foo/*<-advanced::Structural#T#foo.*/: { type B/*<-local12*/ = A/*->advanced::Structural#T#[A]*/ } = ???/*->scala::Predef.`???`().*/; def bar/*<-advanced::Structural#T#bar().*/(b/*<-advanced::Structural#T#bar().(b)*/: foo/*->advanced::Structural#T#foo.*/.B/*->local12*/) = () } // from tests/pos/t8177e.scala
1818
}
1919

2020
class Wildcards/*<-advanced::Wildcards#*/ {
@@ -45,7 +45,7 @@ object Test/*<-advanced::Test.*/ {
4545

4646
// see: https://github.com/lampepfl/dotty/pull/14608#discussion_r835642563
4747
lazy val foo/*<-advanced::Test.foo.*/: (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local16*/ = Int/*->scala::Int#*/ }) &/*->scala::`&`#*/ (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local17*/ = Int/*->scala::Int#*/; val a/*<-local18*/: A/*->local17*/ }) = ???/*->scala::Predef.`???`().*/
48-
def bar/*<-advanced::Test.bar().*/: foo/*->advanced::Test.foo.*/.A = foo/*->advanced::Test.foo.*/.a
48+
def bar/*<-advanced::Test.bar().*/: foo/*->advanced::Test.foo.*/.A/*->local19*/ = foo/*->advanced::Test.foo.*/.a
4949
}
5050

5151

tests/semanticdb/metac.expect

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Uri => Advanced.scala
4949
Text => empty
5050
Language => Scala
5151
Symbols => 62 entries
52-
Occurrences => 130 entries
52+
Occurrences => 132 entries
5353
Synthetics => 4 entries
5454

5555
Symbols:
@@ -169,6 +169,7 @@ Occurrences:
169169
[16:50..16:53): bar <- advanced/Structural#T#bar().
170170
[16:54..16:55): b <- advanced/Structural#T#bar().(b)
171171
[16:57..16:60): foo -> advanced/Structural#T#foo.
172+
[16:61..16:62): B -> local12
172173
[19:6..19:15): Wildcards <- advanced/Wildcards#
173174
[20:6..20:8): e1 <- advanced/Wildcards#e1().
174175
[20:10..20:14): List -> scala/package.List#
@@ -230,6 +231,7 @@ Occurrences:
230231
[46:106..46:109): ??? -> scala/Predef.`???`().
231232
[47:6..47:9): bar <- advanced/Test.bar().
232233
[47:11..47:14): foo -> advanced/Test.foo.
234+
[47:15..47:16): A -> local19
233235
[47:19..47:22): foo -> advanced/Test.foo.
234236
[52:6..52:13): HKClass <- advanced/HKClass#
235237
[52:14..52:15): F <- advanced/HKClass#[F]
@@ -254,6 +256,51 @@ Synthetics:
254256
[31:12..31:16):s.s3 => reflectiveSelectable(*)
255257
[47:19..47:24):foo.a => *[foo.A]
256258

259+
expect/Aho.scala
260+
----------------
261+
262+
Summary:
263+
Schema => SemanticDB v4
264+
Uri => Aho.scala
265+
Text => empty
266+
Language => Scala
267+
Symbols => 8 entries
268+
Occurrences => 18 entries
269+
Synthetics => 1 entries
270+
271+
Symbols:
272+
aho/Aho$package. => final package object aho extends Object { self: aho.type => +3 decls }
273+
aho/Aho$package.bar(). => method bar => foo.AB
274+
aho/Aho$package.foo. => lazy val method foo Selectable { abstract type AB = Int } & Selectable { abstract field a: local4; abstract type AB = Int }
275+
local0 => type AB = Int
276+
local1 => type AB = Int
277+
local2 => abstract val method a AB
278+
local3 => abstract type AB = Int
279+
local5 => abstract field a: AB
280+
281+
Occurrences:
282+
[0:8..0:11): aho <- aho/
283+
[2:9..2:12): foo <- aho/Aho$package.foo.
284+
[2:15..2:22): reflect -> scala/reflect/
285+
[2:23..2:33): Selectable -> scala/reflect/Selectable#
286+
[2:41..2:43): AB <- local0
287+
[2:46..2:49): Int -> scala/Int#
288+
[2:53..2:54): & -> scala/`&`#
289+
[2:56..2:63): reflect -> scala/reflect/
290+
[2:64..2:74): Selectable -> scala/reflect/Selectable#
291+
[2:82..2:84): AB <- local1
292+
[2:87..2:90): Int -> scala/Int#
293+
[2:96..2:97): a <- local2
294+
[2:99..2:101): AB -> local1
295+
[2:107..2:110): ??? -> scala/Predef.`???`().
296+
[3:4..3:7): bar <- aho/Aho$package.bar().
297+
[3:9..3:12): foo -> aho/Aho$package.foo.
298+
[3:13..3:15): AB -> local3
299+
[3:18..3:21): foo -> aho/Aho$package.foo.
300+
301+
Synthetics:
302+
[3:18..3:23):foo.a => *[foo.AB]
303+
257304
expect/Annotations.scala
258305
------------------------
259306

0 commit comments

Comments
 (0)