swift-doc icon indicating copy to clipboard operation
swift-doc copied to clipboard

Add the ability to hide certain properties/methods

Open sindresorhus opened this issue 5 years ago • 9 comments

When you subclass a class, you sometimes have to implement some required methods or you want to override a property. These have to be marked as public, and hence shows up in the docs. It would be nice swift-doc could have a special comment or something to hide it.

When using TypeScript and type-doc, I can do something like this: https://github.com/sindresorhus/ow/blob/816e66c4837fc93ceb92c0480752020625e3b68d/source/predicates/predicate.ts#L7-L9

Jazzy supports this with a /// :nodoc: comment.

Some examples of what I would hide from my docs:

Screenshot 2020-05-07 at 20 17 59 Screenshot 2020-05-07 at 20 19 07

sindresorhus avatar May 07 '20 12:05 sindresorhus

Thanks for sharing this feedback, @sindresorhus. It's certainly possible to add an annotation to hide declarations from swift-doc — and that may well be what we go with — but I'd like to explore the motivating use cases to see if there might be a better solution.

Attempting to restate the problem:

  • Some public-facing APIs are effectively implementation details of type identity, and aren't typically documented.

  • Undocumented symbols in generated output are conspicuous, or at least compete with more important information.

  • These can be divided into two cases*:

    1. Requirements of an adopted protocol. For example, the description property requirement for CustomStringConvertible.
    2. Overridden members that are inherited from a superclass. For example, the canBecomeKeyView property of NSView.

* Are there any others you can think of?


In the first case, there's nothing to be added from a documentation comment; the behavior is defined by the protocol.

Here, I think the best solution would be to do the following:

  1. Inherit any documentation from the protocol declaration
  2. Organize the symbol into a group with others for that protocol that are separate from type-specific declarations.

In the second case, it's less clear when a documentation comment adds useful information. Sometimes, the reason for a method being overridden is an implementation detail that shouldn't be documented. Other times, such as the example of canBecomeKeyView, the overridden implementation may completely change the original behavior; this would probably benefit from documentation.

I'm less certain about what a good solution would be for this case.

Hiding the declaration is one option, but I worry that doing so can be counter-productive, as the fact that a member is overridden by a subclass may be valuable information to an API consumer attempting to understand a certain behavior.

What do you think about a similar approach to the one proposed for the first case? What if we had a section for Overridden Members that was subdivided according to the original declaration. For example, class MyView: NSView {...} would have canBecomeKeyView under NSView and acceptsFirstResponder under NSResponder.

mattt avatar May 07 '20 14:05 mattt

What do you think about a similar approach to the one proposed for the first case? What if we had a section for Overridden Members that was subdivided according to the original declaration. For example, class MyView: NSView {...} would have canBecomeKeyView under NSView and acceptsFirstResponder under NSResponder.

I agree. This is the best (and safest) default behavior.

However, in my specific case, I would still want to completely hide them as my class is final and it's just an implementation detail the user doesn't need to know about. Specifically, it's this class: https://github.com/sindresorhus/KeyboardShortcuts/blob/49b017b2450ac37353934d94d6c64957b62c45b4/Sources/KeyboardShortcuts/RecorderCocoa.swift#L28 So I think it should still be possible to mark properties/methods with some kind of directive comment to completely hide it from the docs.

Maybe hide them by default if the class is final?

sindresorhus avatar May 12 '20 08:05 sindresorhus

  • Are there any others you can think of?

None that I can think of right now, but I will let you know if I encounter any other cases.

sindresorhus avatar May 12 '20 08:05 sindresorhus

Another use-case: A protocol that has to be public, but should not be exposed to the user. For that, I usually prefix the protocol with an underscore: https://github.com/sindresorhus/Defaults/blob/f67098fd5c11b3f000a2d9d89ecfca65872b86f6/Sources/Defaults/util.swift#L121-L134 Maybe underscore prefixed types could be hidden by default?

sindresorhus avatar May 21 '20 08:05 sindresorhus

@mattt One use case that we have is including some private APIs that are not meant for public consumption.

Currently we use /// :nodoc: to exclude from our Jazzy doc output.

Is there a better way to support this?

marknorgren avatar Oct 02 '20 15:10 marknorgren

@mrkd Could you tell me more about your use case? Why is the private access modifier (which would hide the declaration) unsuitable for such a method?

mattt avatar Oct 04 '20 13:10 mattt

@mattt - I should clarify these are not private APIs but more like beta APIs that are undocumented and not to be used for external users. Similar to 'private' APIs in iOS that are accessible if you know what to call, but they are not documented.

We still want to keep documentation for our internal users until these APIs are ready for external consumption.

marknorgren avatar Oct 16 '20 04:10 marknorgren

One solution could be to display stability for a given API. This would be similar to how Node.js declares some APIs "experimental" or "stable"in its documentation.

Not sure how it should be encoded though. Maybe in a similar way to explicit parameter and return value documentation?

MaxDesiatov avatar Oct 16 '20 07:10 MaxDesiatov

@mrkd Thanks for clarifying. I think there are a few different solutions to that problem. In Swift, the convention is to use an underscore prefix (_) for beta language features like @_exported or (until recently) @_functionBuilder. So you might do that. If there are a lot of these APIs, you might parcel them into a separate module with "Beta" or "Experimental" in the name. Or you might just include big bold words in the documentation.

If we did want to support annotations to symbol documentation, my preferred solution would involve processing instructions. For example:

/// Says hello
/// <? swift-doc stability="experimental" ?> 
func greetPerson(named name: String) { }

I know I've mentioned these before, but I think they're such a nice solution. As flexible as you need them to be and degrade nicely, since they aren't rendered.

mattt avatar Oct 30 '20 17:10 mattt