Repository navigation
Commit d13636a
Part of #1591. This PR only changes the region directives
(`:stopdoc:`/`:startdoc:`/`:enddoc:`). `:nodoc:` semantics are unchanged
and will be addressed separately.
## Problem
These directives are currently implemented as mutations of shared
`CodeObject` state
(`document_self`/`document_children`/`done_documenting`). Since classes
are open and shared across files in the store, a `:stopdoc:` without a
matching `:startdoc:` leaks into later reopenings of the class within
the same file. The actual behavior is a product of mutation order, and
neither the documentation nor the implementation defines what these
directives mean.
## New semantics
The parser now tracks the document control state
(`:startdoc:`/`:stopdoc:`/`:enddoc:`) as a lexical region:
- The state is inherited when entering a class/module scope and
automatically restored at its `end`. A `:stopdoc:` can no longer leak
out of the scope it was written in.
- `:startdoc:` inside a nested scope re-enables documentation for that
scope only.
- `:enddoc:` disables documentation for the rest of the current scope
and cannot be cancelled within it, even by `:startdoc:`. It no longer
marks the container object as `done_documenting` globally.
- Classes/modules defined inside a suppressed region are still created
as namespaces (marked as ignored) and their bodies are visited, so an
inner `:startdoc:` works. They become documentable when they receive
documentable contents outside the region, possibly from another file.
Namespaces that never receive contents are removed from the store on
`Store#complete` (`Context#remove_from_documentation?` now also covers
ignored contexts, which is what `CodeObject#ignore` was documented to do
in GH #55).
- Document control scopes are the syntactic units that change the
definition context (`class`/`module` bodies, `class << self`, and
definition-creating blocks). `if`/`while`/`begin` do not create scopes,
consistent with Ruby's own scoping rules.
## Bug fixes
On master, these directives mutate the state of whatever object they
happen
to be applied to, so their effect escapes the scope they were written
in.
Some examples of what this PR fixes:
**A `:stopdoc:` inside `class << self` no longer leaks out of the
singleton
scope:**
```ruby
class Net::HTTPResponse
class << self
# :stopdoc:
def internal; end
end
# master: NOT documented / this PR: documented
attr_reader :http_version
end
```
This is exactly what happened to [the Ruby 4.0
documentation](https://docs.ruby-lang.org/en/4.0/Net/HTTPResponse.html)
**A `:stopdoc:` no longer leaks into later reopenings of the class.**
Note
that on master the two ways of reopening `A::B` below do not even agree
with
each other: `f` is documented but `g` is not, because the leaked state
only
affects the nested-class form. The behavior was an artifact of the
implementation, not a specification:
```ruby
class A
# :stopdoc:
def internal; end
end
class A::B
# master: documented / this PR: documented
def f; end
end
class A
class B
# master: NOT documented / this PR: documented
def g; end
end
end
```
## Compatibility notes
- `:nodoc:` is untouched. However, `:startdoc:` additionally calls
`start_doc` on the current container, because `module Net #:nodoc:`
followed by `:stopdoc:`/`:startdoc:` regions is a common pattern that
expects `:startdoc:` to make the container documentable again. This is a
transitional measure until `:nodoc:` gets lexical semantics, at which
point the pattern itself becomes unnecessary. Containers created inside
a suppressed region are excluded, so a bare `:startdoc:` cannot revive
an empty hidden class.
- A comment linked to a `class << X` line is now processed in the
enclosing scope. Nothing consumes such a comment as documentation, and
processing it inside the singleton scope would make a `:startdoc:`
written there expire at the singleton's `end` (this pattern appears in
net/http).
- Region directives in modifier position (e.g. `class Foo # :stopdoc:`
at the end of a line) are no longer applied. There are no occurrences of
this form in ruby/ruby, rails, or the bundled gems.
## Validation
Compared generated HTML for ruby/ruby `lib` and six Rails frameworks
between master and this branch. The sets of generated files are
identical, and every remaining difference is the directives working as
their authors intended:
- Module aliases written inside `:stopdoc:` regions (`Ripper =
Prism::Translation::Ripper` in prism's shim.rb,
`HashWithIndifferentAccess = ...` in activesupport) are no longer
documented. This also removes a duplicated "Ripper" entry from the
navigation and stops bare "Ripper" mentions (which refer to the stdlib
Ripper) from being cross-referenced to `Prism::Translation::Ripper`.
Note: the old accidental link on `HashWithIndifferentAccess` in
Hash.html was arguably useful; writing the full name in the comment
restores it.
- `Net::HTTPResponse` regains its `include Net::HTTPHeader`. The old
implementation lost it because a `:stopdoc:` inside `class << self`
leaked out of the singleton scope; net/http.rb contains a "this is to
fix bug in RDoc" workaround comment for this exact class of leak.
- `ActionDispatch::Journey` (`# :nodoc:`) no longer appears in the
navigation. Its page is still generated because it has documented
children.
- Namespaces fully contained in suppressed regions (e.g.
`Net::HTTPBadResponse` region in net/http.rb, `Timeout::Request`) no
longer produce empty pages.
## Follow-ups (out of scope here)
- Lexical/shallow semantics for `:nodoc:` (the hard part of #1591); the
`start_doc` compatibility shim and the `received_nodoc` guard in
promotion can be removed then.
- Warnings for degenerate usages (redundant `:stopdoc:`, directives
after `:enddoc:`, standalone `:nodoc:` in the middle of a class body).
- A visibility trace output (`file:line: stopdoc applied to X`) as
proposed in
#1591 (comment); the
parser now has the lexical information to make this cheap.
- The C parser still uses the old CodeObject-state mechanism and is
intentionally untouched.
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent c162c6b commit d13636a
4 files changed
Lines changed: 434 additions & 16 deletions
File tree
- lib/rdoc
- code_object
- parser
- test/rdoc
- generator
- parser
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1066 | 1066 | | |
1067 | 1067 | | |
1068 | 1068 | | |
| 1069 | + | |
| 1070 | + | |
1069 | 1071 | | |
1070 | | - | |
| 1072 | + | |
1071 | 1073 | | |
1072 | 1074 | | |
1073 | 1075 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
155 | 202 | | |
156 | 203 | | |
157 | 204 | | |
| |||
172 | 219 | | |
173 | 220 | | |
174 | 221 | | |
| 222 | + | |
175 | 223 | | |
176 | 224 | | |
177 | 225 | | |
| |||
183 | 231 | | |
184 | 232 | | |
185 | 233 | | |
| 234 | + | |
186 | 235 | | |
187 | 236 | | |
188 | 237 | | |
| |||
307 | 356 | | |
308 | 357 | | |
309 | 358 | | |
| 359 | + | |
310 | 360 | | |
311 | 361 | | |
312 | 362 | | |
| |||
353 | 403 | | |
354 | 404 | | |
355 | 405 | | |
| 406 | + | |
356 | 407 | | |
357 | 408 | | |
358 | 409 | | |
| |||
375 | 426 | | |
376 | 427 | | |
377 | 428 | | |
| 429 | + | |
| 430 | + | |
378 | 431 | | |
379 | 432 | | |
380 | 433 | | |
381 | 434 | | |
382 | 435 | | |
383 | 436 | | |
384 | 437 | | |
| 438 | + | |
385 | 439 | | |
386 | 440 | | |
387 | 441 | | |
| |||
427 | 481 | | |
428 | 482 | | |
429 | 483 | | |
| 484 | + | |
430 | 485 | | |
431 | 486 | | |
432 | 487 | | |
| |||
510 | 565 | | |
511 | 566 | | |
512 | 567 | | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
513 | 571 | | |
514 | 572 | | |
515 | 573 | | |
| |||
532 | 590 | | |
533 | 591 | | |
534 | 592 | | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
535 | 597 | | |
536 | 598 | | |
537 | 599 | | |
| |||
552 | 614 | | |
553 | 615 | | |
554 | 616 | | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
555 | 620 | | |
556 | 621 | | |
557 | 622 | | |
| |||
560 | 625 | | |
561 | 626 | | |
562 | 627 | | |
| 628 | + | |
563 | 629 | | |
| 630 | + | |
| 631 | + | |
564 | 632 | | |
565 | 633 | | |
566 | 634 | | |
567 | 635 | | |
568 | 636 | | |
569 | 637 | | |
570 | 638 | | |
| 639 | + | |
571 | 640 | | |
572 | 641 | | |
573 | 642 | | |
| |||
577 | 646 | | |
578 | 647 | | |
579 | 648 | | |
| 649 | + | |
580 | 650 | | |
| 651 | + | |
581 | 652 | | |
582 | 653 | | |
583 | 654 | | |
| |||
587 | 658 | | |
588 | 659 | | |
589 | 660 | | |
590 | | - | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
591 | 665 | | |
592 | 666 | | |
593 | 667 | | |
| |||
596 | 670 | | |
597 | 671 | | |
598 | 672 | | |
| 673 | + | |
599 | 674 | | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
600 | 678 | | |
601 | 679 | | |
602 | 680 | | |
| |||
622 | 700 | | |
623 | 701 | | |
624 | 702 | | |
625 | | - | |
626 | 703 | | |
| 704 | + | |
627 | 705 | | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
628 | 709 | | |
629 | 710 | | |
630 | 711 | | |
| |||
650 | 731 | | |
651 | 732 | | |
652 | 733 | | |
| 734 | + | |
653 | 735 | | |
654 | 736 | | |
| 737 | + | |
| 738 | + | |
655 | 739 | | |
656 | 740 | | |
657 | 741 | | |
| |||
691 | 775 | | |
692 | 776 | | |
693 | 777 | | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
700 | 790 | | |
701 | 791 | | |
702 | 792 | | |
| |||
755 | 845 | | |
756 | 846 | | |
757 | 847 | | |
| 848 | + | |
758 | 849 | | |
| 850 | + | |
| 851 | + | |
759 | 852 | | |
760 | 853 | | |
761 | 854 | | |
762 | 855 | | |
763 | 856 | | |
764 | 857 | | |
765 | 858 | | |
766 | | - | |
767 | 859 | | |
768 | 860 | | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
769 | 864 | | |
770 | 865 | | |
771 | 866 | | |
| |||
787 | 882 | | |
788 | 883 | | |
789 | 884 | | |
| 885 | + | |
790 | 886 | | |
791 | 887 | | |
792 | 888 | | |
| |||
803 | 899 | | |
804 | 900 | | |
805 | 901 | | |
806 | | - | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
807 | 909 | | |
808 | 910 | | |
809 | 911 | | |
| |||
812 | 914 | | |
813 | 915 | | |
814 | 916 | | |
815 | | - | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
816 | 922 | | |
817 | 923 | | |
818 | 924 | | |
819 | 925 | | |
820 | | - | |
821 | 926 | | |
822 | 927 | | |
823 | | - | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
824 | 944 | | |
825 | 945 | | |
826 | 946 | | |
| |||
975 | 1095 | | |
976 | 1096 | | |
977 | 1097 | | |
978 | | - | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
979 | 1101 | | |
980 | 1102 | | |
981 | 1103 | | |
| |||
990 | 1112 | | |
991 | 1113 | | |
992 | 1114 | | |
| 1115 | + | |
993 | 1116 | | |
994 | 1117 | | |
995 | 1118 | | |
| |||
1150 | 1273 | | |
1151 | 1274 | | |
1152 | 1275 | | |
| 1276 | + | |
1153 | 1277 | | |
1154 | 1278 | | |
1155 | 1279 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
355 | 355 | | |
356 | 356 | | |
357 | 357 | | |
358 | | - | |
| 358 | + | |
| 359 | + | |
359 | 360 | | |
360 | 361 | | |
361 | 362 | | |
| |||
0 commit comments