Skip to content
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

[SemanticDB] Fix missing symbol occurrence of type params' type bounds for constructor #13284

Merged
merged 4 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from 3 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
25 changes: 20 additions & 5 deletions compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class ExtractSemanticDB extends Phase:
case PatternValDef(pat, rhs) =>
traverse(rhs)
PatternValDef.collectPats(pat).foreach(traverse)
case tree: TypeDef =>
traverseChildren(tree)
case tree =>
if !excludeChildren(tree.symbol) then
traverseChildren(tree)
Expand All @@ -176,6 +178,10 @@ class ExtractSemanticDB extends Phase:
registerSymbol(tree.symbol, symbolKinds(tree))
case tree: Template =>
val ctorSym = tree.constr.symbol
if !excludeDef(ctorSym) then
traverseAnnotsOfDefinition(ctorSym)
registerDefinition(ctorSym, tree.constr.nameSpan.startPos, Set.empty, tree.source)
ctorParams(tree.constr.termParamss, tree.constr.leadingTypeParams, tree.body)
for parent <- tree.parentsOrDerived if parent.span.hasLength do
traverse(parent)
val selfSpan = tree.self.span
Expand All @@ -185,10 +191,6 @@ class ExtractSemanticDB extends Phase:
tree.body.foreachUntilImport(traverse).foreach(traverse) // the first import statement
else
tree.body.foreach(traverse)
if !excludeDef(ctorSym) then
traverseAnnotsOfDefinition(ctorSym)
ctorParams(tree.constr.termParamss, tree.body)
registerDefinition(ctorSym, tree.constr.nameSpan.startPos, Set.empty, tree.source)
case tree: Apply =>
@tu lazy val genParamSymbol: Name => String = tree.fun.symbol.funParamSymbol
traverse(tree.fun)
Expand Down Expand Up @@ -231,6 +233,16 @@ class ExtractSemanticDB extends Phase:
registerUseGuarded(None, alt.symbol.companionClass, sel.imported.span, tree.source)
case tree: Inlined =>
traverse(tree.call)
case tree: TypeTree =>
tree.typeOpt match
// Any types could be appear inside of `TypeTree`, but
// types that precent in source other than TypeRef are traversable and contain Ident tree nodes
// (e.g. TypeBoundsTree, AppliedTypeTree)
case Types.TypeRef(_, sym: Symbol) if namePresentInSource(sym, tree.span, tree.source) =>
registerUseGuarded(None, sym, tree.span, tree.source)
case _ => ()


case _ =>
traverseChildren(tree)

Expand Down Expand Up @@ -426,7 +438,7 @@ class ExtractSemanticDB extends Phase:
symkinds.toSet

private def ctorParams(
vparamss: List[List[ValDef]], body: List[Tree])(using Context): Unit =
vparamss: List[List[ValDef]], tparams: List[TypeDef], body: List[Tree])(using Context): Unit =
@tu lazy val getters = findGetters(vparamss.flatMap(_.map(_.name)).toSet, body)
for
vparams <- vparamss
Expand All @@ -439,6 +451,9 @@ class ExtractSemanticDB extends Phase:
getters.get(vparam.name).fold(SymbolKind.emptySet)(getter =>
if getter.mods.is(Mutable) then SymbolKind.VarSet else SymbolKind.ValSet)
registerSymbol(vparam.symbol, symkinds)
traverse(vparam.tpt)
tparams.foreach(tp => traverse(tp.rhs))


