tools: check formatting of more modules with `v test-cleancode`, colorize `v vet` output
parent
9e48826bcb
commit
9b78d7d21d
|
@ -77,22 +77,9 @@ fn main() {
|
||||||
eprintln('vfmt env_vflags_and_os_args: ' + args.str())
|
eprintln('vfmt env_vflags_and_os_args: ' + args.str())
|
||||||
eprintln('vfmt possible_files: ' + possible_files.str())
|
eprintln('vfmt possible_files: ' + possible_files.str())
|
||||||
}
|
}
|
||||||
mut files := []string{}
|
files := util.find_all_v_files(possible_files) or {
|
||||||
for file in possible_files {
|
verror(err.msg)
|
||||||
if os.is_dir(file) {
|
return
|
||||||
files << os.walk_ext(file, '.v')
|
|
||||||
files << os.walk_ext(file, '.vsh')
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !file.ends_with('.v') && !file.ends_with('.vv') && !file.ends_with('.vsh') {
|
|
||||||
verror('v fmt can only be used on .v files.\nOffending file: "$file"')
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !os.exists(file) {
|
|
||||||
verror('"$file" does not exist')
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
files << file
|
|
||||||
}
|
}
|
||||||
if is_atty(0) == 0 && files.len == 0 {
|
if is_atty(0) == 0 && files.len == 0 {
|
||||||
foptions.format_pipe()
|
foptions.format_pipe()
|
||||||
|
|
|
@ -16,7 +16,11 @@ const (
|
||||||
'examples/tetris',
|
'examples/tetris',
|
||||||
'examples/term.ui',
|
'examples/term.ui',
|
||||||
]
|
]
|
||||||
verify_known_failing_exceptions = []string{}
|
verify_known_failing_exceptions = [
|
||||||
|
'vlib/gg/m4/graphic.v' /* has hand crafted meaningful formatting of matrices */,
|
||||||
|
'vlib/gg/m4/m4_test.v' /* has hand crafted meaningful formatting of matrices */,
|
||||||
|
'vlib/gg/m4/matrix.v' /* has hand crafted meaningful formatting of matrices */,
|
||||||
|
]
|
||||||
vfmt_verify_list = [
|
vfmt_verify_list = [
|
||||||
'cmd/v/v.v',
|
'cmd/v/v.v',
|
||||||
'cmd/tools/vdoc/',
|
'cmd/tools/vdoc/',
|
||||||
|
@ -30,8 +34,13 @@ const (
|
||||||
'vlib/builtin/map.v',
|
'vlib/builtin/map.v',
|
||||||
'vlib/builtin/int.v',
|
'vlib/builtin/int.v',
|
||||||
'vlib/builtin/option.v',
|
'vlib/builtin/option.v',
|
||||||
|
'vlib/cli/',
|
||||||
|
'vlib/dl/',
|
||||||
|
'vlib/flag/',
|
||||||
|
'vlib/gg/',
|
||||||
'vlib/math/bits/bits.v',
|
'vlib/math/bits/bits.v',
|
||||||
'vlib/orm/',
|
'vlib/orm/',
|
||||||
|
'vlib/runtime/',
|
||||||
'vlib/term/colors.v',
|
'vlib/term/colors.v',
|
||||||
'vlib/term/term.v',
|
'vlib/term/term.v',
|
||||||
'vlib/v/ast/',
|
'vlib/v/ast/',
|
||||||
|
@ -88,7 +97,8 @@ fn main() {
|
||||||
|
|
||||||
fn tsession(vargs string, tool_source string, tool_cmd string, tool_args string, flist []string, slist []string) testing.TestSession {
|
fn tsession(vargs string, tool_source string, tool_cmd string, tool_args string, flist []string, slist []string) testing.TestSession {
|
||||||
os.chdir(vroot)
|
os.chdir(vroot)
|
||||||
testing.eheader('Run `$tool_cmd` over most .v files')
|
title_message := 'running $tool_cmd over most .v files'
|
||||||
|
testing.eheader(title_message)
|
||||||
mut test_session := testing.new_test_session('$vargs $tool_args')
|
mut test_session := testing.new_test_session('$vargs $tool_args')
|
||||||
test_session.files << flist
|
test_session.files << flist
|
||||||
test_session.skip_files << slist
|
test_session.skip_files << slist
|
||||||
|
@ -97,14 +107,16 @@ fn tsession(vargs string, tool_source string, tool_cmd string, tool_args string,
|
||||||
// in the VTMP from the test session too, so they will be cleaned up
|
// in the VTMP from the test session too, so they will be cleaned up
|
||||||
// at the end
|
// at the end
|
||||||
test_session.test()
|
test_session.test()
|
||||||
eprintln(test_session.benchmark.total_message('running `$tool_cmd` over most .v files'))
|
eprintln(test_session.benchmark.total_message(title_message))
|
||||||
return test_session
|
return test_session
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v_test_vetting(vargs string) {
|
fn v_test_vetting(vargs string) {
|
||||||
vet_session := tsession(vargs, 'vvet', 'v vet', 'vet', vet_folders, vet_known_failing_exceptions)
|
vet_session := tsession(vargs, 'vvet', 'v vet', 'vet', vet_folders, vet_known_failing_exceptions)
|
||||||
fmt_cmd, fmt_args := if is_fix { 'v fmt -w', 'fmt -w' } else { 'v fmt -verify', 'fmt -verify' }
|
fmt_cmd, fmt_args := if is_fix { 'v fmt -w', 'fmt -w' } else { 'v fmt -verify', 'fmt -verify' }
|
||||||
verify_session := tsession(vargs, 'vfmt.v', fmt_cmd, fmt_args, vfmt_verify_list, verify_known_failing_exceptions)
|
expanded_vfmt_list := util.find_all_v_files(vfmt_verify_list) or { return }
|
||||||
|
verify_session := tsession(vargs, 'vfmt.v', fmt_cmd, fmt_args, expanded_vfmt_list,
|
||||||
|
verify_known_failing_exceptions)
|
||||||
//
|
//
|
||||||
if vet_session.benchmark.nfail > 0 || verify_session.benchmark.nfail > 0 {
|
if vet_session.benchmark.nfail > 0 || verify_session.benchmark.nfail > 0 {
|
||||||
eprintln('\n')
|
eprintln('\n')
|
||||||
|
|
|
@ -9,6 +9,7 @@ import v.pref
|
||||||
import v.parser
|
import v.parser
|
||||||
import v.table
|
import v.table
|
||||||
import v.token
|
import v.token
|
||||||
|
import term
|
||||||
|
|
||||||
struct Vet {
|
struct Vet {
|
||||||
opt Options
|
opt Options
|
||||||
|
@ -19,6 +20,7 @@ mut:
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
is_verbose bool
|
is_verbose bool
|
||||||
|
use_color bool
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (vet &Vet) vprintln(s string) {
|
fn (vet &Vet) vprintln(s string) {
|
||||||
|
@ -38,9 +40,23 @@ const is_verbose = '-verbose' in vet_options || '-v' in vet_options
|
||||||
|
|
||||||
const show_warnings = '-hide-warnings' !in vet_options
|
const show_warnings = '-hide-warnings' !in vet_options
|
||||||
|
|
||||||
|
const use_color = should_use_color()
|
||||||
|
|
||||||
|
fn should_use_color() bool {
|
||||||
|
mut color := term.can_show_color_on_stderr()
|
||||||
|
if '-nocolor' in vet_options {
|
||||||
|
color = false
|
||||||
|
}
|
||||||
|
if '-color' in vet_options {
|
||||||
|
color = true
|
||||||
|
}
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
opt := Options{
|
mut opt := Options{
|
||||||
is_verbose: is_verbose
|
is_verbose: is_verbose
|
||||||
|
use_color: use_color
|
||||||
}
|
}
|
||||||
mut vet := Vet{
|
mut vet := Vet{
|
||||||
opt: opt
|
opt: opt
|
||||||
|
@ -97,11 +113,11 @@ fn main() {
|
||||||
errors_vfmt := vet.errors.filter(it.kind == .error && it.fix == .vfmt)
|
errors_vfmt := vet.errors.filter(it.kind == .error && it.fix == .vfmt)
|
||||||
if show_warnings {
|
if show_warnings {
|
||||||
for err in warnings {
|
for err in warnings {
|
||||||
eprintln('$err.file_path:$err.pos.line_nr: warning: $err.message')
|
eprintln(e2string(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for err in errors {
|
for err in errors {
|
||||||
eprintln('$err.file_path:$err.pos.line_nr: error: $err.message')
|
eprintln(e2string(err))
|
||||||
}
|
}
|
||||||
if errors_vfmt.len > 0 {
|
if errors_vfmt.len > 0 {
|
||||||
eprintln('NB: You can run `v fmt -w file.v` to fix these automatically')
|
eprintln('NB: You can run `v fmt -w file.v` to fix these automatically')
|
||||||
|
@ -111,6 +127,20 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn e2string(err vet.Error) string {
|
||||||
|
mut kind := '$err.kind:'
|
||||||
|
mut location := '$err.file_path:$err.pos.line_nr:'
|
||||||
|
if use_color {
|
||||||
|
kind = match err.kind {
|
||||||
|
.warning { term.magenta(kind) }
|
||||||
|
.error { term.red(kind) }
|
||||||
|
}
|
||||||
|
kind = term.bold(kind)
|
||||||
|
location = term.bold(location)
|
||||||
|
}
|
||||||
|
return '$location $kind $err.message'
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut v Vet) error(msg string, line int, fix vet.FixKind) {
|
fn (mut v Vet) error(msg string, line int, fix vet.FixKind) {
|
||||||
pos := token.Position{
|
pos := token.Position{
|
||||||
line_nr: line + 1
|
line_nr: line + 1
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module gg
|
module gg
|
||||||
|
|
||||||
#include "@VROOT/vlib/gg/gg_darwin.m"
|
#include "@VROOT/vlib/gg/gg_darwin.m"
|
||||||
|
|
||||||
fn C.gg_get_screen_size() Size
|
fn C.gg_get_screen_size() Size
|
||||||
|
|
||||||
fn C.darwin_draw_string(x int, y int, s string, cfg voidptr)
|
fn C.darwin_draw_string(x int, y int, s string, cfg voidptr)
|
||||||
|
|
|
@ -28,7 +28,9 @@ pub fn (x Vec4) str() string {
|
||||||
|
|
||||||
// create a Vec4 function passing x,y,z as parameteres. w is set to 1
|
// create a Vec4 function passing x,y,z as parameteres. w is set to 1
|
||||||
pub fn vec3(x f32, y f32, z f32) Vec4 {
|
pub fn vec3(x f32, y f32, z f32) Vec4 {
|
||||||
return m4.Vec4{e:[x, y, z, 1]!}
|
return Vec4{
|
||||||
|
e: [x, y, z, 1]!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all the raw zeros
|
// Remove all the raw zeros
|
||||||
|
@ -47,12 +49,14 @@ pub fn (a Vec4) clean() Vec4 {
|
||||||
|
|
||||||
// Set all elements to value
|
// Set all elements to value
|
||||||
pub fn (mut x Vec4) copy(value f32) {
|
pub fn (mut x Vec4) copy(value f32) {
|
||||||
x.e = [ value, value, value, value, ]!
|
x.e = [value, value, value, value]!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale the vector using a scalar
|
// Scale the vector using a scalar
|
||||||
pub fn (x Vec4) mul_scalar(value f32) Vec4 {
|
pub fn (x Vec4) mul_scalar(value f32) Vec4 {
|
||||||
return Vec4{ e: [ x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value, ]! }
|
return Vec4{
|
||||||
|
e: [x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value]!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reciprocal of the vector
|
// Reciprocal of the vector
|
||||||
|
|
|
@ -261,7 +261,9 @@ pub fn system_font_path() string {
|
||||||
mut fonts := ['Ubuntu-R.ttf', 'Arial.ttf', 'LiberationSans-Regular.ttf', 'NotoSans-Regular.ttf',
|
mut fonts := ['Ubuntu-R.ttf', 'Arial.ttf', 'LiberationSans-Regular.ttf', 'NotoSans-Regular.ttf',
|
||||||
'FreeSans.ttf', 'DejaVuSans.ttf']
|
'FreeSans.ttf', 'DejaVuSans.ttf']
|
||||||
$if macos {
|
$if macos {
|
||||||
fonts = ['/System/Library/Fonts/SFNS.ttf', '/System/Library/Fonts/SFNSText.ttf', '/Library/Fonts/Arial.ttf']
|
fonts = ['/System/Library/Fonts/SFNS.ttf', '/System/Library/Fonts/SFNSText.ttf',
|
||||||
|
'/Library/Fonts/Arial.ttf',
|
||||||
|
]
|
||||||
for font in fonts {
|
for font in fonts {
|
||||||
if os.is_file(font) {
|
if os.is_file(font) {
|
||||||
return font
|
return font
|
||||||
|
@ -269,8 +271,10 @@ pub fn system_font_path() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$if android {
|
$if android {
|
||||||
xml_files := ['/system/etc/system_fonts.xml', '/system/etc/fonts.xml', '/etc/system_fonts.xml',
|
xml_files := ['/system/etc/system_fonts.xml', '/system/etc/fonts.xml',
|
||||||
'/etc/fonts.xml', '/data/fonts/fonts.xml', '/etc/fallback_fonts.xml']
|
'/etc/system_fonts.xml', '/etc/fonts.xml', '/data/fonts/fonts.xml',
|
||||||
|
'/etc/fallback_fonts.xml',
|
||||||
|
]
|
||||||
font_locations := ['/system/fonts', '/data/fonts']
|
font_locations := ['/system/fonts', '/data/fonts']
|
||||||
for xml_file in xml_files {
|
for xml_file in xml_files {
|
||||||
if os.is_file(xml_file) && os.is_readable(xml_file) {
|
if os.is_file(xml_file) && os.is_readable(xml_file) {
|
||||||
|
|
|
@ -35,18 +35,16 @@ pub fn read_all(config ReadAllConfig) ?[]byte {
|
||||||
r := config.reader
|
r := config.reader
|
||||||
read_till_eof := config.read_to_end_of_stream
|
read_till_eof := config.read_to_end_of_stream
|
||||||
|
|
||||||
mut b := []byte{len: read_all_len}
|
mut b := []byte{len: io.read_all_len}
|
||||||
mut read := 0
|
mut read := 0
|
||||||
for {
|
for {
|
||||||
new_read := r.read(mut b[read..]) or {
|
new_read := r.read(mut b[read..]) or { break }
|
||||||
break
|
|
||||||
}
|
|
||||||
read += new_read
|
read += new_read
|
||||||
if !read_till_eof && read == 0 {
|
if !read_till_eof && read == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if b.len == read {
|
if b.len == read {
|
||||||
unsafe { b.grow_len(read_all_grow_len) }
|
unsafe { b.grow_len(io.read_all_grow_len) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b[..read]
|
return b[..read]
|
||||||
|
@ -55,18 +53,16 @@ pub fn read_all(config ReadAllConfig) ?[]byte {
|
||||||
// read_any reads any available bytes from a reader
|
// read_any reads any available bytes from a reader
|
||||||
// (until the reader returns a read of 0 length)
|
// (until the reader returns a read of 0 length)
|
||||||
pub fn read_any(r Reader) ?[]byte {
|
pub fn read_any(r Reader) ?[]byte {
|
||||||
mut b := []byte{len: read_all_len}
|
mut b := []byte{len: io.read_all_len}
|
||||||
mut read := 0
|
mut read := 0
|
||||||
for {
|
for {
|
||||||
new_read := r.read(mut b[read..]) or {
|
new_read := r.read(mut b[read..]) or { break }
|
||||||
break
|
|
||||||
}
|
|
||||||
read += new_read
|
read += new_read
|
||||||
if new_read == 0 {
|
if new_read == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if b.len == read {
|
if b.len == read {
|
||||||
unsafe { b.grow_len(read_all_grow_len) }
|
unsafe { b.grow_len(io.read_all_grow_len) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b[..read]
|
return b[..read]
|
||||||
|
|
|
@ -58,17 +58,15 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_stringreader() {
|
fn test_stringreader() {
|
||||||
text := '12345\n'.repeat(newline_count)
|
text := '12345\n'.repeat(io.newline_count)
|
||||||
mut s := StringReader{
|
mut s := StringReader{
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
mut r := new_buffered_reader({
|
mut r := new_buffered_reader(reader: make_reader(s))
|
||||||
reader: make_reader(s)
|
|
||||||
})
|
|
||||||
for i := 0; true; i++ {
|
for i := 0; true; i++ {
|
||||||
if _ := r.read_line() {
|
if _ := r.read_line() {
|
||||||
} else {
|
} else {
|
||||||
assert i == newline_count
|
assert i == io.newline_count
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,24 +83,22 @@ fn test_stringreader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_stringreader2() {
|
fn test_stringreader2() {
|
||||||
text := '12345\r\n'.repeat(newline_count)
|
text := '12345\r\n'.repeat(io.newline_count)
|
||||||
mut s := StringReader{
|
mut s := StringReader{
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
mut r := new_buffered_reader({
|
mut r := new_buffered_reader(reader: make_reader(s))
|
||||||
reader: make_reader(s)
|
|
||||||
})
|
|
||||||
for i := 0; true; i++ {
|
for i := 0; true; i++ {
|
||||||
if _ := r.read_line() {
|
if _ := r.read_line() {
|
||||||
} else {
|
} else {
|
||||||
assert i == newline_count
|
assert i == io.newline_count
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _ := r.read_line() {
|
if _ := r.read_line() {
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
leftover := read_all(reader: io.make_reader(r)) or {
|
leftover := read_all(reader: make_reader(r)) or {
|
||||||
assert false
|
assert false
|
||||||
panic('bad')
|
panic('bad')
|
||||||
}
|
}
|
||||||
|
@ -116,9 +112,7 @@ fn test_leftover() {
|
||||||
mut s := StringReader{
|
mut s := StringReader{
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
mut r := new_buffered_reader({
|
mut r := new_buffered_reader(reader: make_reader(s))
|
||||||
reader: make_reader(s)
|
|
||||||
})
|
|
||||||
_ := r.read_line() or {
|
_ := r.read_line() or {
|
||||||
assert false
|
assert false
|
||||||
panic('bad')
|
panic('bad')
|
||||||
|
|
|
@ -6,8 +6,10 @@ module runtime
|
||||||
|
|
||||||
//$if linux {
|
//$if linux {
|
||||||
fn C.sysconf(name int) i64
|
fn C.sysconf(name int) i64
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//$if windows {
|
//$if windows {
|
||||||
fn C.GetCurrentProcessorNumber() u32
|
fn C.GetCurrentProcessorNumber() u32
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -22,24 +22,32 @@ pub fn nr_jobs() int {
|
||||||
|
|
||||||
// is_32bit returns true if the current executable is running on a 32 bit system.
|
// is_32bit returns true if the current executable is running on a 32 bit system.
|
||||||
pub fn is_32bit() bool {
|
pub fn is_32bit() bool {
|
||||||
$if x32 { return true }
|
$if x32 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_64bit returns true if the current executable is running on a 64 bit system.
|
// is_64bit returns true if the current executable is running on a 64 bit system.
|
||||||
pub fn is_64bit() bool {
|
pub fn is_64bit() bool {
|
||||||
$if x64 { return true }
|
$if x64 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_little_endian returns true if the current executable is running on a little-endian system.
|
// is_little_endian returns true if the current executable is running on a little-endian system.
|
||||||
pub fn is_little_endian() bool {
|
pub fn is_little_endian() bool {
|
||||||
$if little_endian { return true }
|
$if little_endian {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_big_endian returns true if the current executable is running on a big-endian system.
|
// is_big_endian returns true if the current executable is running on a big-endian system.
|
||||||
pub fn is_big_endian() bool {
|
pub fn is_big_endian() bool {
|
||||||
$if big_endian { return true }
|
$if big_endian {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import os
|
||||||
struct C.SYSTEM_INFO {
|
struct C.SYSTEM_INFO {
|
||||||
dwNumberOfProcessors u32
|
dwNumberOfProcessors u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C.GetSystemInfo(&C.SYSTEM_INFO)
|
fn C.GetSystemInfo(&C.SYSTEM_INFO)
|
||||||
|
|
||||||
// nr_cpus returns the number of virtual CPU cores found on the system.
|
// nr_cpus returns the number of virtual CPU cores found on the system.
|
||||||
|
|
|
@ -556,3 +556,25 @@ pub fn should_bundle_module(mod string) bool {
|
||||||
return mod in util.bundle_modules
|
return mod in util.bundle_modules
|
||||||
|| (mod.contains('.') && mod.all_before('.') in util.bundle_modules)
|
|| (mod.contains('.') && mod.all_before('.') in util.bundle_modules)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find_all_v_files - given a list of files/folders, finds all .v/.vsh files
|
||||||
|
// if some of the files/folders on the list does not exist, or a file is not
|
||||||
|
// a .v or .vsh file, returns an error instead.
|
||||||
|
pub fn find_all_v_files(roots []string) ?[]string {
|
||||||
|
mut files := []string{}
|
||||||
|
for file in roots {
|
||||||
|
if os.is_dir(file) {
|
||||||
|
files << os.walk_ext(file, '.v')
|
||||||
|
files << os.walk_ext(file, '.vsh')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !file.ends_with('.v') && !file.ends_with('.vv') && !file.ends_with('.vsh') {
|
||||||
|
return error('v fmt can only be used on .v files.\nOffending file: "$file"')
|
||||||
|
}
|
||||||
|
if !os.exists(file) {
|
||||||
|
return error('"$file" does not exist')
|
||||||
|
}
|
||||||
|
files << file
|
||||||
|
}
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue