1 ! Copyright (C) 2022 CapitalEx
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs compiler.units formatting
4 hash-sets hashtables io io.encodings.utf8 io.files
5 kernel namespaces regexp sequences sequences.deep sets sorting
6 splitting unicode vocabs vocabs.loader ;
7 FROM: namespaces => set ;
11 SYMBOL: old-dictionary
12 SYMBOL: LINT-VOCABS-REGEX
14 ! Cache regular expression to avoid compile time slowdowns
15 "CHAR:\\s+\\S+\\s+|\"(\\\\\\\\|\\\\[\\\\stnrbvf0e\"]|\\\\x[a-fA-F0-9]{2}|\\\\u[a-fA-F0-9]{6}|[^\\\\\"])*\"|R/ (\\\\/|[^/])*/|\\\\\\s+(USE:|USING:)|POSTPONE:\\s+(USE:|USING:)|(?<!\\S+)! [^\n]*" <regexp>
16 LINT-VOCABS-REGEX set-global
18 : save-dictionary ( -- )
22 : restore-dictionary ( -- )
23 dictionary get keys >hash-set
24 old-dictionary get keys >hash-set
25 diff members [ [ forget-vocab ] each ] with-compilation-unit ;
27 : vocab-loaded? ( name -- ? )
30 : (get-words) ( name -- vocab )
31 dup load-vocab words>> keys 2array ;
33 : no-vocab-found ( name -- empty )
36 : nl>space ( string -- string )
39 : find-import-statements ( string -- seq )
40 "USING: [^;]+ ;|USE: \\S+" <regexp> all-matching-subseqs ;
42 : clean-up-source ( string -- string )
43 LINT-VOCABS-REGEX get-global "" re-replace ;
45 : strip-syntax ( seq -- seq )
46 [ "USING: | ;|USE: " <regexp> " " re-replace ] map ;
48 : split-when-blank ( string -- seq )
49 [ blank? ] split-when ;
51 : split-words ( line -- words )
52 [ split-when-blank ] map flatten harvest ;
54 : get-unique-words ( seq -- hash-set )
55 harvest split-words >hash-set ;
57 : [is-used?] ( hash-set -- quot )
58 '[ nip [ _ in? ] any? ] ; inline
60 : reject-unused-vocabs ( assoc hash-set -- seq )
61 [is-used?] assoc-reject keys ;
63 : print-unused-vocabs ( name seq -- )
64 swap "The following vocabs are unused in %s: \n" printf
65 [ " - " prepend print ] each ;
67 : print-no-unused-vocabs ( name _ -- )
68 drop "No unused vocabs found in %s.\n" printf ;
72 : get-words ( name -- assoc )
75 [ no-vocab-found ] if ;
77 : get-vocabs ( string -- seq )
78 nl>space find-import-statements strip-syntax split-words harvest ;
80 : get-imported-words ( string -- hashtable )
82 get-vocabs [ get-words ] map >hashtable
86 : find-unused-in-string ( string -- seq )
88 [ get-imported-words ] [ "\n" split get-unique-words ] bi
89 reject-unused-vocabs natural-sort ; inline
91 : find-unused-in-file ( path -- seq )
92 utf8 file-contents find-unused-in-string ;
94 : find-unused ( name -- seq )
95 vocab-source-path dup [ find-unused-in-file ] when ;
97 : find-unused. ( name -- )
98 dup find-unused dup empty?
99 [ print-no-unused-vocabs ]
100 [ print-unused-vocabs ] if ;