object ExtractSemanticDB:
import java.nio.file.Path
Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/Advanced.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ object Test/*<-advanced::Test.*/ {


// Curried Type Application
class HKClass/*<-advanced::HKClass#*/[F/*<-advanced::HKClass#[F]*/ <: [T] =>> [U] =>> (U, T)] {
class HKClass/*<-advanced::HKClass#*/[F/*<-advanced::HKClass#[F]*/ <: [T/*<-advanced::HKClass#`<init>`().[F][T]*/] =>> [U/*<-advanced::HKClass#`<init>`().[F][U]*/] =>> (U/*->advanced::HKClass#`<init>`().[F][U]*/, T/*->advanced::HKClass#`<init>`().[F][T]*/)] {
def foo/*<-advanced::HKClass#foo().*/[T/*<-advanced::HKClass#foo().[T]*/,U/*<-advanced::HKClass#foo().[U]*/](x/*<-advanced::HKClass#foo().(x)*/: F/*->advanced::HKClass#[F]*/[T/*->advanced::HKClass#foo().[T]*/][U/*->advanced::HKClass#foo().[U]*/]): String/*->scala::Predef.String#*/ = x/*->advanced::HKClass#foo().(x)*/.toString/*->scala::Tuple2#toString().*/()
}
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/Prefixes.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object Test/*<-prefixes::Test.*/ {
def m2/*<-prefixes::Test.m2().*/: c/*->prefixes::Test.c.*/.T/*->prefixes::C#T#*/ = ???/*->scala::Predef.`???`().*/
def k2/*<-prefixes::Test.k2().*/: c/*->prefixes::Test.c.*/.N/*->prefixes::C#N.*/.U/*->prefixes::C#N.U#*/ = ???/*->scala::Predef.`???`().*/
import c/*->prefixes::Test.c.*/.N/*->prefixes::C#N.*/.*
def k3/*<-prefixes::Test.k3().*/: U = ???/*->scala::Predef.`???`().*/
def k3/*<-prefixes::Test.k3().*/: U/*->prefixes::C#N.U#*/ = ???/*->scala::Predef.`???`().*/

def n2/*<-prefixes::Test.n2().*/: M/*->prefixes::M.*/.T/*->prefixes::M.T#*/ = ???/*->scala::Predef.`???`().*/

Expand Down
20 changes: 10 additions & 10 deletions tests/semanticdb/expect/RecOrRefined.expect.scala
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
package example

def m1/*<-example::RecOrRefined$package.m1().*/(a/*<-example::RecOrRefined$package.m1().(a)*/: Int/*->scala::Int#*/ { val x/*<-local1*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
def m2/*<-example::RecOrRefined$package.m2().*/(x/*<-example::RecOrRefined$package.m2().(x)*/: { val x/*<-local2*/: Int/*->scala::Int#*/; def y/*<-local3*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
def m3/*<-example::RecOrRefined$package.m3().*/(x/*<-example::RecOrRefined$package.m3().(x)*/: { val x/*<-local4*/: Int/*->scala::Int#*/; def y/*<-local5*/: Int/*->scala::Int#*/; type z/*<-local6*/ }) = ???/*->scala::Predef.`???`().*/
def m1/*<-example::RecOrRefined$package.m1().*/(a/*<-example::RecOrRefined$package.m1().(a)*/: Int/*->scala::Int#*/ { val x/*<-local3*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
def m2/*<-example::RecOrRefined$package.m2().*/(x/*<-example::RecOrRefined$package.m2().(x)*/: { val x/*<-local4*/: Int/*->scala::Int#*/; def y/*<-local5*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
def m3/*<-example::RecOrRefined$package.m3().*/(x/*<-example::RecOrRefined$package.m3().(x)*/: { val x/*<-local6*/: Int/*->scala::Int#*/; def y/*<-local7*/: Int/*->scala::Int#*/; type z/*<-local8*/ }) = ???/*->scala::Predef.`???`().*/
trait PolyHolder/*<-example::PolyHolder#*/ {
def foo/*<-example::PolyHolder#foo().*/[T/*<-example::PolyHolder#foo().[T]*/](t/*<-example::PolyHolder#foo().(t)*/: T/*->example::PolyHolder#foo().[T]*/): Any/*->scala::Any#*/
}

def m4/*<-example::RecOrRefined$package.m4().*/(x/*<-example::RecOrRefined$package.m4().(x)*/: PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local9*/[T/*<-local7*/](t/*<-local8*/: T/*->local7*/): T/*->local7*/ }) = ???/*->scala::Predef.`???`().*/
def m5/*<-example::RecOrRefined$package.m5().*/[Z/*<-example::RecOrRefined$package.m5().[Z]*/](x/*<-example::RecOrRefined$package.m5().(x)*/: Int/*->scala::Int#*/): PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local12*/[T/*<-local10*/](t/*<-local11*/: T/*->local10*/): T/*->local10*/ } = ???/*->scala::Predef.`???`().*/
def m4/*<-example::RecOrRefined$package.m4().*/(x/*<-example::RecOrRefined$package.m4().(x)*/: PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local11*/[T/*<-local9*/](t/*<-local10*/: T/*->local9*/): T/*->local9*/ }) = ???/*->scala::Predef.`???`().*/
def m5/*<-example::RecOrRefined$package.m5().*/[Z/*<-example::RecOrRefined$package.m5().[Z]*/](x/*<-example::RecOrRefined$package.m5().(x)*/: Int/*->scala::Int#*/): PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local14*/[T/*<-local12*/](t/*<-local13*/: T/*->local12*/): T/*->local12*/ } = ???/*->scala::Predef.`???`().*/

type m6/*<-example::RecOrRefined$package.m6#*/ = [X/*<-example::RecOrRefined$package.m6#[X]*/] =>> PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local15*/[T/*<-local13*/](t/*<-local14*/: T/*->local13*/): T/*->local13*/ }
type m6/*<-example::RecOrRefined$package.m6#*/ = [X/*<-example::RecOrRefined$package.m6#[X]*/] =>> PolyHolder/*->example::PolyHolder#*/ { def foo/*<-local17*/[T/*<-local15*/](t/*<-local16*/: T/*->local15*/): T/*->local15*/ }

class Record/*<-example::Record#*/(elems/*<-example::Record#elems.*/: (String/*->scala::Predef.String#*/, Any/*->scala::Any#*/)*) extends Selectable/*->scala::Selectable#*/:
private val fields/*<-example::Record#fields.*/ = elems/*->example::Record#elems.*/.toMap/*->scala::collection::IterableOnceOps#toMap().*/
def selectDynamic/*<-example::Record#selectDynamic().*/(name/*<-example::Record#selectDynamic().(name)*/: String/*->scala::Predef.String#*/): Any/*->scala::Any#*/ = fields/*->example::Record#fields.*/(name/*->example::Record#selectDynamic().(name)*/)

type Person/*<-example::RecOrRefined$package.Person#*/ = Record/*->example::Record#*/ {
val name/*<-local16*/: String/*->scala::Predef.String#*/
val age/*<-local17*/: Int/*->scala::Int#*/
val name/*<-local18*/: String/*->scala::Predef.String#*/
val age/*<-local19*/: Int/*->scala::Int#*/
}

// RecType
class C/*<-example::C#*/ { type T1/*<-example::C#T1#*/; type T2/*<-example::C#T2#*/ }
type C2/*<-example::RecOrRefined$package.C2#*/ = C/*->example::C#*/ { type T1/*<-local18*/; type T2/*<-local19*/ = T1/*->local18*/ }
type C2/*<-example::RecOrRefined$package.C2#*/ = C/*->example::C#*/ { type T1/*<-local20*/; type T2/*<-local21*/ = T1/*->local20*/ }

trait SpecialRefinement/*<-example::SpecialRefinement#*/ {
def pickOne/*<-example::SpecialRefinement#pickOne().*/[T/*<-example::SpecialRefinement#pickOne().[T]*/](as/*<-example::SpecialRefinement#pickOne().(as)*/: T/*->example::SpecialRefinement#pickOne().[T]*/*): Option/*->scala::Option#*/[Any/*->scala::Any#*/]
}

class PickOneRefinement_1/*<-example::PickOneRefinement_1#*/[S/*<-example::PickOneRefinement_1#[S]*/ <: SpecialRefinement { def pickOne[T](as: T*): Option[String] }] {
class PickOneRefinement_1/*<-example::PickOneRefinement_1#*/[S/*<-example::PickOneRefinement_1#[S]*/ <: SpecialRefinement/*->example::SpecialRefinement#*/ { def pickOne/*<-local2*/[T/*<-local0*/](as/*<-local1*/: T/*->local0*/*): Option/*->scala::Option#*/[String/*->scala::Predef.String#*/] }] {
def run/*<-example::PickOneRefinement_1#run().*/(s/*<-example::PickOneRefinement_1#run().(s)*/: S/*->example::PickOneRefinement_1#[S]*/, as/*<-example::PickOneRefinement_1#run().(as)*/: String/*->scala::Predef.String#*/*): Option/*->scala::Option#*/[String/*->scala::Predef.String#*/] = s/*->example::PickOneRefinement_1#run().(s)*/.pickOne/*->example::SpecialRefinement#pickOne().*/(as/*->example::PickOneRefinement_1#run().(as)*/:_*)
}
12 changes: 6 additions & 6 deletions tests/semanticdb/expect/i9782.expect.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// LazyRef
trait Txn/*<-_empty_::Txn#*/[T/*<-_empty_::Txn#[T]*/ <: Txn[T]]
trait Txn/*<-_empty_::Txn#*/[T/*<-_empty_::Txn#[T]*/ <: Txn/*->_empty_::Txn#*/[T/*->_empty_::Txn#[T]*/]]

trait Elem/*<-_empty_::Elem#*/[T/*<-_empty_::Elem#[T]*/ <: Txn[T]]
trait Elem/*<-_empty_::Elem#*/[T/*<-_empty_::Elem#[T]*/ <: Txn/*->_empty_::Txn#*/[T/*->_empty_::Elem#[T]*/]]

trait Obj/*<-_empty_::Obj#*/[T/*<-_empty_::Obj#[T]*/ <: Txn[T]] extends Elem/*->_empty_::Elem#*/[T/*->_empty_::Obj#[T]*/]
trait Obj/*<-_empty_::Obj#*/[T/*<-_empty_::Obj#[T]*/ <: Txn/*->_empty_::Txn#*/[T/*->_empty_::Obj#[T]*/]] extends Elem/*->_empty_::Elem#*/[T/*->_empty_::Obj#[T]*/]

trait Copy/*<-_empty_::Copy#*/[In/*<-_empty_::Copy#[In]*/ <: Txn[In], Out/*<-_empty_::Copy#[Out]*/ <: Txn[Out]] {
def copyImpl/*<-_empty_::Copy#copyImpl().*/[Repr/*<-_empty_::Copy#copyImpl().[Repr]*/[~ <: Txn[~]] <: Elem[~]](in/*<-_empty_::Copy#copyImpl().(in)*/: Repr/*->_empty_::Copy#copyImpl().[Repr]*/[In/*->_empty_::Copy#[In]*/]): Repr/*->_empty_::Copy#copyImpl().[Repr]*/[Out/*->_empty_::Copy#[Out]*/]
trait Copy/*<-_empty_::Copy#*/[In/*<-_empty_::Copy#[In]*/ <: Txn/*->_empty_::Txn#*/[In/*->_empty_::Copy#[In]*/], Out/*<-_empty_::Copy#[Out]*/ <: Txn/*->_empty_::Txn#*/[Out/*->_empty_::Copy#[Out]*/]] {
def copyImpl/*<-_empty_::Copy#copyImpl().*/[Repr/*<-_empty_::Copy#copyImpl().[Repr]*/[~/*<-_empty_::Copy#copyImpl().[Repr][`~`]*/ <: Txn/*->_empty_::Txn#*/[~/*->_empty_::Copy#copyImpl().[Repr][`~`]*/]] <: Elem/*->_empty_::Elem#*/[~/*->_empty_::Copy#copyImpl().[Repr][`~`]*/]](in/*<-_empty_::Copy#copyImpl().(in)*/: Repr/*->_empty_::Copy#copyImpl().[Repr]*/[In/*->_empty_::Copy#[In]*/]): Repr/*->_empty_::Copy#copyImpl().[Repr]*/[Out/*->_empty_::Copy#[Out]*/]

def apply/*<-_empty_::Copy#apply().*/[Repr/*<-_empty_::Copy#apply().[Repr]*/[~ <: Txn[~]] <: Elem[~]](in/*<-_empty_::Copy#apply().(in)*/: Repr/*->_empty_::Copy#apply().[Repr]*/[In/*->_empty_::Copy#[In]*/]): Repr/*->_empty_::Copy#apply().[Repr]*/[Out/*->_empty_::Copy#[Out]*/] = {
def apply/*<-_empty_::Copy#apply().*/[Repr/*<-_empty_::Copy#apply().[Repr]*/[~/*<-_empty_::Copy#apply().[Repr][`~`]*/ <: Txn/*->_empty_::Txn#*/[~/*->_empty_::Copy#apply().[Repr][`~`]*/]] <: Elem/*->_empty_::Elem#*/[~/*->_empty_::Copy#apply().[Repr][`~`]*/]](in/*<-_empty_::Copy#apply().(in)*/: Repr/*->_empty_::Copy#apply().[Repr]*/[In/*->_empty_::Copy#[In]*/]): Repr/*->_empty_::Copy#apply().[Repr]*/[Out/*->_empty_::Copy#[Out]*/] = {
val out/*<-local0*/ = copyImpl/*->_empty_::Copy#copyImpl().*/[Repr/*->_empty_::Copy#apply().[Repr]*/](in/*->_empty_::Copy#apply().(in)*/)
(in/*->_empty_::Copy#apply().(in)*/, out/*->local0*/) match {
case (inObj/*<-local1*/: Obj/*->_empty_::Obj#*/[In/*->_empty_::Copy#[In]*/], outObj/*<-local2*/: Obj/*->_empty_::Obj#*/[Out/*->_empty_::Copy#[Out]*/]) => // problem here
Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/nullary.expect.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
abstract class NullaryTest/*<-_empty_::NullaryTest#*/[T/*<-_empty_::NullaryTest#[T]*/, m/*<-_empty_::NullaryTest#[m]*/[s]] {
abstract class NullaryTest/*<-_empty_::NullaryTest#*/[T/*<-_empty_::NullaryTest#[T]*/, m/*<-_empty_::NullaryTest#[m]*/[s/*<-_empty_::NullaryTest#`<init>`().[m][s]*/]] {
def nullary/*<-_empty_::NullaryTest#nullary().*/: String/*->scala::Predef.String#*/ = "a"
val x/*<-_empty_::NullaryTest#x.*/ = nullary/*->_empty_::NullaryTest#nullary().*/

Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/recursion.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object Nats/*<-recursion::Nats.*/ {
}

case object Zero/*<-recursion::Nats.Zero.*/ extends Nat/*->recursion::Nats.Nat#*/
case class Succ/*<-recursion::Nats.Succ#*/[N/*<-recursion::Nats.Succ#[N]*/ <: Nat](p/*<-recursion::Nats.Succ#p.*/: N/*->recursion::Nats.Succ#[N]*/) extends Nat/*->recursion::Nats.Nat#*/
case class Succ/*<-recursion::Nats.Succ#*/[N/*<-recursion::Nats.Succ#[N]*/ <: Nat/*->recursion::Nats.Nat#*/](p/*<-recursion::Nats.Succ#p.*/: N/*->recursion::Nats.Succ#[N]*/) extends Nat/*->recursion::Nats.Nat#*/

transparent inline def toIntg/*<-recursion::Nats.toIntg().*/(inline n/*<-recursion::Nats.toIntg().(n)*/: Nat/*->recursion::Nats.Nat#*/): Int/*->scala::Int#*/ =
inline n/*->recursion::Nats.toIntg().(n)*/ match {
Expand Down
Loading