Skip to content

Commit a3c0bef

Browse files
authored
fix: [SemanticDB] Emit SymbolInformation and Occurrence for anonymous class (#15865)
fix #15852 This commit enables ExtractSemanticDB to emit SymbolInformation and SymbolOccurrence of anonymous classes. e.g. ```scala trait Foo: def foo: String val foo1: Foo = new Foo { def foo: String = ??? } val foo2: Foo = new { def foo: String = ??? } ``` While Scala2 semanticdb-plugin emit symbols for the anonymous class. Lack of the symbol information / occurrence led Metals not being able to find those anonymous classes as implementations by `go-to-implementation` from `trait Foo`. see: scalameta/metals#4246
2 parents 8c8eae9 + 3604d3c commit a3c0bef

File tree

9 files changed

+63
-19
lines changed

9 files changed

+63
-19
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ class ExtractSemanticDB extends Phase:
8181
private def excludeDef(sym: Symbol)(using Context): Boolean =
8282
!sym.exists
8383
|| sym.isLocalDummy
84-
|| sym.is(Synthetic)
84+
// basically do not register synthetic symbols, except anonymous class
85+
// `new Foo { ... }`
86+
|| (sym.is(Synthetic) && !sym.isAnonymousClass)
8587
|| sym.isSetter
8688
|| sym.isOldStyleImplicitConversion(forImplicitClassOnly = true)
8789
|| sym.owner.isGivenInstanceSummoner
@@ -178,7 +180,7 @@ class ExtractSemanticDB extends Phase:
178180
if !excludeChildren(tree.symbol) then
179181
traverseChildren(tree)
180182
}
181-
if !excludeDef(tree.symbol) && tree.span.hasLength then
183+
if !excludeDef(tree.symbol) && (tree.span.hasLength || tree.symbol.isAnonymousClass) then
182184
registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree), tree.source)
183185
val privateWithin = tree.symbol.privateWithin
184186
if privateWithin.exists then
@@ -355,7 +357,7 @@ class ExtractSemanticDB extends Phase:
355357
else
356358
Span(span.start)
357359

358-
if namePresentInSource(sym, span, treeSource) then
360+
if namePresentInSource(sym, span, treeSource) || sym.isAnonymousClass then
359361
registerOccurrence(sname, finalSpan, SymbolOccurrence.Role.DEFINITION, treeSource)
360362
if !sym.is(Package) then
361363
registerSymbol(sym, symkinds)

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ object Scala3:
4343
if content.lift(span.end - 1).exists(_ == '`') then
4444
(span.start + 1, span.end - 1)
4545
else (span.start, span.end)
46-
// println(s"${start}, $end")
4746
val nameInSource = content.slice(start, end).mkString
4847
// for secondary constructors `this`
4948
desig match

