How to disambiguate links to methods in scaladoc?
Asked Answered
P

4

44

I'm documenting a Scala class with overloaded methods. How can I distinguish them when referring to them in scaladoc comments? For example, if I have

/**
 * The most important method is [[Doc.foo]].
 */
object Doc {
  def foo[A]: A = throw new UnsupportedOperationException;
  def foo[A,B >: A](x: A): B = x;
}

and run sbt doc I get

Doc.scala:1: warning: The link target "Doc.foo" is ambiguous. Several (possibly overloaded) members fit the target:

  • method foo[A,B>:A](x:A):B in object Doc [chosen]
  • method foo[A]:Nothing in object Doc

Using foo[A,B >: A] etc. to the link doesn't work.

Postmortem answered 13/3, 2013 at 19:9 Comment(3)
Would using [[Doc.foo()]] work? I know that in C# when there's an ambiguous reference in documentation, you have to either use () when you one the method without parameters or spell out the argument types, e.g. foo(string). Maybe it's similar here...Whitcher
@Trustme-I'maDoctor That doesn't work, complains with: warning: Could not find any member to link for "Doc.foo()".Postmortem
a PR at github.com/scala/docs.scala-lang adding documentation on this to docs.scala-lang.org/overviews/scaladoc/for-library-authors.html would be welcomeEmmuela
S
35

The following seems do the trick in Scala 2.10.

/**
 * The most important method is [[Doc.foo[A]:A*]].
 */

And here is some hint scaladoc gives me:

[warn] Quick crash course on using Scaladoc links
[warn] ==========================================
[warn] Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:
[warn]  - [[scala.collection.immutable.List!.apply class List's apply method]] and
[warn]  - [[scala.collection.immutable.List$.apply object List's apply method]]
[warn] Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:
[warn]  - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]
[warn]  - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]
[warn] Notes: 
[warn]  - you can use any number of matching square brackets to avoid interference with the signature
[warn]  - you can use \. to escape dots in prefixes (don't forget to use * at the end to match the signature!)
[warn]  - you can use \# to escape hashes, otherwise they will be considered as delimiters, like dots.
Skepful answered 14/3, 2013 at 1:55 Comment(7)
I find it abominable that ScalDoc can't resolve names via imports. I refuse to use fully qualified names in documentation comments.Lineation
Apparently, the hint is displayed only if I use scaladoc directly. I used sbt, which didn't show it.Postmortem
@Randall Schulz This should be fixed according to this issue: issues.scala-lang.org/browse/SI-3695Lucas
Alas, this has not consistently worked for me with complex type signatures. But with simpler ones, it does. (I have found no solution for more complex signatures.)Woodhead
This answer was not helpful to me. I'm trying to disambiguate 'apply' methods that have the same type args but different argument signatures. And I need it to work with Intellij IDEA 'Quick Documentation' (Ctrl-Q) for viewing scaladoc of a method.Kuo
This information ought to be in the official doc. Volunteer to PR it? issue here: github.com/scala/docs.scala-lang/issues/1698Emmuela
I believe this answer is out-of-date. please see docs.scala-lang.org/overviews/scaladoc/… for current helpAlard
U
14

What I found very usefull in IntelliJ is right clicking on a method you would like to put in [[ ]] and choosing "Copy reference".

Steps:

  1. You find a method you'd like to reference somewhere else.

enter image description here

  1. You right click on the method name and choose "Copy reference".

enter image description here

  1. You paste it in [[ ]] in your documentation (and write a label of your choice next to it, e.g. "apply(String)").

enter image description here

  1. Voilà.

enter image description here

Unstrung answered 5/12, 2019 at 12:46 Comment(2)
This worked for me in IntelliJ 2019.3.4 Community. I had tried a lot of different things prior to reading your answer and was getting nowhere. Thank you so much.Tubulate
Not always work for Scala, but in general it's a nice feature! Thanks for sharingRishi
Q
12

I'm still surprised at how difficult it is to get this working and the lack of documentation for scaladoc itself. I decided to search the scala code base itself in hope of some useful examples. The best ones that I found were in https://github.com/scala/scala/blob/2.12.x/test/scaladoc/resources/links.scala. Hopefully this is useful for someone else who comes across this.

Quietly answered 21/1, 2016 at 22:25 Comment(0)
C
10

I found a solution (apparently the unique solution) for complex signatures, by studying the doc of scaladoc.

  • Don't use space in the signature
  • Use the arguments name
  • For argument types as well as return types, prefix all dots with a single backslash \
  • Use the star * at the end of the signature
  • Use the complete signature (as the ambiguous signatures are proposed to you). This step is optional, you may be able to stop the signature earlier, as long as you finish it with *

Example:

package org.my.stuff

class ReturnType

object Foo {
  class Bar {
    def lara(s: String): String = ???
    def lara(s: Foo.Bar): ReturnType= ???
  }
}

/** [[org.my.stuff.Foo$.Bar.lara(s:org\.my\.stuff\.Foo\.Bar):org\.my\.stuff\.ReturnType* The link to the right lara method]]
  */
object DocumentFooBarBingComplex {
}
Ceasar answered 22/7, 2015 at 17:17 Comment(2)
"Don't use a space in the signature" -- What if there is an implicit parameter?Tumpline
Alas, that would not work indeed. You may try adding \ in front of the space, or make sure you don't need to write up to the implicit parameters to disambiguate your code.Gravelly

© 2022 - 2024 — McMap. All rights reserved.