diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala index 7326bc13c5e..eac15efe168 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala @@ -231,8 +231,17 @@ class MetalsGlobal( val documentation = search.documentation( sym, new ParentSymbols { - def parents(): util.List[String] = - symbol.overrides.map(toSemanticdbSymbol).asJava + def parents(): util.List[String] = { + val parentSymbols = + if (symbol.name == nme.apply && symbol.safeOwner.isModuleClass) + List( + symbol.safeOwner, + symbol.safeOwner.companion + ).filter(_ != NoSymbol) ++ symbol.overrides + else symbol.overrides + + parentSymbols.map(toSemanticdbSymbol).asJava + } } ) diff --git a/mtags/src/main/scala-3/scala/meta/internal/mtags/MtagsEnrichments.scala b/mtags/src/main/scala-3/scala/meta/internal/mtags/MtagsEnrichments.scala index 568e48fbd67..26279ae5b65 100644 --- a/mtags/src/main/scala-3/scala/meta/internal/mtags/MtagsEnrichments.scala +++ b/mtags/src/main/scala-3/scala/meta/internal/mtags/MtagsEnrichments.scala @@ -196,9 +196,17 @@ object MtagsEnrichments extends ScalametaCommonEnrichments: else symbol ) val sym = toSemanticdbSymbol(symbol) + def parentSymbols = + if symbol.name == nme.apply && symbol.maybeOwner.is(ModuleClass) then + List( + symbol.maybeOwner, + symbol.maybeOwner.companion, + ).filter(_ != NoSymbol) ++ symbol.allOverriddenSymbols + else symbol.allOverriddenSymbols + val documentation = search.documentation( sym, - () => symbol.allOverriddenSymbols.map(toSemanticdbSymbol).toList.asJava, + () => parentSymbols.map(toSemanticdbSymbol).toList.asJava, ) if documentation.isPresent then Some(documentation.get()) else None diff --git a/mtags/src/main/scala/scala/meta/internal/metals/Docstrings.scala b/mtags/src/main/scala/scala/meta/internal/metals/Docstrings.scala index dbd6b60b373..0efcb4a4154 100644 --- a/mtags/src/main/scala/scala/meta/internal/metals/Docstrings.scala +++ b/mtags/src/main/scala/scala/meta/internal/metals/Docstrings.scala @@ -54,6 +54,14 @@ class Docstrings(index: GlobalSymbolIndex) { case Some(value: MetalsSymbolDocumentation) if value.docstring.isEmpty() => Some(parentDocumentation(symbol, value, parents)) + case None => + Some( + parentDocumentation( + symbol, + MetalsSymbolDocumentation.empty(symbol), + parents + ) + ) case _ => result } Optional.ofNullable(resultWithParentDocs.orNull) diff --git a/mtags/src/main/scala/scala/meta/internal/metals/MetalsSymbolDocumentation.scala b/mtags/src/main/scala/scala/meta/internal/metals/MetalsSymbolDocumentation.scala index 505c5d91d5c..b282b4f024a 100644 --- a/mtags/src/main/scala/scala/meta/internal/metals/MetalsSymbolDocumentation.scala +++ b/mtags/src/main/scala/scala/meta/internal/metals/MetalsSymbolDocumentation.scala @@ -13,3 +13,8 @@ case class MetalsSymbolDocumentation( typeParameters: util.List[SymbolDocumentation] = Nil.asJava, parameters: util.List[SymbolDocumentation] = Nil.asJava ) extends SymbolDocumentation + +object MetalsSymbolDocumentation { + def empty(symbol: String): MetalsSymbolDocumentation = + MetalsSymbolDocumentation(symbol, "", "") +} diff --git a/tests/cross/src/test/scala/tests/hover/HoverDocSuite.scala b/tests/cross/src/test/scala/tests/hover/HoverDocSuite.scala index 770422a0750..048640f531a 100644 --- a/tests/cross/src/test/scala/tests/hover/HoverDocSuite.scala +++ b/tests/cross/src/test/scala/tests/hover/HoverDocSuite.scala @@ -114,4 +114,204 @@ class HoverDocSuite extends BaseHoverSuite { |a path string, to a `Path`. |""".stripMargin, ) + + check( + "object", + """| + |/** + | * Doc about object + | */ + |object Alpha { + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about object + | + |""".stripMargin, + ) + + check( + "object1", + """| + |/** + | * Doc about object + | */ + |object Alpha { + | /** + | * Doc about method + | */ + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about method + | + |""".stripMargin, + ) + + check( + "case-class", + """| + |/** + | * Doc about case class + | * + | */ + |case class Alpha(x: Int) + | + |/** + | * Doc about object + | */ + |object Alpha { + | /** + | * Doc about method + | */ + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about method + | + |""".stripMargin, + ) + + check( + "case-class1", + """| + |/** + | * Doc about case class + | * + | */ + |case class Alpha(x: Int) + | + |/** + | * Doc about object + | */ + |object Alpha { + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about object + | + |""".stripMargin, + ) + + check( + "case-class2", + """| + |/** + | * Doc about case class + | * + | */ + |case class Alpha(x: Int) + | + |object Alpha { + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about case class + | + |""".stripMargin, + ) + + check( + "case-class3", + """| + |/** + | * Doc about case class + | * + | */ + |case class Alpha(x: Int) + | + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Alpha + |``` + |Doc about case class + | + |""".stripMargin, + ) + + check( + "class", + """| + |/** + | * Doc about class + | * + | */ + |class Alpha(x: Int) + | + |object Alpha { + | def apply(x: Int) = x + 1 + |} + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def apply(x: Int): Int + |``` + |Doc about class + | + |""".stripMargin, + ) + + check( + "universal-apply".tag(IgnoreScala2), + """| + |/** + | * Doc about class + | * + | */ + |class Alpha(x: Int) + | + |object Main { + | val x = <> + |} + |""".stripMargin, + """|```scala + |def this(x: Int): Alpha + |``` + |Doc about class + | + |""".stripMargin, + ) + } diff --git a/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala index 93ef67d4d90..352e2fa90f2 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionDocSuite.scala @@ -569,14 +569,14 @@ class CompletionDocSuite extends BaseCompletionSuite { |StringBuilder scala.collection.mutable |""".stripMargin, "3" -> - s"""$scala213Docs - |StringBuilder scala.collection.mutable - |StringBuilder(): StringBuilder - |StringBuilder(str: String): StringBuilder - |StringBuilder(underlying: StringBuilder): StringBuilder - |StringBuilder(capacity: Int): StringBuilder - |StringBuilder(initCapacity: Int, initValue: String): StringBuilder - |""".stripMargin, + List( + "StringBuilder scala.collection.mutable", + "StringBuilder(): StringBuilder", + "StringBuilder(str: String): StringBuilder", + "StringBuilder(underlying: StringBuilder): StringBuilder", + "StringBuilder(capacity: Int): StringBuilder", + "StringBuilder(initCapacity: Int, initValue: String): StringBuilder", + ).map(s => scala213Docs + "\n" + s).mkString("\n"), "2.13.11" -> s"""|$scala213Docs |StringBuilder scala.collection.mutable diff --git a/tests/cross/src/test/scala/tests/pc/SignatureHelpDocSuite.scala b/tests/cross/src/test/scala/tests/pc/SignatureHelpDocSuite.scala index e47693a4d1f..51df3890f2a 100644 --- a/tests/cross/src/test/scala/tests/pc/SignatureHelpDocSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/SignatureHelpDocSuite.scala @@ -272,7 +272,16 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite { |""".stripMargin, compat = Map( "3" -> - """|apply[T1, T2, T3](_1: T1, _2: T2, _3: T3): (T1, T2, T3) + """|A tuple of 3 elements; the canonical representation of a [scala.Product3](scala.Product3). + | + | + |**Constructor:** Create a new tuple with 3 elements. Note that it is more idiomatic to create a Tuple3 via `(t1, t2, t3)` + | + |**Parameters** + |- `_1`: Element 1 of this Tuple3 + |- `_2`: Element 2 of this Tuple3 + |- `_3`: Element 3 of this Tuple3 + |apply[T1, T2, T3](_1: T1, _2: T2, _3: T3): (T1, T2, T3) | ^^^^^^ |""".stripMargin, ">=3.2.0-RC1-bin-20220610-30f83f7-NIGHTLY" ->