From 9a7c184a13763535c5c7589ff71d2240135233bf Mon Sep 17 00:00:00 2001 From: Rocco Caputo Date: Fri, 18 Nov 2011 03:17:15 -0500 Subject: [PATCH] Inherit or automatically generate attribute documentation. Documentation for attributes is inherited from base classes if necessary. When there's absolutely no documentation for an attribute, Pod::Plexus will generate a "not documented yet" stub. There's a TODO comment to extend that by introspecting the attribute. --- pod-plexus/lib/Pod/Plexus/Code.pm | 1 + pod-plexus/lib/Pod/Plexus/Module.pm | 82 +++++++++--------------- pod-plexus/lib/Pod/Plexus/Module/Docs.pm | 59 ++++++++++++++--- 3 files changed, 84 insertions(+), 58 deletions(-) diff --git a/pod-plexus/lib/Pod/Plexus/Code.pm b/pod-plexus/lib/Pod/Plexus/Code.pm index c808ff2..a49efca 100644 --- a/pod-plexus/lib/Pod/Plexus/Code.pm +++ b/pod-plexus/lib/Pod/Plexus/Code.pm @@ -54,6 +54,7 @@ sub is_documented { push @$errors, "Object $self ... class needs to override validate()"; } + sub validate { my ($self, $module, $errors) = @_; push @$errors, "Object $self ... class needs to override validate()"; diff --git a/pod-plexus/lib/Pod/Plexus/Module.pm b/pod-plexus/lib/Pod/Plexus/Module.pm index 2314d82..d069d65 100755 --- a/pod-plexus/lib/Pod/Plexus/Module.pm +++ b/pod-plexus/lib/Pod/Plexus/Module.pm @@ -137,83 +137,65 @@ sub cache_structure { return @errors if push @errors, $self->docs()->cache_plexus_directives(); - # 2. Index code entities: attributes and methods. - # Must be done before documentation is parsed. - # Methods must come before attributes. - -# return @errors if push @errors, ( -# $self->code()->cache_all_methods(), -# $self->code()->cache_all_attributes() -# ); - - # 3. Parse, build and collect documentation references. + # 2. Parse, build and collect documentation references. return @errors if push @errors, $self->docs()->cache_all_matter(); - # 4. Acquire documentation for things that have been inherited and - # documented elsehwere. As long as we don't already have them. + # 3. Inherit documentation from base classes as needed. Generate + # documentation stubs for things that would otherwise go + # unmentioned. + # + # Attributes come first since their accessors must be treated before + # methods are. return @errors if push @errors, ( + $self->docs()->flatten_attributes(), $self->docs()->flatten_methods(), - $self->docs()->flatten_attributes() ); - # 5. Document things we can intuit from Moose and/or Class::MOP. + # 4. Document things we can intuit from Moose and/or Class::MOP. + # This may actually be rolled into flatten_attributes() since the + # timing would be better there. return @errors if push @errors, $self->docs()->document_accessors(); - # 6. Make sure all code and documentation is accounted for. This - # step may be obsolete if everything is auto-docuemented as a last - # resort. + # 5. Do any final validations. Is everything documented? Do all + # documentation sections reference actual implementation? I'm not + # entirely sure this step's needed so far, but it remains as a + # reminder. return @errors if push @errors, ( $self->docs()->validate_code(), $self->code()->validate_docs() ); -# push @errors, $self->ensure_documentation(); -# return @errors if @errors; + # We succeeded if we got this far. return; - # ---------- - # TODO - Gathering or grouping documentation into topics. The idea - # is to render them as "=topic" so that Pod::Weaver can gather them. - # Possible syntax: + # SOME OLDER IDEAS TO CONSIDER. + # + # Gathering and grouping documentation into topics. Not all + # =methods are created equal. For exmaple, POE's timer methods + # could all be grouped under "=head2 Timer Methods" with a preamble. + # + # Hierarchical grouping. Sometimes a group needs subgroups. POE's + # timer methods are a good example... there's a group that + # identifies timers by name, and there's another set of methods that + # returns and uses timer IDs. # - # TODO - Gathering topics under higher level topics. Hierarchical - # documentation, if it's possible. This would be nice to do without - # building an explicit outline. + # Possible syntax: # - # =method delay EVENT [, SECONDS [, CONTINUATION DATA] ] - # SS XD X + # =method delay EVENT [, SECONDS [, CONTINUATION_DATA] ] + # SS XD X # - # Where XD<> is a "definition" cross-reference. The index will + # Where XD<> is a "definition" cross-reference. The index could # highlight this entry as the definition for "delay". # - # SS puts this method in the "timers" topic. + # SS puts this method under the "timers" topic (section). # # X indexes this section under the "relative - # timers" topic, but it doesn't _define_ that topic. - # ---------- - - # NOTE - Attributes and methods are special. It's okay for them to - # be processed specially. - - # Once explicit code and documentation are associated, we can see - # which remain undocumented and need to inherit documentation or - # have boilerplate docs written. - - # TODO - For each undocumented attribute or method, try to find - # documentation up the inheritance or role chain until we reach the - # entity's implementation. - - # TODO - Load and parse all cross referenced modules. We need - # enough data to set xrefs, import inclusions, and import examples - # from other, possibly non-Moose distributions. - - # TODO - Validate whether all cross referenced modules exist, within - # and outside the current distribution. + # timers" topic, but that topic doesn't _define_ it. } diff --git a/pod-plexus/lib/Pod/Plexus/Module/Docs.pm b/pod-plexus/lib/Pod/Plexus/Module/Docs.pm index a9f727c..2997168 100644 --- a/pod-plexus/lib/Pod/Plexus/Module/Docs.pm +++ b/pod-plexus/lib/Pod/Plexus/Module/Docs.pm @@ -166,18 +166,16 @@ sub flatten_methods { my $self = shift(); my @errors; - my $docs = $self->_elemental()->children(); - my $meta_class = $self->get_meta_class(); - METHOD: foreach my $method ($meta_class->get_all_methods()) { - my $method_name = $method->name(); + METHOD: foreach my $meta_method ($meta_class->get_all_methods()) { + my $method_name = $meta_method->name(); # Skip internal methods. next METHOD if $method_name =~ /^__pod_plexus_/; - # And skip private methods, why not? - next METHOD if $method_name =~ /^_/; + # Skip methods upon request. + next METHOD if $self->skips_method($method_name); # Skip if documented. my $pod_plexus_name = "__pod_plexus_matter_method__$method_name\__"; @@ -194,13 +192,14 @@ sub flatten_methods { blank_line(), cut_paragraph(), ); + next METHOD; } # Nothing to inherit. How about we document that it's not # documented? # But not if it's private. - next METHOD if $self->skips_method($method_name); + next METHOD if $method_name =~ /^_/; push @errors, $self->_generate_documentation( generic_command("method", $method_name . "\n"), @@ -220,7 +219,51 @@ sub flatten_methods { sub flatten_attributes { my $self = shift(); - warn " TODO - flatten_attributes()"; + my @errors; + my $meta_class = $self->get_meta_class(); + + ATTRIBUTE: foreach my $meta_attribute ($meta_class->get_all_attributes()) { + my $attribute_name = $meta_attribute->name(); + + # Skip if documented. Yes, this calls get_method() here. + my $pod_plexus_name = "__pod_plexus_matter_attribute__$attribute_name\__"; + next ATTRIBUTE if $meta_class->get_method($pod_plexus_name); + + # Inherit it. + my $doc_method = $meta_class->find_method_by_name($pod_plexus_name); + if ($doc_method) { + my $ancestor_package = $doc_method->package_name(); + push @errors, $self->_generate_documentation( + generic_command( + "inherits", "$ancestor_package attribute $attribute_name\n" + ), + blank_line(), + cut_paragraph(), + ); + next ATTRIBUTE; + } + + # Nothing to inherit. How about we document that it's not + # documented? + + # But not if it's private. + next ATTRIBUTE if $attribute_name =~ /^_/; + + # TODO - We can glean a lot about this attribute from + # Moose::Meta::Attribute and Class::MOP::Attribute. + + push @errors, $self->_generate_documentation( + generic_command("attribute", $attribute_name . "\n"), + blank_line(), + text_paragraph("Attribute [% s.name %] is not yet documented.\n"), + blank_line(), + cut_paragraph(), + ); + + next ATTRIBUTE; + } + + return @errors; return; }