v / cmd / tools / vwhere / finder.v
244 lines · 224 sloc · 6.04 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1module main
2
3import os
4import term { blue, bright_cyan, bright_green, bright_magenta, bright_red, bright_yellow, colorize }
5import regex
6import os.cmdline
7
8// Finder is entity that contains all the logic
9struct Finder {
10mut:
11 symbol Symbol
12 visib Visibility
13 mutab Mutability
14 name string
15 modul string
16 receiver string
17 dirs []string
18 matches []Match // all the results are collected here
19}
20
21fn (mut fdr Finder) configure_from_arguments(args []string) {
22 if args.len == 1 {
23 fdr.name = args[0]
24 return
25 }
26 fdr.symbol.set_from_str(args[0])
27 if fdr.symbol == .method && !args[1].contains('.') {
28 make_and_print_error('method require a special notation:', [
29 'Receiver.method',
30 ], '${args[1]}')
31 } else if fdr.symbol == .method {
32 temp_args := args[1].split('.')
33 fdr.receiver = temp_args[0]
34 fdr.name = temp_args[1]
35 } else {
36 fdr.name = args[1]
37 }
38 if fdr.name.contains('-') {
39 make_and_print_error('It seems you forgot positional arg name:', [], fdr.name)
40 }
41 fdr.visib.set_from_str(cmdline.option(args, '-vis', '${Visibility.all}'))
42 if fdr.symbol == .var && fdr.visib != .all {
43 make_and_print_error('-vis ${fdr.visib} just can be set with symbol_type:', [
44 'fn',
45 'method',
46 'const',
47 'struct',
48 'enum',
49 'interface',
50 'regexp',
51 ], '${fdr.symbol}')
52 }
53 fdr.mutab.set_from_str(cmdline.option(args, '-mut', '${Mutability.any}'))
54 if fdr.symbol != .var && fdr.mutab != .any {
55 make_and_print_error('-mut ${fdr.mutab} just can be set with symbol_type:', [
56 'var',
57 ], '${fdr.symbol}')
58 }
59 fdr.modul = cmdline.option(args, '-mod', '')
60 fdr.dirs = cmdline.options(args, '-dir')
61}
62
63fn (mut fdr Finder) search_for_matches() {
64 // Define where search
65 mut recursive := true
66 mut paths_to_search := []string{}
67 if fdr.dirs.len == 0 && fdr.modul == '' {
68 paths_to_search << [current_dir, vmod_dir]
69 if vlib_dir !in paths_to_search && paths_to_search.all(!vlib_dir.starts_with(it)) {
70 paths_to_search << vlib_dir
71 }
72 paths_to_search << vmod_paths
73 } else if fdr.dirs.len == 0 && fdr.modul != '' {
74 paths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {
75 panic(err)} }
76 } else if fdr.dirs.len != 0 && fdr.modul == '' {
77 paths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })
78 } else {
79 recursive = false
80 paths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {
81 panic(err)} }
82 paths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })
83 }
84
85 // dump(paths_to_search)
86 mut files_to_search := []string{}
87 for p in paths_to_search {
88 files_to_search << collect_v_files(p, recursive) or { panic(err) }
89 }
90 // dump(files_to_search)
91
92 // Auxiliary rgx
93 sp := r'\s*'
94 op := r'\('
95 cp := r'\)'
96
97 // Build regex query
98 sy := '${fdr.symbol}'
99 st := if fdr.receiver != '' {
100 '${sp}${op}${sp}[a-z].*${sp}${fdr.receiver}${cp}${sp}'
101 } else {
102 '.*'
103 }
104 na := '${fdr.name}'
105
106 query := match fdr.symbol {
107 .fn { '.*${sy}${sp}${na}${sp}${op}.*${cp}.*' }
108 .method { '.*fn${st}${na}${sp}${op}.*${cp}.*' }
109 .var { '.*${na}${sp}:=.*' }
110 .const { '.*${na}${sp} = .*' }
111 .regexp { '${na}' }
112 else { '.*${sy}${sp}${na}${sp}.*' } // struct, enum, interface
113 }
114
115 // dump(query)
116 for file in files_to_search {
117 fdr.search_within_file(file, query)
118 }
119}
120
121fn (mut fdr Finder) search_within_file(file string, query string) {
122 mut re := regex.regex_opt(query) or { panic(err) }
123 lines := os.read_lines(file) or { panic(err) }
124 mut const_found := if fdr.symbol == .const { false } else { true }
125 mut n_line := 1
126 for line in lines {
127 match fdr.visib {
128 .all {
129 if line.contains('const (') {
130 const_found = true
131 }
132 }
133 .pub {
134 if line.contains('pub const (') {
135 const_found = true
136 }
137 }
138 .pri {
139 if line.contains('const (') && !line.contains('pub') {
140 const_found = true
141 }
142 }
143 }
144
145 if re.matches_string(line) && (const_found || line.contains('const')) {
146 words := line.split(' ').filter(it != '').map(it.trim('\t'))
147 match fdr.visib {
148 .all {}
149 .pub {
150 if 'pub' !in words && fdr.symbol != .const {
151 continue
152 }
153 }
154 .pri {
155 if 'pub' in words && fdr.symbol != .const {
156 continue
157 }
158 }
159 }
160
161 match fdr.mutab {
162 .any {}
163 .yes {
164 if 'mut' !in words {
165 continue
166 }
167 }
168 .not {
169 if 'mut' in words {
170 continue
171 }
172 }
173 }
174
175 fdr.matches << Match{file, n_line, words.join(' ').trim(' {')}
176 }
177 if line.starts_with(')') && fdr.symbol == .const {
178 const_found = false
179 }
180 n_line++
181 }
182}
183
184fn (fdr Finder) show_results() {
185 if fdr.matches.len < 1 && (verbose || header) {
186 print(fdr)
187 println(colorize(bright_yellow, 'No Matches found'))
188 } else if verbose || header {
189 print(fdr)
190 println(colorize(bright_green, '${fdr.matches.len} matches Found\n'))
191 for result in fdr.matches {
192 result.show()
193 }
194 } else {
195 for result in fdr.matches {
196 result.show()
197 }
198 }
199}
200
201fn (fdr Finder) str() string {
202 v := colorize(bright_red, '${fdr.visib}')
203 m := colorize(bright_red, '${fdr.mutab}')
204 st := if fdr.receiver != '' { ' ( _ ${fdr.receiver})' } else { '' }
205 s := colorize(bright_magenta, '${fdr.symbol}')
206 n := colorize(bright_cyan, '${fdr.name}')
207
208 mm := if fdr.modul != '' { colorize(blue, '${fdr.modul}') } else { '' }
209 dd := if fdr.dirs.len != 0 {
210 fdr.dirs.map(colorize(blue, it))
211 } else {
212 fdr.dirs
213 }
214
215 dm := if fdr.dirs.len == 0 && fdr.modul == '' {
216 'all the project scope'
217 } else if fdr.dirs.len == 0 && fdr.modul != '' {
218 'module ${mm}'
219 } else if fdr.dirs.len != 0 && fdr.modul == '' {
220 'directories: ${dd}'
221 } else {
222 'module ${mm} searching within directories: ${dd}'
223 }
224
225 return '\nFind: ${s}${st} ${n} | visibility: ${v} mutability: ${m}\nwithin ${dm} '
226}
227
228// Match is one result of the search_for_matches() process
229struct Match {
230 path string @[required]
231 line int @[required]
232 text string @[required]
233}
234
235fn (mtc Match) show() {
236 path := colorize(bright_magenta, mtc.path)
237 line := colorize(bright_yellow, '${mtc.line}')
238 text := colorize(bright_green, '${mtc.text}')
239 if verbose || format {
240 println('${path}\n${line} : [ ${text} ]\n')
241 } else {
242 println('${path}:${line}: ${text}')
243 }
244}
245