diff --git a/mtags/src/main/scala-3/scala/meta/internal/pc/PcCollector.scala b/mtags/src/main/scala-3/scala/meta/internal/pc/PcCollector.scala
index 253ff06199e..6bbe6bbdd56 100644
--- a/mtags/src/main/scala-3/scala/meta/internal/pc/PcCollector.scala
+++ b/mtags/src/main/scala-3/scala/meta/internal/pc/PcCollector.scala
@@ -148,6 +148,23 @@ abstract class PcCollector[T](
if id.symbol
.is(Flags.Param) && id.symbol.owner.is(Flags.ExtensionMethod) =>
Some(findAllExtensionParamSymbols(id.sourcePos, id.name, id.symbol))
+ /**
+ * Workaround for missing symbol in:
+ * class A[T](a: T)
+ * val x = new <>(1)
+ */
+ case t :: (n: New) :: (sel: Select) :: _
+ if t.symbol == NoSymbol && sel.symbol.isConstructor =>
+ Some(symbolAlternatives(sel.symbol.owner), namePos(t))
+ /**
+ * Workaround for missing symbol in:
+ * class A[T](a: T)
+ * val x = <>[Int](1)
+ */
+ case (sel @ Select(New(t), _)) :: (_: TypeApply) :: _
+ if sel.symbol.isConstructor =>
+ Some(symbolAlternatives(sel.symbol.owner), namePos(t))
+
/* simple identifier:
* val a = val@@ue + value
*/
@@ -416,6 +433,23 @@ abstract class PcCollector[T](
ident.sourcePos,
)
else occurences
+
+ /**
+ * Workaround for missing symbol in:
+ * class A[T](a: T)
+ * val x = new <>(1)
+ */
+ case sel @ Select(New(t), _)
+ if sel.span.isCorrect &&
+ sel.symbol.isConstructor &&
+ t.symbol == NoSymbol =>
+ if soughtFilter(_ == sel.symbol.owner) then
+ occurences + collect(
+ sel,
+ namePos(t),
+ Some(sel.symbol.owner),
+ )
+ else occurences
/**
* All select statements such as:
* val a = hello.<>
@@ -600,6 +634,11 @@ abstract class PcCollector[T](
Span(span.start, span.start + realName.length, point)
else Span(point, span.end, point)
else span
+
+ private def namePos(tree: Tree): SourcePosition =
+ tree match
+ case sel: Select => sel.sourcePos.withSpan(selectNameSpan(sel))
+ case _ => tree.sourcePos
end PcCollector
object PcCollector:
diff --git a/tests/cross/src/test/scala/tests/highlight/DocumentHighlightSuite.scala b/tests/cross/src/test/scala/tests/highlight/DocumentHighlightSuite.scala
index 4a78e62c4a3..5867c986ae0 100644
--- a/tests/cross/src/test/scala/tests/highlight/DocumentHighlightSuite.scala
+++ b/tests/cross/src/test/scala/tests/highlight/DocumentHighlightSuite.scala
@@ -1044,4 +1044,98 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite {
|""".stripMargin
)
+ check(
+ "constructor",
+ """
+ |object Main {
+ | class <>[T](abc: T)
+ | val x = new <>(123)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor1",
+ """
+ |object Main {
+ | case class <>[T](abc: T)
+ | val x = <>(123)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor2",
+ """
+ |object Main {
+ | class <>[T](abc: T)
+ | object <>
+ | val x = new <>(123)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor3",
+ """
+ |object Main {
+ | class <>[T](abc: T)
+ | object <>
+ | val x = new <>(123)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor4",
+ """
+ |object Main {
+ | class <>[T](abc: T)
+ | object <>
+ | val x = new <>(123)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor5",
+ """
+ |object Main {
+ | class <>[T](abc: T)
+ | object <> {
+ | def apply(abc: Int, bde: Int) = new <>(abc + bde)
+ | }
+ | val x = <>(123, 456)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor6".tag(IgnoreScala2),
+ """
+ |class <>[T](a: T)
+ |object O {
+ | def foo(a: Int) = new <>[Int](a)
+ | val x = <>[Int](2)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor7",
+ """
+ |object Bar {
+ |class <>[T](a: T)
+ |}
+ |
+ |object O {
+ | val x = new Bar.<>(2)
+ |}""".stripMargin
+ )
+
+ check(
+ "constructor8".tag(IgnoreScala2),
+ """
+ |object Bar {
+ |class <>[T](a: T)
+ |}
+ |
+ |object O {
+ | val x = Bar.<>[Int](2)
+ |}""".stripMargin
+ )
+
}
diff --git a/tests/cross/src/test/scala/tests/tokens/SemanticTokensScala3Suite.scala b/tests/cross/src/test/scala/tests/tokens/SemanticTokensScala3Suite.scala
index df3f0347e47..6304a02b563 100644
--- a/tests/cross/src/test/scala/tests/tokens/SemanticTokensScala3Suite.scala
+++ b/tests/cross/src/test/scala/tests/tokens/SemanticTokensScala3Suite.scala
@@ -146,4 +146,19 @@ class SemanticTokensScala3Suite extends BaseSemanticTokensSuite {
|""".stripMargin
)
+ check(
+ "constructor2",
+ """
+ |object <>/*class*/ {
+ | class <>/*class*/[<>/*typeParameter,definition,abstract*/](<>/*variable,declaration,readonly*/: <>/*typeParameter,abstract*/)
+ |}
+ |
+ |object <>/*class*/ {
+ | val <>/*variable,definition,readonly*/ = new <>/*class*/.<>/*class*/(2)
+ | val <>/*variable,definition,readonly*/ = new <>/*class*/.<>/*class*/[<>/*class,abstract*/](2)
+ | val <>/*variable,definition,readonly*/ = <>/*class*/.<>/*class*/(2)
+ | val <>/*variable,definition,readonly*/ = <>/*class*/.<>/*class*/[<>/*class,abstract*/](2)
+ |}""".stripMargin
+ )
+
}
diff --git a/tests/cross/src/test/scala/tests/tokens/SemanticTokensSuite.scala b/tests/cross/src/test/scala/tests/tokens/SemanticTokensSuite.scala
index 872776e561f..e7f68679838 100644
--- a/tests/cross/src/test/scala/tests/tokens/SemanticTokensSuite.scala
+++ b/tests/cross/src/test/scala/tests/tokens/SemanticTokensSuite.scala
@@ -365,4 +365,45 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite {
|}""".stripMargin
)
+ check(
+ "constructor",
+ """
+ |object <>/*class*/ {
+ | class <>/*class*/[<>/*typeParameter,declaration,abstract*/](<>/*variable,declaration,readonly*/: <>/*typeParameter,abstract*/)
+ | object <>/*class*/
+ | val <>/*variable,definition,readonly*/ = new <>/*class*/(123)
+ |}""".stripMargin,
+ compat = Map(
+ "3" -> """
+ |object <>/*class*/ {
+ | class <>/*class*/[<>/*typeParameter,definition,abstract*/](<>/*variable,declaration,readonly*/: <>/*typeParameter,abstract*/)
+ | object <>/*class*/
+ | val <>/*variable,definition,readonly*/ = new <>/*class*/(123)
+ |}""".stripMargin
+ )
+ )
+
+ check(
+ "constructor1",
+ """
+ |object <>/*class*/ {
+ | class <>/*class*/[<>/*typeParameter,declaration,abstract*/](<>/*variable,declaration,readonly*/: <>/*typeParameter,abstract*/)
+ | object <>/*class*/ {
+ | def <>/*method,definition*/[<>/*typeParameter,declaration,abstract*/](<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/, <>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/) = new <>/*class*/(<>/*parameter,readonly*/)
+ | }
+ | val <>/*variable,definition,readonly*/ = <>/*class*/(123, 456)
+ |}""".stripMargin,
+ compat = Map(
+ "3" ->
+ """
+ |object <>/*class*/ {
+ | class <>/*class*/[<>/*typeParameter,definition,abstract*/](<>/*variable,declaration,readonly*/: <>/*typeParameter,abstract*/)
+ | object <>/*class*/ {
+ | def <>/*method,definition*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/, <>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/) = new <>/*class*/(<>/*parameter,readonly*/)
+ | }
+ | val <>/*variable,definition,readonly*/ = <>/*class*/(123, 456)
+ |}""".stripMargin
+ )
+ )
+
}