@@ -8,7 +8,12 @@ When referring to items that are types, the required format is:
8
8
9
9
Any other formatting code that refers to a type will fail the test; any C <>
10
10
that isn't inside of an L <> will fail, and any L <> that doesn't have a C <>
11
- will fail.
11
+ will fail. Links may end with an optional #id.
12
+
13
+ Exceptions:
14
+
15
+ = item Referring to a type on its own page should only use C <> .
16
+ = item It's Ok to refer to a routine page with the same name instead.
12
17
13
18
= end overview
14
19
@@ -26,56 +31,103 @@ if @files {
26
31
plan : skip-all<No rakudoc files specified >
27
32
}
28
33
34
+ # TODO: Renders #tags oddly.
29
35
sub render-node ($ node ) {
30
36
my $ type = $ node . contents. join (' ' );
31
37
my $ result = $ node . type ~ ' <' ~ $ type ;
32
38
if $ node . type eq ' L' {
33
- $ result ~ = ' |' ~ $ node . meta
39
+ $ result ~ = ' |' ~ $ node . meta. join ( ' ' );
34
40
}
35
41
$ result ~ = ' >' ;
36
-
42
+
37
43
$ result ;
38
44
}
39
45
40
- sub is-valid-type ($ node , $ parent ) {
46
+ # given a slashy type, see if that file exists on disk
47
+ # To work on case-insensitive file systems, we grep the dir listing
48
+ # rather than check a preconstructed path.
49
+
50
+ sub file-exists ($ type ) {
51
+ next if $ type . fc eq ' raku' | ' perl' ; # Too common
52
+
53
+ my @ parts = $ type . split (' /' );
54
+
55
+
56
+ my $ path = " doc/Type" . IO ;
57
+ while @ parts {
58
+ my $ part = @ parts . shift ;
59
+ $ part ~ = ' .rakudoc' unless @ parts . elems ;
60
+ return False unless $ path . dir . grep (*. basename eq $ part );
61
+ $ path = $ path . child ($ part );
62
+ }
63
+ return True ;
64
+ }
65
+
66
+ sub is-valid-type ($ node , $ parent , $ file ) {
41
67
# only care about I<>, C<>, L<>, etc.
42
68
return unless $ node ~~ Pod ::FormattingCode;
69
+ return if $ node . type eq ' X' ; # These are OK as is, and not user-visible
43
70
44
- # Does this match a type?
45
- my $ type = $ node . contents. join (' ' ). subst (' ::' ,' /' , : g);
46
- return unless " doc/Type/$ type .rakudoc" . IO . f ;
71
+ # Does this match a documented type?
72
+ my $ type = $ node . contents. join (' ' );
73
+ my $ type-slash = $ type . subst (' ::' , ' /' , : g);
74
+ my $ type-colon = $ type . subst (' /' , ' ::' , : g);
75
+
76
+ return unless file-exists($ type-slash );
77
+
78
+ if $ file eq " doc/Type/$ type-slash .rakudoc" {
79
+ # We are on the same page as this type. Don't link it, only C<> it.
80
+ if $ node . type ne ' C' or $ type ne $ type-colon {
81
+ flunk " { render-node($ node )} should be C<$ type-colon > - self reference" ;
82
+ } elsif $ parent ~~ Pod ::FormattingCode {
83
+ flunk " { $ parent . type} <{ render-node($ node )} > should be C<$ type > - bad parent FormattingCode - self reference" ;
84
+ } else {
85
+ pass " { render-node($ node )} OK - self reference" ;
86
+ }
87
+ return ;
88
+ }
47
89
48
90
# Might be nested but we only report on the innermost here.
49
91
if $ node . type ne ' C' {
50
- flunk " { render-node($ node )} should be L<C<$ type >|/type/$ type >" ;
92
+ flunk " { render-node($ node )} should be L<C<$ type >|/type/$ type-colon >" ;
51
93
return ;
52
94
}
53
95
54
96
# Probably in a paragraph
55
97
if $ parent === Nil or ! ($ parent ~~ Pod ::FormattingCode) {
56
- flunk " { render-node($ node )} should be L<C<$ type >|/type/$ type >" ;
98
+ flunk " { render-node($ node )} should be L<C<$ type >|/type/$ type-colon >" ;
57
99
return ;
58
100
}
59
101
60
102
# Wrapped, but not in an L<>
61
103
if $ parent . type ne ' L' {
62
- flunk " $ parent .type<{ render-node($ node )} > should be L<C<$ type >|/type/$ type > - bad parent FormattingCode" ;
104
+ flunk " $ parent .type<{ render-node($ node )} > should be L<C<$ type >|/type/$ type-colon > - bad parent FormattingCode" ;
63
105
return ;
64
- } elsif $ parent . meta ne " /type/$ type" {
65
- # Wrapped in an L<> but wrong URL
66
- flunk " L<{ render-node($ node )} |$ parent .meta> should be L<C<$ type >|/type/$ type > - bad link" ;
67
- } else {
106
+ }
107
+
108
+ my $ meta = $ parent . meta. join (' ' );
109
+ if $ meta eq " /type/$ type-colon" or
110
+ $ meta . starts-with : " /type/{ $ type-colon } #" {
68
111
# \o/
69
- pass " $ type reference correctly formatted." ;
112
+ pass " L<{ render-node($ node )} |$ meta >" ;
113
+ } else {
114
+ if $ meta . starts-with (' /routine/' ) {
115
+ # Is this pointing to an routine page? /routine is generated, so we cannot verify
116
+ # the existence of an actual file; trust if present.
117
+ pass " L<{ render-node($ node )} |$ meta > - routine" ;
118
+ } else {
119
+ # Wrapped in an L<> with wrong URL
120
+ flunk " L<{ render-node($ node )} |$ meta > should be L<C<$ type >|/type/$ type-colon > - bad link" ;
121
+ }
70
122
}
71
123
}
72
124
73
- sub walk-content ($ item , $ parent ) {
74
- is-valid-type($ item , $ parent );
125
+ sub walk-content ($ item , $ parent , $ file ) {
126
+ is-valid-type($ item , $ parent , $ file );
75
127
76
128
next unless $ item . can (' contents' );
77
129
for @ ($ item . contents) -> $ child {
78
- walk-content($ child , $ item );
130
+ walk-content($ child , $ item , $ file );
79
131
}
80
132
}
81
133
@@ -85,6 +137,6 @@ for @files -> $file {
85
137
86
138
# This emits pass or flunk for each local L<> found.
87
139
subtest $ file => {
88
- walk-content($ _ , Nil ) for @ chunks ;
140
+ walk-content($ _ , Nil , $ file ) for @ chunks ;
89
141
}
90
142
}
0 commit comments