Skip to content

fix: [SemanticDB] Emit SymbolInformation and Occurrence for anonymous class #15865

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ class ExtractSemanticDB extends Phase:
private def excludeDef(sym: Symbol)(using Context): Boolean =
!sym.exists
|| sym.isLocalDummy
|| sym.is(Synthetic)
// basically do not register synthetic symbols, except anonymous class
// `new Foo { ... }`
|| (sym.is(Synthetic) && !sym.isAnonymousClass)
|| sym.isSetter
|| sym.isOldStyleImplicitConversion(forImplicitClassOnly = true)
|| sym.owner.isGivenInstanceSummoner
Expand Down Expand Up @@ -178,7 +180,7 @@ class ExtractSemanticDB extends Phase:
if !excludeChildren(tree.symbol) then
traverseChildren(tree)
}
if !excludeDef(tree.symbol) && tree.span.hasLength then
if !excludeDef(tree.symbol) && (tree.span.hasLength || tree.symbol.isAnonymousClass) then
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change seems kind of monkey patch, maybe we should refactor ExtractSemanticDB at some point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A redesign would be welcome - The only specification I used in the original implementation was comparing with the expect files from scalameta's semanticdb tests, so everything grew organically around that

registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree), tree.source)
val privateWithin = tree.symbol.privateWithin
if privateWithin.exists then
Expand Down Expand Up @@ -355,7 +357,7 @@ class ExtractSemanticDB extends Phase:
else
Span(span.start)

