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

Issue #5759 -- inherit documentation #6981

Conversation

dscottboggs
Copy link
Contributor

This issue came to my attention and I thought I'd take a stab at it. I hope this solution works, and is the way you want to go about resolving this issue.

Added option to inherit documentation from a superclass's methods or class methods
Added option to inherit documentation from a superclass's macro definition
Added option to inherit documentation from a superclass's constant definition
end

def inherit_docs?(str : String)
str.starts_with?(":inherit:") || str.starts_with?("inherit")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just :inherit:, ditto all below (btw could it get more DRY?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also I'd change it to str == ":inherit:"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if you want to inherit docs and add some specific doc afterward?
like:

# :inherit:
# Some specific doc
def foo
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bew I thought about but it's IMO better to add it in another PR since it'd be beneficial for :ditto: too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if you want to inherit docs and add some specific doc afterward?

I'm not sure that makes sense with :inherit: or :ditto:. What would it mean? Just append everything following the keyword? Or ignore it as internal comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say append everything, for internal comments you'd use :nodoc: or put the doc inside the method (as a workaround)

@@ -20,7 +20,15 @@ class Crystal::Doc::Method
end

def doc
@def.doc
if inherit_docs? @def.doc
(@type.superclass.lookup_method(name) || @type.superclass.lookup_class_method(name)).doc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use @type.ancestors which gives you the full type hierarchy (including modules) because @type.superclass just gives you the superclass.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also wrong because it just checks for the name, ignoring argument names and types.

@asterite
Copy link
Member

This is good!

Though I'm thinking it's probably better to have an @[Override] annotation which will error if a method doesn't override another one. The problem is defining the semantic of this, but for starters we can require having the exact same signature. I'll start to work on this. And once we have this we can replace :inherit: with this.

@RX14
Copy link
Contributor

RX14 commented Oct 23, 2018

@asterite aren't they orthogonal?

@asterite
Copy link
Member

@RX14 If you override a method and you don't specify docs, I think it makes sense to inherit the docs.

@straight-shoota
Copy link
Member

@asterite https://github.com/GrottoPress/crystal-annotation has a simple @[Override] annotation.

And once we have this we can replace :inherit: with this.

Wouldn't it make more sense to don't even merge :inherit: in the first place, even if it means waiting a little bit for @[Override]?

But in general, I like this either way.

@RX14
Copy link
Contributor

RX14 commented Oct 24, 2018

@asterite inherit allows composing documentation by adding :inherit: and a suffix.

@Sija
Copy link
Contributor

Sija commented Oct 24, 2018

@RX14 not with the current implementation from this PR, but as I said earlier in #6981 (comment) it's sensible to do it in a followup PR.

@asterite
Copy link
Member

@RX14 Ah, that makes sense. Well, in any case, the implementation in this PR is wrong. One should copy the logic of my "Redefine and Override annotation" PR.

@straight-shoota
Copy link
Member

inherit allows composing documentation by adding :inherit: and a suffix.

I don't think that's actually much helpful, it might rather be contraproductive at times.

When a method is overriden in a child class, it usually changes behaviour from the parent implementation. This could either be only internal changes, not worth mentioning. Then just inheriting the parent's docs is enough. The can be achieved with either :inherit: or @[Override].
If the changes are relevant to the public API, this should be mentioned in the main part of the method doc, typically near the top.
The option to just append something to the parent's docs, is probably not much help for most use cases.

@ysbaddaden
Copy link
Contributor

My use case for :inherit:, or an annotation that would copy the documentation, is Crystal::System.

For now, we have documented methods that often delegate to another type/module under the Crystal::System namespace, because otherwise we'd replace the method and lose the documentation (or have to duplicate it). It would be great to have documented abstract methods on types and the implementations in target specific files by reopening the types, yet keep the documentation from the abstract methods.

I'm fine with always copying the docs from an abstract method when it's implemented, or make it explicit with :inherit:, or introduce an annotation for stricter checks, ...

@straight-shoota
Copy link
Member

@ysbaddaden In your Crystal::System implementation example, the methods wouldn't be inherited, so abstract, :inherit: or @[Override] wouldn't apply anyway.

And honestly I can't see any benefit over documenting a public API method which calls a private implementation method defined in Crystal::System.

@dscottboggs
Copy link
Contributor Author

Sorry about jumping the gun on this PR, I knew like right after uploading that my implementation wasn't going to cut it. I'll do more thorough testing and research next time.

I was going to begin working on this now, but I saw @asterite 's #6989 and I like that syntax way better than the one suggested by @bew that inspired this PR.

@dscottboggs dscottboggs deleted the bug/5759-inherit-documentation branch October 26, 2018 23:46
@RX14
Copy link
Contributor

RX14 commented Oct 27, 2018

@dscottboggs thanks a lot for making this PR! The compiler is a very complex piece of code.

@asterite
Copy link
Member

@dscottboggs Also it's thanks to you I decided to tackle these issues myself :-)

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

Successfully merging this pull request may close these issues.

None yet

7 participants