Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate the @usecase scaladoc tag ? #584

Closed
smarter opened this issue Nov 20, 2018 · 8 comments
Closed

Deprecate the @usecase scaladoc tag ? #584

smarter opened this issue Nov 20, 2018 · 8 comments

Comments

@smarter
Copy link
Member

smarter commented Nov 20, 2018

@usecase was introduced to make some signatures less scary, but it can be confusing and sometimes downright misleading (e.g. https://www.scala-lang.org/api/2.12.7/scala/collection/Map.html#map[B](f:A=%3EB):scala.collection.Map[B]).

With the collection redesign in 2.13, @usecase is almost not used anymore, the remaining usage is giving "simpler" signatures that violate variance checks (and this isn't done consistently, e.g. List#:: gets a usecase but List#::: doesn't):

% rg @usecase src/library
src/library/scala/collection/IterableOnce.scala
766:   *  @usecase def copyToArray(xs: Array[A]): Int
784:    *  @usecase def copyToArray(xs: Array[A], start: Int): Int
815:    *  @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Int
837:    *   @usecase def sum: A
855:    *   @usecase def product: A
871:    *  @usecase def min: A
890:    *  @usecase def minOption: Option[A]
908:    *  @usecase def max: A
927:    *  @usecase def maxOption: Option[A]
947:    *  @usecase def maxBy[B](f: A => B): A
980:    *  @usecase def maxByOption[B](f: A => B): Option[A]
1001:    *  @usecase def minBy[B](f: A => B): A
1035:    *  @usecase def minByOption[B](f: A => B): Option[A]

src/library/scala/collection/Map.scala
126:   *   @usecase def getOrElse(key: K, default: => V): V

src/library/scala/collection/immutable/List.scala
98:    *  @usecase def ::(elem: A): List[A]
426:    *  @usecase def mapConserve(f: A => A): List[A]

src/library/scala/collection/immutable/Map.scala
102:    *  @usecase  def updated(key: K, value: V): Map[K, V]

(Github search doesn't like "@" apparently so I can't say how much this is used in the wild, but I would guess very rarely)

Given the implementation complexity of usecase (it ties documentation generation to typechecking), it may be time to rethink whether this is a feature we should support at all. What do people think ? /cc @odersky @Duhemm

@SethTisue
Copy link
Member

yes please! I would like to see this deprecated in 2.13 (and then removed in 2.14 or 3.0, whichever)

@dwijnand
Copy link
Member

(Github search doesn't like "@" apparently so I can't say how much this is used in the wild, but I would guess very rarely)

Using @olafurpg's https://github.com/olafurpg/scala-repos, which is about 2.3 MLoC of Scala:

21:54:41 $ tokei
---------------------------------------------------------------------------------------
 Language                    Files        Lines         Code     Comments       Blanks
---------------------------------------------------------------------------------------
 BASH                            1           86           50           21           15
 HTML                            1           66           65            0            1
 Markdown                      143        13880        13880            0            0
 ReStructuredText                3          109          109            0            0
 Scala                       27497      3260660      2291063       559285       410312
 Plain Text                     65         3749         3749            0            0
---------------------------------------------------------------------------------------
 Total                       27710      3278550      2308916       559306       410328
---------------------------------------------------------------------------------------

there's only 1 usage of @usecase, which is in com.twitter.util.Activity:

21:52:35 $ rg -g '!repos/scala/' @usecase
repos/util/util-core/src/main/scala/com/twitter/util/Activity.scala
144:    * @usecase def collect[T](activities: Coll[Activity[T]]): Activity[Coll[T]]

repos/ensime-server/core/src/main/scala/org/ensime/core/DocUsecaseHandling.scala
11:// Scaladoc uses @usecase comment annotations to substitute kid-safe signatures
20:// to determine if the link is likely to be a @usecase, and then go digging

repos/ensime-server/core/src/it/scala/org/ensime/core/DocFindingSpec.scala
160:          // Check @usecase handling.

repos/intellij-scala/src/org/jetbrains/plugins/scala/lang/scaladoc/parser/parsing/MyScaladocParsing.scala
323:  val USECASE_TAG = "@usecase"

@Duhemm
Copy link

Duhemm commented Nov 21, 2018

I also think that we should kill it.

  • This feature is practically undocumented, the only existing bit of documentation is:

    @usecase provide a simplified method definition for when the full method definition is too complex or noisy. An example is (in the collections API), providing documentation for methods that omit the implicit canBuildFrom.

    This doesn't explain what's a "simplified method definition", where are @usecase accepted, how many @usecase can I include, how's the simplified definition checked, etc.

  • It makes writing a doc tool much more complicated, since the @usecase signatures need to be typechecked, probably in the context where they're written.

  • The way it's displayed today is pretty bad. Why does it prepend [use case] to the method's description? I thought for a long time that this was referring to the description.

  • The real signature is very well hidden. We need to unroll twice in order to find it. If I didn't know this existed and the doc tool was lying to me, I would probably waste at least 10 minutes trying to figure out why the compiler is showing me nonsensical errors before starting to angrily click everywhere on my doc webpage.

This problem may be better solved by careful API design and improving how we display the full signatures. For instance, implicit parameters may be slightly faded.

@propensive
Copy link

I liked it when it was introduced, but I think that generally it would be better, in 2018, to document use-cases with actual code samples, compiled.

@felixmulder
Copy link

@smarter - killed it in Dotty too?

@odersky
Copy link

odersky commented Jan 9, 2019

I do think @usecase has a role to play so I would be against killing it, and would prefer to improve its implementation and documentation. The usecase of @usecase is this:

In a highly generic library we have situations where the general inherited type template is not the type the user of an abstraction should be shown. We need a checked way to present the relevant type. Simply dropping usecase does not solve this.

Here's a super-simplified example:

class Base {
   type This <: Base
   def copy: This
}
class Sub extends Base {
   type This <: Sub
}

In the ScalaDoc for Sub, the user should be shown:

def copy: Sub

since that's the relevant info for copy. The inherited info:

def copy: This

is much less useful, since This needs to be looked up, and even then it's an abstract type and the user needs advanced type knowledge to infer that, yes, this is actually equivalent to

def copy: Sub

If there's a way to do this without usecase, great. But as long as there isn't, usecase has a role to play.

@SethTisue
Copy link
Member

see also scala/bug#8887

@Atry
Copy link

Atry commented Jan 10, 2019

1,420 Scala source files on Github still use @usecase:
https://github.com/search?l=Scala&q=%22usecase+def%22&type=Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants