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 + ) + ) + }