diff --git a/doc/Type/Bool.rakudoc b/doc/Type/Bool.rakudoc index d1475e35b..a9f09a1e9 100644 --- a/doc/Type/Bool.rakudoc +++ b/doc/Type/Bool.rakudoc @@ -70,7 +70,7 @@ the "lowest" Bool enum value, its own predecessor is also C. method enums(--> Hash:D) -Returns a L of enum-pairs. Works on both the L|/type/Bool> type +Returns a L of enum-pairs. Works on both the C type and any key. say Bool.enums; # OUTPUT: «{False => 0, True => 1}␤» diff --git a/xt/rakudoc-types.rakutest b/xt/rakudoc-types.rakutest index 44f680889..965ba289c 100755 --- a/xt/rakudoc-types.rakutest +++ b/xt/rakudoc-types.rakutest @@ -8,7 +8,12 @@ When referring to items that are types, the required format is: Any other formatting code that refers to a type will fail the test; any C<> that isn't inside of an L<> will fail, and any L<> that doesn't have a C<> -will fail. +will fail. Links may end with an optional #id. + +Exceptions: + +=item Referring to a type on its own page should only use C<>. +=item It's Ok to refer to a routine page with the same name instead. =end overview @@ -26,56 +31,103 @@ if @files { plan :skip-all } +# TODO: Renders #tags oddly. sub render-node($node) { my $type = $node.contents.join(''); my $result = $node.type ~ '<' ~ $type; if $node.type eq 'L' { - $result ~= '|' ~ $node.meta + $result ~= '|' ~ $node.meta.join(''); } $result ~= '>'; - + $result; } -sub is-valid-type($node, $parent) { +# given a slashy type, see if that file exists on disk +# To work on case-insensitive file systems, we grep the dir listing +# rather than check a preconstructed path. + +sub file-exists($type) { + next if $type.fc eq 'raku'|'perl'; # Too common + + my @parts = $type.split('/'); + + + my $path = "doc/Type".IO; + while @parts { + my $part = @parts.shift; + $part ~= '.rakudoc' unless @parts.elems; + return False unless $path.dir.grep(*.basename eq $part); + $path = $path.child($part); + } + return True; +} + +sub is-valid-type($node, $parent, $file) { # only care about I<>, C<>, L<>, etc. return unless $node ~~ Pod::FormattingCode; + return if $node.type eq 'X'; # These are OK as is, and not user-visible - # Does this match a type? - my $type = $node.contents.join('').subst('::','/', :g); - return unless "doc/Type/$type.rakudoc".IO.f; + # Does this match a documented type? + my $type = $node.contents.join(''); + my $type-slash = $type.subst('::', '/', :g); + my $type-colon = $type.subst('/', '::', :g); + + return unless file-exists($type-slash); + + if $file eq "doc/Type/$type-slash.rakudoc" { + # We are on the same page as this type. Don't link it, only C<> it. + if $node.type ne 'C' or $type ne $type-colon { + flunk "{render-node($node)} should be C<$type-colon> - self reference"; + } elsif $parent ~~ Pod::FormattingCode { + flunk "{$parent.type}<{render-node($node)}> should be C<$type> - bad parent FormattingCode - self reference"; + } else { + pass "{render-node($node)} OK - self reference"; + } + return; + } # Might be nested but we only report on the innermost here. if $node.type ne 'C' { - flunk "{render-node($node)} should be L|/type/$type>"; + flunk "{render-node($node)} should be L|/type/$type-colon>"; return; } # Probably in a paragraph if $parent === Nil or ! ($parent ~~ Pod::FormattingCode) { - flunk "{render-node($node)} should be L|/type/$type>"; + flunk "{render-node($node)} should be L|/type/$type-colon>"; return; } # Wrapped, but not in an L<> if $parent.type ne 'L' { - flunk "$parent.type<{render-node($node)}> should be L|/type/$type> - bad parent FormattingCode"; + flunk "$parent.type<{render-node($node)}> should be L|/type/$type-colon> - bad parent FormattingCode"; return; - } elsif $parent.meta ne "/type/$type" { - # Wrapped in an L<> but wrong URL - flunk "L<{render-node($node)}|$parent.meta> should be L|/type/$type> - bad link"; - } else { + } + + my $meta = $parent.meta.join(''); + if $meta eq "/type/$type-colon" or + $meta.starts-with: "/type/{$type-colon}#" { # \o/ - pass "$type reference correctly formatted."; + pass "L<{render-node($node)}|$meta>"; + } else { + if $meta.starts-with('/routine/') { + # Is this pointing to an routine page? /routine is generated, so we cannot verify + # the existence of an actual file; trust if present. + pass "L<{render-node($node)}|$meta> - routine"; + } else { + # Wrapped in an L<> with wrong URL + flunk "L<{render-node($node)}|$meta> should be L|/type/$type-colon> - bad link"; + } } } -sub walk-content($item, $parent) { - is-valid-type($item, $parent); +sub walk-content($item, $parent, $file) { + is-valid-type($item, $parent, $file); next unless $item.can('contents'); for @($item.contents) -> $child { - walk-content($child, $item); + walk-content($child, $item, $file); } } @@ -85,6 +137,6 @@ for @files -> $file { # This emits pass or flunk for each local L<> found. subtest $file => { - walk-content($_, Nil) for @chunks; + walk-content($_, Nil, $file) for @chunks; } }