tests/semanticdb/expect/Advanced.expect.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class C/*<-advanced::C#*/[T/*<-advanced::C#[T]*/] {
1111

1212
class Structural/*<-advanced::Structural#*/ {
1313
def s1/*<-advanced::Structural#s1().*/: { val x/*<-local0*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
14-
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = new { val x/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
15-
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.`???`().*/ }
14+
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = /*<-local3*/new { val x/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
15+
def s3/*<-advanced::Structural#s3().*/: { def m/*<-local6*/(x/*<-local5*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ } = /*<-local9*/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.`???`().*/
1717
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
}

tests/semanticdb/expect/Anonymous.expect.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@ class Anonymous/*<-example::Anonymous#*/ {
1616
}
1717

1818
trait Foo/*<-example::Anonymous#Foo#*/
19-
val foo/*<-example::Anonymous#foo.*/ = new Foo/*->example::Anonymous#Foo#*/ {}
19+
val foo/*<-example::Anonymous#foo.*/ = /*<-local1*/new Foo/*->example::Anonymous#Foo#*/ {}
20+
21+
trait Bar/*<-example::Anonymous#Bar#*/:
22+
def bar/*<-example::Anonymous#Bar#bar().*/: String/*->scala::Predef.String#*/
23+
val bar1/*<-example::Anonymous#bar1.*/: Bar/*->example::Anonymous#Bar#*/ = /*<-local4*/new Bar/*->example::Anonymous#Bar#*/ { def bar/*<-local3*/: String/*->scala::Predef.String#*/ = ???/*->scala::Predef.`???`().*/ }
24+
val bar2/*<-example::Anonymous#bar2.*/: Bar/*->example::Anonymous#Bar#*/ = /*<-local7*/new { def bar/*<-local6*/: String/*->scala::Predef.String#*/ = ???/*->scala::Predef.`???`().*/ }
2025
}

tests/semanticdb/expect/Anonymous.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ class Anonymous {
1717

1818
trait Foo
1919
val foo = new Foo {}
20+
21+
trait Bar:
22+
def bar: String
23+
val bar1: Bar = new Bar { def bar: String = ??? }
24+
val bar2: Bar = new { def bar: String = ??? }
2025
}

tests/semanticdb/expect/Classes.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class C12/*<-classes::C12#*/ {
4646
}
4747

4848
object N/*<-classes::N.*/ {
49-
val anonClass/*<-classes::N.anonClass.*/ = new C7/*->classes::C7#*/(42) {
49+
val anonClass/*<-classes::N.anonClass.*/ = /*<-local1*/new C7/*->classes::C7#*/(42) {
5050
val local/*<-local0*/ = ???/*->scala::Predef.`???`().*/
5151
}
5252
val anonFun/*<-classes::N.anonFun.*/ = List/*->scala::package.List.*/(1).map/*->scala::collection::immutable::List#map().*/ { i/*<-local3*/ =>

tests/semanticdb/expect/Traits.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ trait T/*<-traits::T#*/ {
66

77
sealed trait U/*<-traits::U#*/
88
object U/*<-traits::U.*/ {
9-
def u/*<-traits::U.u().*/: U/*->traits::U#*/ = new U/*->traits::U#*/ {}
9+
def u/*<-traits::U.u().*/: U/*->traits::U#*/ = /*<-local0*/new U/*->traits::U#*/ {}
1010
}
1111

1212
class C/*<-traits::C#*/

tests/semanticdb/expect/semanticdb-Types.expect.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ object Test/*<-types::Test.*/ {
6262
val compoundType1/*<-types::Test.C#compoundType1.*/: { def k/*<-local0*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
6363
val compoundType2/*<-types::Test.C#compoundType2.*/: M/*->types::Test.M#*/ with N/*->types::Test.N#*/ = ???/*->scala::Predef.`???`().*/
6464
val compoundType3/*<-types::Test.C#compoundType3.*/: M/*->types::Test.M#*/ with N/*->types::Test.N#*/ { def k/*<-local1*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
65-
val compoundType4/*<-types::Test.C#compoundType4.*/ = new { def k/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
66-
val compoundType5/*<-types::Test.C#compoundType5.*/ = new M/*->types::Test.M#*/ with N/*->types::Test.N#*/
67-
val compoundType6/*<-types::Test.C#compoundType6.*/ = new M/*->types::Test.M#*/ with N/*->types::Test.N#*/ { def k/*<-local7*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
65+
val compoundType4/*<-types::Test.C#compoundType4.*/ = /*<-local3*/new { def k/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
66+
val compoundType5/*<-types::Test.C#compoundType5.*/ = /*<-local5*/new M/*->types::Test.M#*/ with N/*->types::Test.N#*/
67+
val compoundType6/*<-types::Test.C#compoundType6.*/ = /*<-local8*/new M/*->types::Test.M#*/ with N/*->types::Test.N#*/ { def k/*<-local7*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
6868

6969
val annType1/*<-types::Test.C#annType1.*/: T/*->types::T#*/ @ann(42) = ???/*->scala::Predef.`???`().*/
7070
val annType2/*<-types::Test.C#annType2.*/: T/*->types::T#*/ @ann1/*->types::ann1#*/ @ann2/*->types::ann2#*/ = ???/*->scala::Predef.`???`().*/

tests/semanticdb/metac.expect

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Uri => Advanced.scala
4949
Text => empty
5050
Language => Scala
5151
Symbols => 60 entries
52-
Occurrences => 132 entries
52+
Occurrences => 134 entries
5353
Synthetics => 3 entries
5454

5555
Symbols:
@@ -139,6 +139,7 @@ Occurrences:
139139
[13:6..13:8): s2 <- advanced/Structural#s2().
140140
[13:16..13:17): x <- local1
141141
[13:19..13:22): Int -> scala/Int#
142+
[13:27..13:27): <- local3
142143
[13:37..13:38): x <- local2
143144
[13:40..13:43): Int -> scala/Int#
144145
[13:46..13:49): ??? -> scala/Predef.`???`().
@@ -147,6 +148,7 @@ Occurrences:
147148
[14:18..14:19): x <- local5
148149
[14:21..14:24): Int -> scala/Int#
149150
[14:27..14:30): Int -> scala/Int#
151+
[14:35..14:35): <- local9
150152
[14:45..14:46): m <- local8
151153
[14:47..14:48): x <- local7
152154
[14:50..14:53): Int -> scala/Int#
@@ -351,15 +353,20 @@ Schema => SemanticDB v4
351353
Uri => Anonymous.scala
352354
Text => empty
353355
Language => Scala
354-
Symbols => 14 entries
355-
Occurrences => 30 entries
356+
Symbols => 23 entries
357+
Occurrences => 47 entries
356358
Synthetics => 2 entries
357359

358360
Symbols:
359-
example/Anonymous# => class Anonymous extends Object { self: Anonymous & Anonymous => +6 decls }
361+
example/Anonymous# => class Anonymous extends Object { self: Anonymous & Anonymous => +9 decls }
362+
example/Anonymous#Bar# => trait Bar extends Object { self: Bar => +2 decls }
363+
example/Anonymous#Bar#`<init>`(). => primary ctor <init> (): Bar
364+
example/Anonymous#Bar#bar(). => abstract method bar => String
360365
example/Anonymous#Foo# => trait Foo extends Object { self: Foo => +1 decls }
361366
example/Anonymous#Foo#`<init>`(). => primary ctor <init> (): Foo
362367
example/Anonymous#`<init>`(). => primary ctor <init> (): Anonymous
368+
example/Anonymous#bar1. => val method bar1 Bar
369+
example/Anonymous#bar2. => val method bar2 Bar
363370
example/Anonymous#foo. => val method foo Foo
364371
example/Anonymous#locally(). => method locally [typeparam A ](param x: A): A
365372
example/Anonymous#locally().(x) => param x: A
@@ -370,6 +377,10 @@ example/Anonymous#m1().[T][_] => type _
370377
example/Anonymous#m2(). => method m2 => Map[_, List[_] forSome { type _ }] forSome { type _ }
371378
local0 => val local x: Function1[Int, Int]
372379
local1 => final class $anon extends Object with Foo { self: $anon => +1 decls }
380+
local3 => method bar => String <: example/Anonymous#Bar#bar().
381+
local4 => final class $anon extends Object with Bar { self: $anon => +2 decls }
382+
local6 => method bar => String <: example/Anonymous#Bar#bar().
383+
local7 => final class $anon extends Object with Bar { self: $anon => +2 decls }
373384

374385
Occurrences:
375386
[0:8..0:15): example <- example/
@@ -401,7 +412,24 @@ Occurrences:
401412
[14:29..14:32): ??? -> scala/Predef.`???`().
402413
[17:8..17:11): Foo <- example/Anonymous#Foo#
403414
[18:6..18:9): foo <- example/Anonymous#foo.
415+
[18:12..18:12): <- local1
404416
[18:16..18:19): Foo -> example/Anonymous#Foo#
417+
[20:8..20:11): Bar <- example/Anonymous#Bar#
418+
[21:8..21:11): bar <- example/Anonymous#Bar#bar().
419+
[21:13..21:19): String -> scala/Predef.String#
420+
[22:6..22:10): bar1 <- example/Anonymous#bar1.
421+
[22:12..22:15): Bar -> example/Anonymous#Bar#
422+
[22:18..22:18): <- local4
423+
[22:22..22:25): Bar -> example/Anonymous#Bar#
424+
[22:32..22:35): bar <- local3
425+
[22:37..22:43): String -> scala/Predef.String#
426+
[22:46..22:49): ??? -> scala/Predef.`???`().
427+
[23:6..23:10): bar2 <- example/Anonymous#bar2.
428+
[23:12..23:15): Bar -> example/Anonymous#Bar#
429+
[23:18..23:18): <- local7
430+
[23:28..23:31): bar <- local6
431+
[23:33..23:39): String -> scala/Predef.String#
432+
[23:42..23:45): ??? -> scala/Predef.`???`().
405433

406434
Synthetics:
407435
[10:2..10:9):locally => *[Unit]
@@ -440,7 +468,7 @@ Uri => Classes.scala
440468
Text => empty
441469
Language => Scala
442470
Symbols => 109 entries
443-
Occurrences => 113 entries
471+
Occurrences => 114 entries
444472
Synthetics => 2 entries
445473

446474
Symbols:
@@ -658,6 +686,7 @@ Occurrences:
658686
[43:101..43:104): ??? -> scala/Predef.`???`().
659687
[47:7..47:8): N <- classes/N.
660688
[48:6..48:15): anonClass <- classes/N.anonClass.
689+
[48:18..48:18): <- local1
661690
[48:22..48:24): C7 -> classes/C7#
662691
[49:8..49:13): local <- local0
663692
[49:16..49:19): ??? -> scala/Predef.`???`().
@@ -3423,7 +3452,7 @@ Uri => Traits.scala
34233452
Text => empty
34243453
Language => Scala
34253454
Symbols => 13 entries
3426-
Occurrences => 12 entries
3455+
Occurrences => 13 entries
34273456

34283457
Symbols:
34293458
local0 => final class $anon extends Object with U { self: $anon => +1 decls }
@@ -3448,6 +3477,7 @@ Occurrences:
34483477
[7:7..7:8): U <- traits/U.
34493478
[8:6..8:7): u <- traits/U.u().
34503479
[8:9..8:10): U -> traits/U#
3480+
[8:13..8:13): <- local0
34513481
[8:17..8:18): U -> traits/U#
34523482
[11:6..11:7): C <- traits/C#
34533483
[12:6..12:7): V <- traits/V#
@@ -4532,7 +4562,7 @@ Uri => semanticdb-Types.scala
45324562
Text => empty
45334563
Language => Scala
45344564
Symbols => 144 entries
4535-
Occurrences => 225 entries
4565+
Occurrences => 228 entries
45364566
Synthetics => 1 entries
45374567

45384568
Symbols:
@@ -4790,13 +4820,16 @@ Occurrences:
47904820
[63:41..63:44): Int -> scala/Int#
47914821
[63:49..63:52): ??? -> scala/Predef.`???`().
47924822
[64:8..64:21): compoundType4 <- types/Test.C#compoundType4.
4823+
[64:24..64:24): <- local3
47934824
[64:34..64:35): k <- local2
47944825
[64:37..64:40): Int -> scala/Int#
47954826
[64:43..64:46): ??? -> scala/Predef.`???`().
47964827
[65:8..65:21): compoundType5 <- types/Test.C#compoundType5.
4828+
[65:24..65:24): <- local5
47974829
[65:28..65:29): M -> types/Test.M#
47984830
[65:35..65:36): N -> types/Test.N#
47994831
[66:8..66:21): compoundType6 <- types/Test.C#compoundType6.
4832+
[66:24..66:24): <- local8
48004833
[66:28..66:29): M -> types/Test.M#
48014834
[66:35..66:36): N -> types/Test.N#
48024835
[66:43..66:44): k <- local7

0 commit comments

Comments
 (0)