-
-
Notifications
You must be signed in to change notification settings - Fork 403
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
@api-filtered class is incorrectly hidden if containing module not marked with same @api #1380
Comments
Unfortunately that's not the expectation YARD provides, though I understand the confusion. There is a bug here, but I'm not sure fixing it will necessarily do what you want. Specifically, the bug is YARD is not warning you about this behavior and creating an inconsistent state. If YARD was going to "fix" this, it would probably do so by hiding MyClass and warning you that your public API is invalid. Again, I'm sure that's not what you want. The issue is that by applying At the end of the day, you might want to ask whether MyModule is actually private, or whether you just mis-documented it as such? Remember: if you omit public in your example, you're effectively calling it non-public. Presumably if MyClass is to be found, its parent namespace must also be publicly available in your API, no? As a suggestion, it might be easier to accomplish the same result by doing this in the opposite direction: rather than assuming everything unmarked is private and only those with Alternatively, a little added tip here: $ ruby -ryard -e 'YARD::CLI::Yardoc.run("-q"); p YARD::Registry.at("MyModule::MyClass").docstring.to_raw'
"@api public" Note, that this means everything inside MyModule now has |
Thanks @lsegal for the clear and detailed response. The reasoning that the container must be public for the child to be public does make sense. I would have inferred that but for the fact that all of the methods of Now if I understand you, the intended rule of YARD queries is: "a construct (module/class/method) is only matched by a query if all of its ancestors in the container hierarchy also match the query". Call this the "ancestor-match rule". IMO this rule is counterintuitive, as code objects that live deeper in the container hierarchy are often classified in a way that doesn't make sense for their containers. For instance, this implies that to query for That said, I haven't thought enough about the issue to propose an intelligent alternative that also accounts for the logic of namespace hiding you mention. As for your suggestions regarding the "direction" of API-marking (default public or default private): The example I posted is a simplified version of my actual use-case, in which the container module is actually the root module of my gem. In my gem (and I find in most of the stuff I code-- I try to keep my public API as small as possible) the majority of methods are private. So I prefer treating everything as private by default, and explicitly marking constructs as public. But according to the ancestor-match rule, that's impossible with transitive api tags, because it's impossible for a query to return any results if it doesn't match the root module. So It is impossible to query any api that is not the default api (since the default is set by the transitive root module tag). IMO this makes the I do find the current state of affairs pretty counterintuitive though. Maybe some docs would help? I'd actually be happy to translate the knowledge I've gained debugging this issue into a short guide for inclusion in the YARD docs showing how to generate docs under various API scenarios, but I'm not sure of where the guide should live in the docs. |
I'm not sure I'm following here. What's the repro case for this? If you apply
Sorry, one of the things I did not make very clear at all with my last paragraph was actually a pretty important feature of transitivity, so let me correct my last message: Transitive tags are applied transitively to child objects unless there is an overriding tag in the child. In other words, transitive tags are not applied to children that already have a tag of that type defined on them. This is a very important distinction and why you can in fact do something as simple as: # @api public
module MyModule
class MyClass
def my_method; end
# @api private
def my_private_api_method; end
end
# @api private
class MyPrivateClass; end
end And One might assume that you would end up with both
FWIW this is documented in the tag documentation, though even I completely missed explaining this detail above, so one could argue it needs better explanation than what is below:
If you have recommendations / suggestions, PRs are always welcome to improve docs. The Getting Started guide is long overdue for an improvement, and perhaps that is what you're describing, but you may also consider that some of this belongs in separate documentation, i.e. littered through quick start, advanced topics, tag doc improvements, etc. I would love to see any contributions there! |
Also just adding a bit extra to one part of your initial response which I think is relevant:
This is a fair callout, though I wouldn't consider it counter-intuitive. It kind of depends on what your expectation is. If the expectation is to generate with For example, a displayed object might require the context of objects that were otherwise hidden by a filter. A common scenario here is a subclass that inherits a class that was filtered out by FWIW, while we're on the subject of filtering, it's worth pointing out that In the case of the original code pasted in this issue, you could create a filter that finds anything with |
The repro is the original case I posted. Yes,
But we have a situation where the methods of Regarding transitive tags, I understand what you're saying here about explicit marking overriding transitivity. My point is that the only API that can ever be matched is the default one. That is what I find counterintuitive. You can mark up constructs with arbitrary values for Regarding docs, I will poke around and look for a good place to make my contribution. |
When I mark a class
MyModule::MyClass
with@api public
, then runyard doc --api public
:MyClass
incorrectly does not show up in the "Class List"MyClass
correctly show up in the "Method List"MyModule
with@api public
, then it works.Steps to reproduce
$ mkdir -p yardtest/lib
$ cd yardtest
lib/test.rb
:$ yard doc --api public
# output shows 1 class, 1 method$ open doc/index.html
MyClass
is not listedlib/test.rb
to add# @api public
as the first line, overmodule MyModule
$ yard doc --api public
doc/index.html
, this time the output is correctMyClass
is in the class listExpected Output
Classes marked with
@api public
should show in the class list regardless of whether the containing module is marked as such.Environment details:
ruby -v
): ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin20]yard -v
):yard 0.9.26
The text was updated successfully, but these errors were encountered: