diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 7de75e371752..821c7833a737 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -357,13 +357,25 @@ object Symbols extends SymUtils { targets.match case (tp: NamedType) :: _ => tp.symbol.sourceSymbol case _ => this - else if (denot.is(Synthetic)) { + else if denot.is(Synthetic) then val linked = denot.linkedClass if (linked.exists && !linked.is(Synthetic)) linked else denot.owner.sourceSymbol - } + else if ( + denot.is(TypeParam) && + denot.maybeOwner.maybeOwner.isAllOf(EnumCase) && + denot.maybeOwner.isPrimaryConstructor + ) then + val enclosingEnumCase = denot.maybeOwner.maybeOwner + val caseTypeParam = enclosingEnumCase.typeParams.find(_.name == denot.name) + if caseTypeParam.exists(_.is(Synthetic)) then + val enumClass = enclosingEnumCase.info.firstParent.typeSymbol + val sourceTypeParam = enumClass.typeParams.find(_.name == denot.name) + sourceTypeParam.getOrElse(this) + else + caseTypeParam.getOrElse(this) else if (denot.isPrimaryConstructor) denot.owner.sourceSymbol else this diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 16079125a434..973fc2f3d79d 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -144,6 +144,7 @@ object Interactive { ( sym == tree.symbol || sym.exists && sym == tree.symbol.sourceSymbol + || sym.exists && sym.sourceSymbol == tree.symbol || !include.isEmpty && sym.name == tree.symbol.name && sym.maybeOwner != tree.symbol.maybeOwner && ( include.isOverridden && overrides(sym, tree.symbol) || include.isOverriding && overrides(tree.symbol, sym) diff --git a/language-server/test/dotty/tools/languageserver/DefinitionTest.scala b/language-server/test/dotty/tools/languageserver/DefinitionTest.scala index ddacd0c868e0..d6de3d971e2b 100644 --- a/language-server/test/dotty/tools/languageserver/DefinitionTest.scala +++ b/language-server/test/dotty/tools/languageserver/DefinitionTest.scala @@ -378,4 +378,38 @@ class DefinitionTest { .definition(m3 to m4, Nil) .definition(m5 to m6, Nil) .definition(m7 to m8, Nil) + + @Test def typeParam: Unit = { + code"""|class Foo[${m1}T${m2}]: + | def test: ${m3}T${m4}""" + .definition(m3 to m4, List(m1 to m2)) + } + + @Test def enumTypeParam: Unit = { + code"""|enum Test[${m1}T${m2}]: + | case EnumCase(value: ${m3}T${m4})""" + .definition(m3 to m4, List(m1 to m2)) + } + + @Test def extMethodTypeParam: Unit = { + code"""extension [${m1}T${m2}](string: String) def xxxx(y: ${m3}T${m4}) = ???""" + .definition(m3 to m4, List(m1 to m2)) + } + + @Test def typeParamCovariant: Unit = { + code"""|class Foo[+${m1}T${m2}]: + | def test: ${m3}T${m4}""" + .definition(m3 to m4, List(m1 to m2)) + } + + @Test def enumTypeParamCovariant: Unit = { + code"""|enum Test[+${m1}T${m2}]: + | case EnumCase(value: ${m3}T${m4})""" + .definition(m3 to m4, List(m1 to m2)) + } + + @Test def extMethodTypeParamCovariant: Unit = { + code"""extension [+${m1}T${m2}](string: String) def xxxx(y: ${m3}T${m4}) = ???""" + .definition(m3 to m4, List(m1 to m2)) + } } diff --git a/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala index ff4c6ec25e27..68f664c54789 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala @@ -478,6 +478,33 @@ class PcDefinitionSuite extends BasePcDefinitionSuite: |""".stripMargin ) + @Test def `enum-class-type-param` = + check( + """| + |enum Options[<>]: + | case Some(x: A@@A) + | case None extends Options[Nothing] + |""".stripMargin + ) + + @Test def `enum-class-type-param-covariant` = + check( + """| + |enum Options[+<>]: + | case Some(x: A@@A) + | case None extends Options[Nothing] + |""".stripMargin + ) + + @Test def `enum-class-type-param-duplicate` = + check( + """| + |enum Testing[AA]: + | case Some[<>](x: A@@A) extends Testing[AA] + | case None extends Testing[Nothing] + |""".stripMargin + ) + @Test def `derives-def` = check( """|