builtin,vdoc: fix the examples for the builtin methods, so that v doc -check-examples -time -f ansi vlib/builtin/ pass

This commit is contained in:
Delyan Angelov 2025-08-13 16:22:22 +03:00
parent 89c470bbba
commit 82cd81e963
No known key found for this signature in database
GPG key ID: 66886C0F12D595ED
6 changed files with 41 additions and 38 deletions

View file

@ -16,6 +16,7 @@ fn (mut vd VDoc) process_all_examples(contents []doc.DocNode) {
} }
const normalised_default_vmodules_path = os.vmodules_dir().replace('\\', '/') const normalised_default_vmodules_path = os.vmodules_dir().replace('\\', '/')
const vdoc_max_fails = os.getenv_opt('VDOC_MAX_FAILS') or { '999' }.int()
fn get_mod_name_by_file_path(file_path string) string { fn get_mod_name_by_file_path(file_path string) string {
mut mcache := vmod.get_cache() mut mcache := vmod.get_cache()
@ -51,9 +52,11 @@ fn (mut vd VDoc) run_examples(dn doc.DocNode) {
os.rm(sfile) or {} os.rm(sfile) or {}
} }
} }
mut failures := 0
mut oks := 0
for example in examples { for example in examples {
if vd.example_failures >= vdoc_max_fails {
eprintln('> vdoc: too many examples failed in ${vd.cfg.run_examples} mode')
exit(1)
}
code := example.all_after('Example:').all_after('example:').trim_space() code := example.all_after('Example:').all_after('example:').trim_space()
mod_name := get_mod_name_by_file_path(dn.file_path) mod_name := get_mod_name_by_file_path(dn.file_path)
vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v') vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v')
@ -61,6 +64,7 @@ fn (mut vd VDoc) run_examples(dn doc.DocNode) {
import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' } import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' }
source := '${import_clause}fn main() {\n\t${code}\n}\n' source := '${import_clause}fn main() {\n\t${code}\n}\n'
os.write_file(vsource_path, source) or { continue } os.write_file(vsource_path, source) or { continue }
vd.vprintln('>>> vd.example_oks: ${vd.example_oks:5} | vd.example_failures: ${vd.example_failures:5} | examples.len: ${examples.len} | source.len: ${source.len:5} | dn.name: ${dn.name}')
cmd := '${os.quoted_path(vexe)} ${voptions} ${os.quoted_path(vsource_path)}' cmd := '${os.quoted_path(vexe)} ${voptions} ${os.quoted_path(vsource_path)}'
res := os.execute(cmd) res := os.execute(cmd)
if res.exit_code != 0 { if res.exit_code != 0 {
@ -68,12 +72,10 @@ fn (mut vd VDoc) run_examples(dn doc.DocNode) {
eprintln(' cmd: ${cmd}') eprintln(' cmd: ${cmd}')
eprintln(' result:') eprintln(' result:')
eprintln(res.output) eprintln(res.output)
failures++ vd.example_failures++
continue continue
} }
example_program_source_files << vsource_path example_program_source_files << vsource_path
oks++ vd.example_oks++
} }
vd.example_failures += failures
vd.example_oks += oks
} }

View file