if namePresentInSource(sym, span, treeSource) then
if namePresentInSource(sym, span, treeSource) || sym.isAnonymousClass then
registerOccurrence(sname, finalSpan, SymbolOccurrence.Role.DEFINITION, treeSource)
if !sym.is(Package) then
registerSymbol(sym, symkinds)
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ object Scala3:
if content.lift(span.end - 1).exists(_ == '`') then
(span.start + 1, span.end - 1)
else (span.start, span.end)
// println(s"${start}, $end")
val nameInSource = content.slice(start, end).mkString
// for secondary constructors `this`
desig match
Expand Down
4 changes: 2 additions & 2 deletions tests/semanticdb/expect/Advanced.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class C/*<-advanced::C#*/[T/*<-advanced::C#[T]*/] {

class Structural/*<-advanced::Structural#*/ {
def s1/*<-advanced::Structural#s1().*/: { val x/*<-local0*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = new { val x/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
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.`???`().*/ }
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = /*<-local3*/new { val x/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
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.`???`().*/ }
def s4/*<-advanced::Structural#s4().*/(a/*<-advanced::Structural#s4().(a)*/: Int/*->scala::Int#*/): { val x/*<-local11*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
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
}
Expand Down
7 changes: 6 additions & 1 deletion tests/semanticdb/expect/Anonymous.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ class Anonymous/*<-example::Anonymous#*/ {
}

trait Foo/*<-example::Anonymous#Foo#*/
val foo/*<-example::Anonymous#foo.*/ = new Foo/*->example::Anonymous#Foo#*/ {}
val foo/*<-example::Anonymous#foo.*/ = /*<-local1*/new Foo/*->example::Anonymous#Foo#*/ {}

trait Bar/*<-example::Anonymous#Bar#*/:
def bar/*<-example::Anonymous#Bar#bar().*/: String/*->scala::Predef.String#*/
val bar1/*<-example::Anonymous#bar1.*/: Bar/*->example::Anonymous#Bar#*/ = /*<-local4*/new Bar/*->example::Anonymous#Bar#*/ { def bar/*<-local3*/: String/*->scala::Predef.String#*/ = ???/*->scala::Predef.`???`().*/ }
val bar2/*<-example::Anonymous#bar2.*/: Bar/*->example::Anonymous#Bar#*/ = /*<-local7*/new { def bar/*<-local6*/: String/*->scala::Predef.String#*/ = ???/*->scala::Predef.`???`().*/ }
}
5 changes: 5 additions & 0 deletions tests/semanticdb/expect/Anonymous.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ class Anonymous {

trait Foo
val foo = new Foo {}

trait Bar:
def bar: String
val bar1: Bar = new Bar { def bar: String = ??? }
val bar2: Bar = new { def bar: String = ??? }
}
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/Classes.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class C12/*<-classes::C12#*/ {
}

object N/*<-classes::N.*/ {
val anonClass/*<-classes::N.anonClass.*/ = new C7/*->classes::C7#*/(42) {
val anonClass/*<-classes::N.anonClass.*/ = /*<-local1*/new C7/*->classes::C7#*/(42) {
val local/*<-local0*/ = ???/*->scala::Predef.`???`().*/
}
val anonFun/*<-classes::N.anonFun.*/ = List/*->scala::package.List.*/(1).map/*->scala::collection::immutable::List#map().*/ { i/*<-local3*/ =>
Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/Traits.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ trait T/*<-traits::T#*/ {

sealed trait U/*<-traits::U#*/
object U/*<-traits::U.*/ {
def u/*<-traits::U.u().*/: U/*->traits::U#*/ = new U/*->traits::U#*/ {}
def u/*<-traits::U.u().*/: U/*->traits::U#*/ = /*<-local0*/new U/*->traits::U#*/ {}
}

class C/*<-traits::C#*/
Expand Down
6 changes: 3 additions & 3 deletions tests/semanticdb/expect/semanticdb-Types.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ object Test/*<-types::Test.*/ {
val compoundType1/*<-types::Test.C#compoundType1.*/: { def k/*<-local0*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
val compoundType2/*<-types::Test.C#compoundType2.*/: M/*->types::Test.M#*/ with N/*->types::Test.N#*/ = ???/*->scala::Predef.`???`().*/
val compoundType3/*<-types::Test.C#compoundType3.*/: M/*->types::Test.M#*/ with N/*->types::Test.N#*/ { def k/*<-local1*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
val compoundType4/*<-types::Test.C#compoundType4.*/ = new { def k/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
val compoundType5/*<-types::Test.C#compoundType5.*/ = new M/*->types::Test.M#*/ with N/*->types::Test.N#*/
val compoundType6/*<-types::Test.C#compoundType6.*/ = new M/*->types::Test.M#*/ with N/*->types::Test.N#*/ { def k/*<-local7*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
val compoundType4/*<-types::Test.C#compoundType4.*/ = /*<-local3*/new { def k/*<-local2*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
val compoundType5/*<-types::Test.C#compoundType5.*/ = /*<-local5*/new M/*->types::Test.M#*/ with N/*->types::Test.N#*/
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.`???`().*/ }

val annType1/*<-types::Test.C#annType1.*/: T/*->types::T#*/ @ann(42) = ???/*->scala::Predef.`???`().*/
val annType2/*<-types::Test.C#annType2.*/: T/*->types::T#*/ @ann1/*->types::ann1#*/ @ann2/*->types::ann2#*/ = ???/*->scala::Predef.`???`().*/
Expand Down
47 changes: 40 additions & 7 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Uri => Advanced.scala
Text => empty
Language => Scala
Symbols => 60 entries
Occurrences => 132 entries
Occurrences => 134 entries
Synthetics => 3 entries

Symbols:
Expand Down Expand Up @@ -139,6 +139,7 @@ Occurrences:
[13:6..13:8): s2 <- advanced/Structural#s2().
[13:16..13:17): x <- local1
[13:19..13:22): Int -> scala/Int#
[13:27..13:27): <- local3
[13:37..13:38): x <- local2
[13:40..13:43): Int -> scala/Int#
[13:46..13:49): ??? -> scala/Predef.`???`().
Expand All @@ -147,6 +148,7 @@ Occurrences:
[14:18..14:19): x <- local5
[14:21..14:24): Int -> scala/Int#
[14:27..14:30): Int -> scala/Int#
[14:35..14:35): <- local9
[14:45..14:46): m <- local8
[14:47..14:48): x <- local7
[14:50..14:53): Int -> scala/Int#
Expand Down Expand Up @@ -351,15 +353,20 @@ Schema => SemanticDB v4
Uri => Anonymous.scala
Text => empty
Language => Scala
Symbols => 14 entries
Occurrences => 30 entries
Symbols => 23 entries
Occurrences => 47 entries
Synthetics => 2 entries

Symbols:
example/Anonymous# => class Anonymous extends Object { self: Anonymous & Anonymous => +6 decls }
example/Anonymous# => class Anonymous extends Object { self: Anonymous & Anonymous => +9 decls }
example/Anonymous#Bar# => trait Bar extends Object { self: Bar => +2 decls }
example/Anonymous#Bar#`<init>`(). => primary ctor <init> (): Bar
example/Anonymous#Bar#bar(). => abstract method bar => String
example/Anonymous#Foo# => trait Foo extends Object { self: Foo => +1 decls }
example/Anonymous#Foo#`<init>`(). => primary ctor <init> (): Foo
example/Anonymous#`<init>`(). => primary ctor <init> (): Anonymous
example/Anonymous#bar1. => val method bar1 Bar
example/Anonymous#bar2. => val method bar2 Bar
example/Anonymous#foo. => val method foo Foo
example/Anonymous#locally(). => method locally [typeparam A ](param x: A): A
example/Anonymous#locally().(x) => param x: A
Expand All @@ -370,6 +377,10 @@ example/Anonymous#m1().[T][_] => type _
example/Anonymous#m2(). => method m2 => Map[_, List[_] forSome { type _ }] forSome { type _ }
local0 => val local x: Function1[Int, Int]
local1 => final class $anon extends Object with Foo { self: $anon => +1 decls }
local3 => method bar => String <: example/Anonymous#Bar#bar().
local4 => final class $anon extends Object with Bar { self: $anon => +2 decls }
local6 => method bar => String <: example/Anonymous#Bar#bar().
local7 => final class $anon extends Object with Bar { self: $anon => +2 decls }

Occurrences:
[0:8..0:15): example <- example/
Expand Down Expand Up @@ -401,7 +412,24 @@ Occurrences:
[14:29..14:32): ??? -> scala/Predef.`???`().
[17:8..17:11): Foo <- example/Anonymous#Foo#
[18:6..18:9): foo <- example/Anonymous#foo.
[18:12..18:12): <- local1
[18:16..18:19): Foo -> example/Anonymous#Foo#
[20:8..20:11): Bar <- example/Anonymous#Bar#
[21:8..21:11): bar <- example/Anonymous#Bar#bar().
[21:13..21:19): String -> scala/Predef.String#
[22:6..22:10): bar1 <- example/Anonymous#bar1.
[22:12..22:15): Bar -> example/Anonymous#Bar#
[22:18..22:18): <- local4
[22:22..22:25): Bar -> example/Anonymous#Bar#
[22:32..22:35): bar <- local3
[22:37..22:43): String -> scala/Predef.String#
[22:46..22:49): ??? -> scala/Predef.`???`().
[23:6..23:10): bar2 <- example/Anonymous#bar2.
[23:12..23:15): Bar -> example/Anonymous#Bar#
[23:18..23:18): <- local7
[23:28..23:31): bar <- local6
[23:33..23:39): String -> scala/Predef.String#
[23:42..23:45): ??? -> scala/Predef.`???`().

Synthetics:
[10:2..10:9):locally => *[Unit]
Expand Down Expand Up @@ -440,7 +468,7 @@ Uri => Classes.scala
Text => empty
Language => Scala
Symbols => 109 entries
Occurrences => 113 entries
Occurrences => 114 entries
Synthetics => 2 entries

Symbols:
Expand Down Expand Up @@ -658,6 +686,7 @@ Occurrences:
[43:101..43:104): ??? -> scala/Predef.`???`().
[47:7..47:8): N <- classes/N.
[48:6..48:15): anonClass <- classes/N.anonClass.
[48:18..48:18): <- local1
[48:22..48:24): C7 -> classes/C7#
[49:8..49:13): local <- local0
[49:16..49:19): ??? -> scala/Predef.`???`().
Expand Down Expand Up @@ -3423,7 +3452,7 @@ Uri => Traits.scala
Text => empty
Language => Scala
Symbols => 13 entries
Occurrences => 12 entries
Occurrences => 13 entries

Symbols:
local0 => final class $anon extends Object with U { self: $anon => +1 decls }
Expand All @@ -3448,6 +3477,7 @@ Occurrences:
[7:7..7:8): U <- traits/U.
[8:6..8:7): u <- traits/U.u().
[8:9..8:10): U -> traits/U#
[8:13..8:13): <- local0
[8:17..8:18): U -> traits/U#
[11:6..11:7): C <- traits/C#
[12:6..12:7): V <- traits/V#
Expand Down Expand Up @@ -4532,7 +4562,7 @@ Uri => semanticdb-Types.scala
Text => empty
Language => Scala
Symbols => 144 entries
Occurrences => 225 entries
Occurrences => 228 entries
Synthetics => 1 entries

Symbols:
Expand Down Expand Up @@ -4790,13 +4820,16 @@ Occurrences:
[63:41..63:44): Int -> scala/Int#
[63:49..63:52): ??? -> scala/Predef.`???`().
[64:8..64:21): compoundType4 <- types/Test.C#compoundType4.
[64:24..64:24): <- local3
[64:34..64:35): k <- local2
[64:37..64:40): Int -> scala/Int#
[64:43..64:46): ??? -> scala/Predef.`???`().
[65:8..65:21): compoundType5 <- types/Test.C#compoundType5.
[65:24..65:24): <- local5
[65:28..65:29): M -> types/Test.M#
[65:35..65:36): N -> types/Test.N#
[66:8..66:21): compoundType6 <- types/Test.C#compoundType6.
[66:24..66:24): <- local8
[66:28..66:29): M -> types/Test.M#
[66:35..66:36): N -> types/Test.N#
[66:43..66:44): k <- local7
Expand Down