update
[shellsnippets/shellsnippets.git] / mksh / testlink2javadoc.shar
1 # This is a shell archive.  Save it in a file, remove anything before
2 # this line, and then unpack it by entering "sh file".  Note, it may
3 # create directories; files and directories will be owned by you and
4 # have default permissions.
5 #
6 # This archive contains:
7 #
8 #       jdmerge.sh
9 #       munge.sh
10 #       testcheck.sh
11 #       tl2jd.sh
12 #
13 echo x - jdmerge.sh
14 sed 's/^X//' >jdmerge.sh << 'END-of-jdmerge.sh'
15 X#!/bin/mksh
16 X# -*- mode: sh -*-
17 X#-
18 X# Copyright © 2016
19 X#      mirabilos <t.glaser@tarent.de>
20 X#
21 X# Provided that these terms and disclaimer and all copyright notices
22 X# are retained or reproduced in an accompanying document, permission
23 X# is granted to deal in this work without restriction, including un‐
24 X# limited rights to use, publicly perform, distribute, sell, modify,
25 X# merge, give away, or sublicence.
26 X#
27 X# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
28 X# the utmost extent permitted by applicable law, neither express nor
29 X# implied; without malicious intent or gross negligence. In no event
30 X# may a licensor, author or contributor be held liable for indirect,
31 X# direct, other damage, loss, or other issues arising in any way out
32 X# of dealing in the work, even if advised of the possibility of such
33 X# damage or existence of a defect, except proven that it results out
34 X# of said person’s immediate fault when using the work as intended.
35 X
36 Xexport LC_ALL=C.UTF-8
37 X
38 Xlog() {
39 X       print -r -- "$*"
40 X       print -ru2 -- "I: $*"
41 X}
42 X
43 Xwarn() {
44 X       print -ru2 -- "W: $*"
45 X}
46 X
47 Xdie() {
48 X       print -ru2 -- "E: $*"
49 X       exit 1
50 X}
51 X
52 Xmode=$1
53 Xif [[ $mode != @(1|2|3) ]]; then
54 X       print -ru2 -- "N: mode 1 = check class names"
55 X       print -ru2 -- "N: mode 2 = check method names"
56 X       print -ru2 -- "N: mode 3 = apply changes (WARNING, writes to files)"
57 X       die "syntax error, usage: mksh jdmerge.sh <mode> [<target directory>]"
58 Xfi
59 X
60 X[[ -d testlink.out ]] || die input directory testlink.out not found
61 X
62 Xtargdir=$(realpath "${2:-.}")
63 Xwhile [[ ! -d $targdir/.git ]]; do
64 X       [[ $targdir = +(/) ]] && die target directory "${2:-$PWD}" not found
65 X       targdir=$(realpath "$targdir/..")
66 Xdone
67 Xset -A files
68 Xnfiles=0
69 X(cd "$targdir" && git ls-tree -r --name-only -z HEAD | grep -z '\.java$' | LC_ALL=C sort -z) |&
70 Xwhile IFS= read -prd '' fn; do
71 X       files[nfiles++]=$fn
72 Xdone
73 X
74 Xcd testlink.out
75 Xfor cls in *; do
76 X       [[ -d $cls ]] || die not a directory: "testlink.out/$cls"
77 X       for x in $cls/*; do
78 X               [[ -s $x ]] && continue
79 X               die empty or broken directory: "testlink.out/$cls"
80 X       done
81 Xdone
82 X
83 Xfunction method_check {
84 X       local found state i n=${#methods[*]} fn line
85 X       set -A found
86 X
87 X       for fn in "${classes[@]}"; do
88 X               state=0
89 X               while IFS= read -r line; do
90 X                       line=${line%%//*}
91 X                       line=${line##*([         ])}
92 X                       [[ -n $line ]] || continue
93 X                       case $state:$line {
94 X                       (0:'@Test'*)
95 X                               state=1
96 X                               ;;
97 X                       (1:'@'+([A-Za-z0-9_])*)
98 X                               ;;
99 X                       (1:'public void '+([A-Za-z0-9_])'()'?( *))
100 X                               state=0
101 X                               line=${line#public void }
102 X                               line=${line%%'('*}
103 X                               i=-1
104 X                               while (( ++i < n )); do
105 X                                       [[ ${methods[i]} = "$line" ]] || continue
106 X                                       found[i]=1
107 X                                       break
108 X                               done
109 X                               ;;
110 X                       }
111 X               done <"$targdir/$fn"
112 X       done
113 X
114 X       i=-1
115 X       while (( ++i < n )); do
116 X               [[ -n ${found[i]} ]] || log "no method $cls.${methods[i]}()"
117 X       done
118 X}
119 X
120 Xfunction method_patch {
121 X       local lns state i k l n=${#methods[*]} pfx fn line
122 X
123 X       for fn in "${classes[@]}"; do
124 X               tr '\n' $'\1' <"$targdir/$fn" |&
125 X               IFS=$'\1' read -ArpN-1 -d '' lns
126 X               l=${#lns[*]}
127 X               state=0
128 X               i=-1
129 X               while (( ++i < l )); do
130 X                       line=${lns[i]%%//*}
131 X                       line=${line##*([         ])}
132 X                       [[ -n $line ]] || continue
133 X                       case $state:$line {
134 X                       (0:'@Test'*)
135 X                               k=$i
136 X                               pfx=${lns[i]%%'@'*}
137 X                               state=1
138 X                               ;;
139 X                       (1:'@'+([A-Za-z0-9_])*)
140 X                               ;;
141 X                       (1:'public void '+([A-Za-z0-9_])'()'?( *))
142 X                               state=0
143 X                               line=${line#public void }
144 X                               line=${line%%'('*}
145 X                               if [[ -s $cls/$line ]]; then
146 X                                       log "patching $fn.$line()"
147 X                                       lns[k]=$(sed "s\ 1^\ 1$pfx\ 1" "$cls/$line")$'\n'${lns[k]}
148 X                               fi
149 X                               ;;
150 X                       }
151 X               done
152 X               i=-1
153 X               while (( ++i < l )); do
154 X                       print -r -- "${lns[i]}"
155 X               done >"$targdir/$fn"
156 X       done
157 X}
158 X
159 X# preliminary checks done
160 X
161 Xexec >../jdmerge.log
162 Xfor cls in *; do
163 X       set -A classes
164 X       nclasses=0
165 X       i=-1
166 X       while (( ++i < nfiles )); do
167 X               [[ ${files[i]} = */"$cls.java" ]] && classes[nclasses++]=${files[i]}
168 X       done
169 X       case $nclasses {
170 X       (0)
171 X               log "no classes for $cls, skipping"
172 X               continue
173 X               ;;
174 X       (1)
175 X               ;;
176 X       (*)
177 X               log "multiple ($nclasses) classes for $cls: ${classes[*]}"
178 X               ;;
179 X       }
180 X       [[ $mode = 1 ]] && continue
181 X
182 X       cd "$cls"
183 X       set -A methods -- *
184 X       cd ..
185 X       if [[ $mode = 2 ]]; then
186 X               method_check
187 X       else
188 X               method_patch
189 X       fi
190 Xdone
191 END-of-jdmerge.sh
192 echo x - munge.sh
193 sed 's/^X//' >munge.sh << 'END-of-munge.sh'
194 X#!/bin/mksh
195 X# -*- mode: sh -*-
196 X#-
197 X# Copyright © 2016
198 X#      mirabilos <t.glaser@tarent.de>
199 X#
200 X# Provided that these terms and disclaimer and all copyright notices
201 X# are retained or reproduced in an accompanying document, permission
202 X# is granted to deal in this work without restriction, including un‐
203 X# limited rights to use, publicly perform, distribute, sell, modify,
204 X# merge, give away, or sublicence.
205 X#
206 X# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
207 X# the utmost extent permitted by applicable law, neither express nor
208 X# implied; without malicious intent or gross negligence. In no event
209 X# may a licensor, author or contributor be held liable for indirect,
210 X# direct, other damage, loss, or other issues arising in any way out
211 X# of dealing in the work, even if advised of the possibility of such
212 X# damage or existence of a defect, except proven that it results out
213 X# of said person’s immediate fault when using the work as intended.
214 X
215 Xexport LC_ALL=C.UTF-8
216 X
217 Xdie() {
218 X       print -ru2 -- "E: $*"
219 X       exit 1
220 X}
221 X
222 Xcd "$(dirname "$0")"/testlink.out
223 Xset -A entries -- *
224 Xnentries=${#entries[*]}
225 Xfor ent in "${entries[@]}"; do
226 X       cd "$ent"
227 X       eval "set -A sub_$ent -- *"
228 X       cd ..
229 Xdone
230 Xset -A cmds
231 Xncmds=0
232 X
233 Xfindent() {
234 X       local -i i=-1
235 X
236 X       while (( ++i < nentries )); do
237 X               [[ ${entries[i]} = "$1" ]] || continue
238 X               print -r -- "$i"
239 X               return 0
240 X       done
241 X       return 1
242 X}
243 X
244 Xfindsub() {
245 X       nameref s=sub_$2
246 X       local -i i=-1 n=${#s[*]}
247 X
248 X       while (( ++i < n )); do
249 X               [[ ${s[i]} = "$1" ]] || continue
250 X               print -r -- "$i"
251 X               return 0
252 X       done
253 X       return 1
254 X}
255 X
256 Xdrop() {
257 X       local ent
258 X
259 X       ent=$(findent "$1") || return 0
260 X       unset entries[ent]
261 X       eval "unset sub_$1"
262 X       set -A entries -- "${entries[@]}"
263 X       nentries=${#entries[*]}
264 X       cmds[ncmds++]="rm -rf ${1@Q}"
265 X}
266 X
267 Xdsub() {
268 X       local ent c=$2 m=$1
269 X
270 X       if [[ -z $c ]]; then
271 X               c=${m%.*}
272 X               m=${m#*.}
273 X       fi
274 X
275 X       ent=$(findent "$c") || return 0
276 X       ent=$(findsub "$m" "$c") || return 0
277 X       eval "unset sub_$c[ent]"
278 X       eval "set -A sub_$c -- \"\${sub_$c[@]}\""
279 X       cmds[ncmds++]="rm -f ${c@Q}/${m@Q}"
280 X}
281 X
282 Xmove() {
283 X       local src dst
284 X
285 X       src=$(findent "$1") || return 0
286 X       dst=$(findent "$2") && die "move ${1@Q} ${2@Q}: target already exists"
287 X       entries[src]=$2
288 X       eval "set -A -- sub_$2 -- \"\${sub_$1[@]}\""
289 X       eval "unset sub_$1"
290 X       cmds[ncmds++]="mv -f ${1@Q} ${2@Q}"
291 X}
292 X
293 Xmsub() {
294 X       local src dst
295 X
296 X       src=$(findent "$2") || return 0
297 X       src=$(findsub "$1" "$2") || return 0
298 X       dst=$(findent "$4") || die "moving to new subdir not implemented yet"
299 X       dst=$(findsub "$3" "$4") && die "msub ${1@Q} ${2@Q} ${3@Q} ${4@Q}: target already exists"
300 X       eval "unset sub_$2[src]"
301 X       eval "set -A sub_$2 -- \"\${sub_$2[@]}\""
302 X       eval "set -A sub_$4 -- \"\${sub_$4[@]}\" \"\$3\""
303 X       cmds[ncmds++]="mv -f ${2@Q}/${1@Q} ${4@Q}/${3@Q}"
304 X}
305 X
306 Xdoit() {
307 X       local i=-1
308 X
309 X       while (( ++i < ncmds )); do
310 X               print -r -- "+ ${cmds[i]}"
311 X               eval "${cmds[i]}"
312 X       done
313 X}
314 X
315 X# insert here commands to munge the descriptions
316 Xmove OldTestClassName NewTestClassName
317 Xdrop RemovedTestClassName
318 Xdsub TestClassName.removedTestMethodName
319 Xmsub oldTestMethodName OldTestClassName newTestMethodName NewTestClassName
320 X
321 Xdoit
322 END-of-munge.sh
323 echo x - testcheck.sh
324 sed 's/^X//' >testcheck.sh << 'END-of-testcheck.sh'
325 X#!/bin/mksh
326 X# -*- mode: sh -*-
327 X#-
328 X# Copyright © 2016
329 X#      mirabilos <t.glaser@tarent.de>
330 X#
331 X# Provided that these terms and disclaimer and all copyright notices
332 X# are retained or reproduced in an accompanying document, permission
333 X# is granted to deal in this work without restriction, including un‐
334 X# limited rights to use, publicly perform, distribute, sell, modify,
335 X# merge, give away, or sublicence.
336 X#
337 X# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
338 X# the utmost extent permitted by applicable law, neither express nor
339 X# implied; without malicious intent or gross negligence. In no event
340 X# may a licensor, author or contributor be held liable for indirect,
341 X# direct, other damage, loss, or other issues arising in any way out
342 X# of dealing in the work, even if advised of the possibility of such
343 X# damage or existence of a defect, except proven that it results out
344 X# of said person’s immediate fault when using the work as intended.
345 X
346 Xexport LC_ALL=C.UTF-8
347 X
348 Xdie() {
349 X       print -ru2 -- "E: $*"
350 X       exit 1
351 X}
352 X
353 Xclr() {
354 X       local -R$((COLUMNS - 1)) x=''
355 X
356 X       print -n "\r$x\r"
357 X}
358 X
359 Xtargdir=$(realpath "${1:-.}")
360 Xwhile [[ ! -d $targdir/.git ]]; do
361 X       [[ $targdir = +(/) ]] && die target directory "${1:-$PWD}" not found
362 X       targdir=$(realpath "$targdir/..")
363 Xdone
364 Xcd "$targdir"
365 Xgit grep -F -z -l '@Test' |&
366 Xwhile IFS= read -prd '' fn; do
367 X       [[ $fn = *.java ]] || continue
368 X       clr
369 X       print -nr -- "Checking $fn ...\r"
370 X       state=0
371 X       while IFS= read -r line; do
372 X               line=${line%%//*}
373 X               line=${line##*([         ])}
374 X               [[ -n $line ]] || continue
375 X               case $state:$line {
376 X               (0:'@Test'?('('*([!\)])')'))
377 X                       state=1
378 X                       ;;
379 X               (0:*'@Test'*)
380 X                       print -r -- "Error found in $fn"
381 X                       die "WTF? 0 $line"
382 X                       ;;
383 X               (0:'@'+([A-Za-z0-9_])?('('*([!\)])')'))
384 X                       state=2
385 X                       ;;
386 X               (1:'@'+([A-Za-z0-9_])?('('*([!\)])')'))
387 X                       ;;
388 X               (1:'public void '+([A-Za-z0-9_])'()'?( *))
389 X                       state=0
390 X                       ;;
391 X               (1:*)
392 X                       print -r -- "Error found in $fn"
393 X                       die "WTF? 1 $line"
394 X                       ;;
395 X               (2:*'@Test'*)
396 X                       print -r -- "Error found in $fn"
397 X                       die "@Test is not the first annotation"
398 X                       ;;
399 X               (2:'@'+([A-Za-z0-9_])?('('*([!\)])')'))
400 X                       ;;
401 X               (2:*)
402 X                       state=0
403 X                       ;;
404 X               }
405 X       done <"$fn"
406 X       if [[ $state != 0 ]]; then
407 X               print -r -- "Error found in $fn"
408 X               die "State $state at EOF"
409 X       fi
410 Xdone
411 Xclr
412 Xprint All files checked successfully.
413 END-of-testcheck.sh
414 echo x - tl2jd.sh
415 sed 's/^X//' >tl2jd.sh << 'END-of-tl2jd.sh'
416 X#!/bin/mksh
417 X# -*- mode: sh -*-
418 X#-
419 X# Copyright © 2016
420 X#      mirabilos <t.glaser@tarent.de>
421 X# Copyright © 2015
422 X#      mirabilos <thorsten.glaser@teckids.org>
423 X# Copyright © 2007, 2008, 2012, 2013, 2014
424 X#      mirabilos <m@mirbsd.org>
425 X#
426 X# Provided that these terms and disclaimer and all copyright notices
427 X# are retained or reproduced in an accompanying document, permission
428 X# is granted to deal in this work without restriction, including un‐
429 X# limited rights to use, publicly perform, distribute, sell, modify,
430 X# merge, give away, or sublicence.
431 X#
432 X# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
433 X# the utmost extent permitted by applicable law, neither express nor
434 X# implied; without malicious intent or gross negligence. In no event
435 X# may a licensor, author or contributor be held liable for indirect,
436 X# direct, other damage, loss, or other issues arising in any way out
437 X# of dealing in the work, even if advised of the possibility of such
438 X# damage or existence of a defect, except proven that it results out
439 X# of said person’s immediate fault when using the work as intended.
440 X
441 Xexport LC_ALL=C.UTF-8
442 X
443 Xwarn() {
444 X       print -ru2 -- "W: $*"
445 X}
446 X
447 Xdie() {
448 X       print -ru2 -- "E: $*"
449 X       exit 1
450 X}
451 X
452 X[[ -s testlink.html ]] || die input file testlink.html not found
453 X[[ -e testlink.out || -h testlink.out ]] && die output directory testlink.out already exists
454 Xmkdir testlink.out || die cannot create output directory testlink.out
455 X
456 X<testlink.html \
457 X    tidy -q -asxhtml -w 0 -utf8 --quote-nbsp no 2>/dev/null | \
458 X    sed -e 's! xmlns="http://www.w3.org/1999/xhtml"!!' -e 's/ / /g' | \
459 X    xmlstarlet sel -B -T -t -m '//table[@class="tc"]/tbody' -o $'\2' \
460 X    -v 'tr/td[.="Java Class:"]/following-sibling::td' -o $'\1' \
461 X    -v 'tr[1]/th' -o $'\1' \
462 X    -v 'tr/td[.="Refenz:"]/following-sibling::td' -o $'\1' \
463 X    -m 'tr/td/table/tbody' \
464 X    -v 'tr/td[contains(.,"Beschreibung")]/following-sibling::td' -o $'\1' \
465 X    -v 'tr/td[contains(.,"Getestete Funktion")]/following-sibling::td' -o $'\1' \
466 X    -v 'tr/td[contains(.,"Vorbedingung")]/following-sibling::td' -o $'\1' \
467 X    -v 'tr/td[contains(.,"Nachbedingung")]/following-sibling::td' -o $'\1' \
468 X    -t -o $'\2' \
469 X    | tr $'\t\n\2' $' \3\n' \
470 X    | sed -e 1d -e $'s! *\1 *!\1!g' -e 's!&!\&amp;!g' -e 's!<!\&lt;!g' -e 's!>!\&gt;!g' -e $'s!\3!<br />!g' \
471 X    | tee testlink.log \
472 X    | while IFS=$'\1' read -r jp tf ref bes fn vb nb rest; do
473 X       [[ -n $rest ]] && warn "ignoring nonzero rest in record ||$jp|$tf|$ref|$bes|$fn|$vb|$nb||$rest||"
474 X       if [[ $jp != +([A-Za-z0-9_]).+([A-Za-z0-9_])'()' ]]; then
475 X               warn "skipping line, invalid java class name: $jp"
476 X               continue
477 X       fi
478 X       jp=${jp%'()'}
479 X       jc=${jp%.*}
480 X       jm=${jp#*.}
481 X       mkdir -p testlink.out/$jc
482 X       [[ -e testlink.out/$jc/$jm ]] && warn "multiple entries for $jp()"
483 X       exec >>testlink.out/$jc/$jm
484 X       print -r -- "/**"
485 X       print -r -- " * $tf"
486 X       [[ -n $bes$fn$vb$nb ]] && print -r -- " * <ul>"
487 X       [[ -n $bes ]] && print -r -- " * <li><b>Beschreibung:</b> $bes</li>"
488 X       [[ -n $fn ]] && print -r -- " * <li><b>Getestete Funktion:</b> $fn</li>"
489 X       [[ -n $vb ]] && print -r -- " * <li><b>Vorbedingung:</b> $vb</li>"
490 X       [[ -n $nb ]] && print -r -- " * <li><b>Nachbedingung:</b> $nb</li>"
491 X       [[ -n $bes$fn$vb$nb ]] && print -r -- " * </ul>"
492 X       [[ -n $ref ]] && print -r -- " * <b>Referenz:</b> $ref"
493 X       print -r -- " */"
494 X       exec >/dev/null
495 Xdone
496 END-of-tl2jd.sh
497 exit