@ -369,7 +369,7 @@ pub fn (mut a array) delete(i int) {
// Example: // Example:
// ```v // ```v
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9] // mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
// b := a[..9] // creates a `slice` of `a`, not a clone // b := unsafe { a[..9] } // creates a `slice` of `a`, not a clone
// a.delete_many(4, 3) // replaces `a` with a modified clone // a.delete_many(4, 3) // replaces `a` with a modified clone
// dump(a) // a: [1, 2, 3, 4, 8, 9] // `a` is now different // dump(a) // a: [1, 2, 3, 4, 8, 9] // `a` is now different
// dump(b) // b: [1, 2, 3, 4, 5, 6, 7, 8, 9] // `b` is still the same // dump(b) // b: [1, 2, 3, 4, 5, 6, 7, 8, 9] // `b` is still the same
@ -413,7 +413,7 @@ pub fn (mut a array) delete_many(i int, size int) {
// clear clears the array without deallocating the allocated data. // clear clears the array without deallocating the allocated data.
// It does it by setting the array length to `0` // It does it by setting the array length to `0`
// Example: a.clear() // `a.len` is now 0 // Example: mut a := [1,2]; a.clear(); assert a.len == 0
pub fn (mut a array) clear() { pub fn (mut a array) clear() {
a.len = 0 a.len = 0
} }
@ -430,7 +430,7 @@ pub fn (mut a array) reset() {
// trim trims the array length to `index` without modifying the allocated data. // trim trims the array length to `index` without modifying the allocated data.
// If `index` is greater than `len` nothing will be changed. // If `index` is greater than `len` nothing will be changed.
// Example: a.trim(3) // `a.len` is now <= 3 // Example: mut a := [1,2,3,4]; a.trim(3); assert a.len == 10
pub fn (mut a array) trim(index int) { pub fn (mut a array) trim(index int) {
if index < a.len { if index < a.len {
a.len = index a.len = index
@ -520,11 +520,14 @@ pub fn (a array) last() voidptr {
// Example: // Example:
// ```v // ```v
// mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9] // mut a := [1, 2, 3, 4, 5, 6, 7, 8, 9]
// b := a[..9] // creates a "view" into the same memory // b := unsafe{ a[..9] } // creates a "view" (also called a slice) into the same memory
// c := a.pop() // c == 9 // c := a.pop()
// assert c == 9
// a[1] = 5 // a[1] = 5
// dump(a) // a: [1, 5, 3, 4, 5, 6, 7, 8] // dump(a) // a: [1, 5, 3, 4, 5, 6, 7, 8]
// dump(b) // b: [1, 5, 3, 4, 5, 6, 7, 8, 9] // dump(b) // b: [1, 5, 3, 4, 5, 6, 7, 8, 9]
// assert a.len == 8
// assert b.len == 9
// ``` // ```
pub fn (mut a array) pop() voidptr { pub fn (mut a array) pop() voidptr {
// in a sense, this is the opposite of `a << x` // in a sense, this is the opposite of `a << x`
@ -816,9 +819,9 @@ pub fn (a &array) free() {
// Each function takes a boolean test expression as its single argument. // Each function takes a boolean test expression as its single argument.
// These test expressions may use `it` as a pointer to a single element at a time. // These test expressions may use `it` as a pointer to a single element at a time.
// //
// Example: array.filter(it < 5) // create an array of elements less than 5 // Example: a := [10,20,30,3,5,99]; assert a.filter(it < 5) == [3,5] // create an array of elements less than 5
// Example: array.filter(it % 2 == 1) // create an array of only odd elements // Example: a := [10,20,30,3,5,99]; assert a.filter(it % 2 == 1) == [3,5,99] // create an array of only odd elements
// Example: array.filter(it.name[0] == `A`) // create an array of elements whose `name` field starts with 'A' // Example: struct Named { name string }; a := [Named{'Abc'}, Named{'Bcd'}, Named{'Az'}]; assert a.filter(it.name[0] == `A`).len == 2
pub fn (a array) filter(predicate fn (voidptr) bool) array pub fn (a array) filter(predicate fn (voidptr) bool) array
// any tests whether at least one element in the array passes the test. // any tests whether at least one element in the array passes the test.
@ -827,15 +830,15 @@ pub fn (a array) filter(predicate fn (voidptr) bool) array
// It returns `true` if it finds an element passing the test. Otherwise, // It returns `true` if it finds an element passing the test. Otherwise,
// it returns `false`. It doesn't modify the array. // it returns `false`. It doesn't modify the array.
// //
// Example: array.any(it % 2 == 1) // will return true if any element is odd // Example: a := [2,3,4]; assert a.any(it % 2 == 1) // 3 is odd, so this will pass
// Example: array.any(it.name == 'Bob') // will yield `true` if any element has `.name == 'Bob'` // Example: struct Named { name string }; a := [Named{'Bob'}, Named{'Bilbo'}]; assert a.any(it.name == 'Bob') // the first element will match
pub fn (a array) any(predicate fn (voidptr) bool) bool pub fn (a array) any(predicate fn (voidptr) bool) bool
// count counts how many elements in array pass the test. // count counts how many elements in array pass the test.
// Ignore the function signature. `count` does not take an actual callback. Rather, it // Ignore the function signature. `count` does not take an actual callback. Rather, it
// takes an `it` expression. // takes an `it` expression.
// //
// Example: array.count(it % 2 == 1) // will return how many elements are odd // Example: a := [10,3,5,7]; assert a.count(it % 2 == 1) == 3 // will return how many elements are odd
pub fn (a array) count(predicate fn (voidptr) bool) int pub fn (a array) count(predicate fn (voidptr) bool) int
// all tests whether all elements in the array pass the test. // all tests whether all elements in the array pass the test.
@ -844,7 +847,7 @@ pub fn (a array) count(predicate fn (voidptr) bool) int
// It returns `false` if any element fails the test. Otherwise, // It returns `false` if any element fails the test. Otherwise,
// it returns `true`. It doesn't modify the array. // it returns `true`. It doesn't modify the array.
// //
// Example: array.all(it % 2 == 1) // will return true if every element is odd // Example: a := [3,5,7,9]; assert a.all(it % 2 == 1) // will return true if every element is odd
pub fn (a array) all(predicate fn (voidptr) bool) bool pub fn (a array) all(predicate fn (voidptr) bool) bool
// map creates a new array populated with the results of calling a provided function // map creates a new array populated with the results of calling a provided function
@ -873,9 +876,9 @@ pub fn (a array) map(callback fn (voidptr) voidptr) array
// The expression uses 2 'magic' variables `a` and `b` as pointers to the two elements // The expression uses 2 'magic' variables `a` and `b` as pointers to the two elements
// being compared. // being compared.
// //
// Example: array.sort() // will sort the array in ascending order // Example: mut aa := [5,2,1,10]; aa.sort(); assert aa == [1,2,5,10] // will sort the array in ascending order
// Example: array.sort(b < a) // will sort the array in descending order // Example: mut aa := [5,2,1,10]; aa.sort(b < a); assert aa == [10,5,2,1] // will sort the array in descending order
// Example: array.sort(b.name < a.name) // will sort descending by the .name field // Example: struct Named { name string }; mut aa := [Named{'Abc'}, Named{'Xyz'}]; aa.sort(b.name < a.name); assert aa.map(it.name) == ['Abc', 'Xyz'] // will sort descending by the .name field
pub fn (mut a array) sort(callback fn (voidptr, voidptr) int) pub fn (mut a array) sort(callback fn (voidptr, voidptr) int)
// sorted returns a sorted copy of the original array. The original array is *NOT* modified. // sorted returns a sorted copy of the original array. The original array is *NOT* modified.
@ -894,9 +897,8 @@ pub fn (a &array) sorted(callback fn (voidptr, voidptr) int) array
// //
// Example: // Example:
// ```v // ```v
// fn main() { // mut a := ['hi', '1', '5', '3']
// mut a := ['hi', '1', '5', '3'] // a.sort_with_compare(fn (a &string, b &string) int {
// a.sort_with_compare(fn (a &string, b &string) int {
// if a < b { // if a < b {
// return -1 // return -1
// } // }
@ -904,9 +906,8 @@ pub fn (a &array) sorted(callback fn (voidptr, voidptr) int) array
// return 1 // return 1
// } // }
// return 0 // return 0
// }) // })
// assert a == ['1', '3', '5', 'hi'] // assert a == ['1', '3', '5', 'hi']
// }
// ``` // ```
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) { pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
$if freestanding { $if freestanding {
@ -934,7 +935,7 @@ pub fn (a &array) sorted_with_compare(callback fn (voidptr, voidptr) int) array
// It will return `true` if the array contains an element with this value. // It will return `true` if the array contains an element with this value.
// It is similar to `.any` but does not take an `it` expression. // It is similar to `.any` but does not take an `it` expression.
// //
// Example: [1, 2, 3].contains(4) == false // Example: assert [1, 2, 3].contains(4) == false
pub fn (a array) contains(value voidptr) bool pub fn (a array) contains(value voidptr) bool
// index returns the first index at which a given element can be found in the array or `-1` if the value is not found. // index returns the first index at which a given element can be found in the array or `-1` if the value is not found.
@ -955,7 +956,7 @@ pub fn (mut a []string) free() {
// to arrays of different types in different ways. // to arrays of different types in different ways.
// str returns a string representation of an array of strings. // str returns a string representation of an array of strings.
// Example: ['a', 'b', 'c'].str() // => "['a', 'b', 'c']". // Example: assert ['a', 'b', 'c'].str() == "['a', 'b', 'c']"
@[direct_array_access; manualfree] @[direct_array_access; manualfree]
pub fn (a []string) str() string { pub fn (a []string) str() string {
mut sb_len := 4 // 2x" + 1x, + 1xspace mut sb_len := 4 // 2x" + 1x, + 1xspace

View file

@ -118,7 +118,7 @@ fn trace_error(x string) {
} }
// error returns a default error instance containing the error given in `message`. // error returns a default error instance containing the error given in `message`.
// Example: if ouch { return error('an error occurred') } // Example: f := fn (ouch bool) ! { if ouch { return error('an error occurred') } }; f(false)!
@[inline] @[inline]
pub fn error(message string) IError { pub fn error(message string) IError {
trace_error(message) trace_error(message)
@ -128,7 +128,7 @@ pub fn error(message string) IError {
} }
// error_with_code returns a default error instance containing the given `message` and error `code`. // error_with_code returns a default error instance containing the given `message` and error `code`.
// Example: if ouch { return error_with_code('an error occurred', 1) } // Example: f := fn (ouch bool) ! { if ouch { return error_with_code('an error occurred', 1) } }; f(false)!
@[inline] @[inline]
pub fn error_with_code(message string, code int) IError { pub fn error_with_code(message string, code int) IError {
trace_error('${message} | code: ${code}') trace_error('${message} | code: ${code}')

View file

@ -538,8 +538,8 @@ pub fn (b u8) str_escaped() string {
} }
// is_capital returns `true`, if the byte is a Latin capital letter. // is_capital returns `true`, if the byte is a Latin capital letter.
// Example: assert `H`.is_capital() == true // Example: assert u8(`H`).is_capital() == true
// Example: assert `h`.is_capital() == false // Example: assert u8(`h`).is_capital() == false
@[inline] @[inline]
pub fn (c u8) is_capital() bool { pub fn (c u8) is_capital() bool {
return c >= `A` && c <= `Z` return c >= `A` && c <= `Z`

View file

@ -324,7 +324,7 @@ pub fn (mut m map) move() map {
// clear clears the map without deallocating the allocated data. // clear clears the map without deallocating the allocated data.
// It does it by setting the map length to `0` // It does it by setting the map length to `0`
// Example: a.clear() // `a.len` and `a.key_values.len` is now 0 // Example: mut m := {'abc': 'xyz', 'def': 'aaa'}; m.clear(); assert m.len == 0
pub fn (mut m map) clear() { pub fn (mut m map) clear() {
unsafe { unsafe {
if m.key_values.all_deleted != 0 { if m.key_values.all_deleted != 0 {

View file

@ -872,7 +872,7 @@ fn (s string) plus_two(a string, b string) string {
// split_any splits the string to an array by any of the `delim` chars. // split_any splits the string to an array by any of the `delim` chars.
// If the delimiter string is empty then `.split()` is used. // If the delimiter string is empty then `.split()` is used.
// Example: "first row\nsecond row".split_any(" \n") == ['first', 'row', 'second', 'row'] // Example: assert "first row\nsecond row".split_any(" \n") == ['first', 'row', 'second', 'row']
@[direct_array_access] @[direct_array_access]
pub fn (s string) split_any(delim string) []string { pub fn (s string) split_any(delim string) []string {
mut res := []string{} mut res := []string{}
@ -903,7 +903,7 @@ pub fn (s string) split_any(delim string) []string {
// rsplit_any splits the string to an array by any of the `delim` chars in reverse order. // rsplit_any splits the string to an array by any of the `delim` chars in reverse order.
// If the delimiter string is empty then `.rsplit()` is used. // If the delimiter string is empty then `.rsplit()` is used.
// Example: "first row\nsecond row".rsplit_any(" \n") == ['row', 'second', 'row', 'first'] // Example: assert "first row\nsecond row".rsplit_any(" \n") == ['row', 'second', 'row', 'first']
@[direct_array_access] @[direct_array_access]
pub fn (s string) rsplit_any(delim string) []string { pub fn (s string) rsplit_any(delim string) []string {
mut res := []string{} mut res := []string{}
@ -1837,7 +1837,7 @@ pub fn (s string) trim(cutset string) string {
} }
// trim_indexes gets the new start and end indices of a string when any of the characters given in `cutset` were stripped from the start and end of the string. Should be used as an input to `substr()`. If the string contains only the characters in `cutset`, both values returned are zero. // trim_indexes gets the new start and end indices of a string when any of the characters given in `cutset` were stripped from the start and end of the string. Should be used as an input to `substr()`. If the string contains only the characters in `cutset`, both values returned are zero.
// Example: left, right := '-hi-'.trim_indexes('-') // Example: left, right := '-hi-'.trim_indexes('-'); assert left == 1; assert right == 3
@[direct_array_access] @[direct_array_access]
pub fn (s string) trim_indexes(cutset string) (int, int) { pub fn (s string) trim_indexes(cutset string) (int, int) {
mut pos_left := 0 mut pos_left := 0
@ -2965,7 +2965,7 @@ pub:
// wrap wraps the string `s` when each line exceeds the width specified in `width` . // wrap wraps the string `s` when each line exceeds the width specified in `width` .
// (default value is 80), and will use `end` (default value is '\n') as a line break. // (default value is 80), and will use `end` (default value is '\n') as a line break.
// Example: `assert 'Hello, my name is Carl and I am a delivery'.wrap(width: 20) == 'Hello, my name is\nCarl and I am a\ndelivery'` // Example: assert 'Hello, my name is Carl and I am a delivery'.wrap(width: 20) == 'Hello, my name is\nCarl and I am a\ndelivery'
pub fn (s string) wrap(config WrapConfig) string { pub fn (s string) wrap(config WrapConfig) string {
if config.width <= 0 { if config.width <= 0 {
return '' return ''