From bd408289d501263b0464839dc32ca715308df09a Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 13 Aug 2025 21:02:14 +0300 Subject: [PATCH] vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so `v doc -v -unsafe-run-examples -f none vlib/` could be added to the CI --- cmd/tools/vdoc/run_examples.v | 6 ++- vlib/veb/assets/assets.v | 2 +- vlib/veb/middleware.v | 6 +-- vlib/veb/veb.v | 2 +- vlib/vweb/vweb.v | 47 ++++++++++--------- vlib/x/crypto/slhdsa/slhdsa.v | 8 ++-- vlib/x/encoding/asn1/bitstring.v | 8 ++-- vlib/x/sessions/sessions.v | 6 +-- .../vweb2_middleware/vweb2_middleware.v | 3 +- 9 files changed, 46 insertions(+), 42 deletions(-) diff --git a/cmd/tools/vdoc/run_examples.v b/cmd/tools/vdoc/run_examples.v index 1520922bd2..5ece267dc1 100644 --- a/cmd/tools/vdoc/run_examples.v +++ b/cmd/tools/vdoc/run_examples.v @@ -62,7 +62,11 @@ fn (mut vd VDoc) run_examples(dn doc.DocNode) { vsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v') // eprintln('>>> example dn.file_path: ${dn.file_path} | mod_name: ${mod_name} | vsource_path: ${vsource_path} | code: `${code}`') import_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\n' } - source := '${import_clause}fn main() {\n\t${code}\n}\n' + source := if import_clause != '' && !code.contains('import ') { + '${import_clause}fn main() {\n\t${code}\n}\n' + } else { + code + } 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)}' diff --git a/vlib/veb/assets/assets.v b/vlib/veb/assets/assets.v index 0b716564c4..bbadec3869 100644 --- a/vlib/veb/assets/assets.v +++ b/vlib/veb/assets/assets.v @@ -206,7 +206,7 @@ pub fn (am AssetManager) exists(asset_type AssetType, include_name string) bool } // include css/js files in your veb app from templates -// Example: +// Usage example: // ```html // @{app.am.include(.css, 'main.css')} // ``` diff --git a/vlib/veb/middleware.v b/vlib/veb/middleware.v index d90b292aaf..21aa4bd85a 100644 --- a/vlib/veb/middleware.v +++ b/vlib/veb/middleware.v @@ -120,7 +120,7 @@ fn validate_middleware[T](mut ctx T, raw_handlers []voidptr) bool { // encode_gzip adds gzip encoding to the HTTP Response body. // This middleware does not encode files, if you return `ctx.file()`. // Register this middleware as last! -// Example: app.use(veb.encode_gzip[Context]()) +// Usage example: app.use(veb.encode_gzip[Context]()) pub fn encode_gzip[T]() MiddlewareOptions[T] { return MiddlewareOptions[T]{ after: true @@ -155,7 +155,7 @@ pub fn encode_gzip[T]() MiddlewareOptions[T] { // decode_gzip decodes the body of a gzip'ed HTTP request. // Register this middleware before you do anything with the request body! -// Example: app.use(veb.decode_gzip[Context]()) +// Usage example: app.use(veb.decode_gzip[Context]()) pub fn decode_gzip[T]() MiddlewareOptions[T] { return MiddlewareOptions[T]{ handler: fn [T](mut ctx T) bool { @@ -299,7 +299,7 @@ pub fn (options &CorsOptions) validate_request(mut ctx Context) bool { // cors handles cross-origin requests by adding Access-Control-* headers to a // preflight request and validating the headers of a cross-origin request. -// Example: +// Usage example: // ```v // app.use(veb.cors[Context](veb.CorsOptions{ // origins: ['*'] diff --git a/vlib/veb/veb.v b/vlib/veb/veb.v index f7a9b0148e..0d3f02aa2f 100644 --- a/vlib/veb/veb.v +++ b/vlib/veb/veb.v @@ -142,7 +142,7 @@ mut: } // run_at - start a new veb server, listening only on a specific address `host`, at the specified `port` -// Example: veb.run_at(new_app(), veb.RunParams{ host: 'localhost' port: 8099 family: .ip }) or { panic(err) } +// Usage example: veb.run_at(new_app(), host: 'localhost' port: 8099 family: .ip)! @[direct_array_access; manualfree] pub fn run_at[A, X](mut global_app A, params RunParams) ! { if params.port <= 0 || params.port > 65535 { diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index f0eb1bea65..4b34eb1aa5 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -200,8 +200,8 @@ struct Route { host string } -// Defining this method is optional. -// This method called at server start. +// init_server is called at the server start. +// Note: defining this method is optional. // You can use it for initializing globals. pub fn (ctx &Context) init_server() { eprintln('init_server() has been deprecated, please init your web app in `fn main()`') @@ -223,7 +223,7 @@ pub fn (ctx &Context) before_accept_loop() { pub fn (ctx &Context) before_request() {} // TODO: test -// vweb intern function +// send_response_to_client sends back a custom response to the client, with the given `mimetype` and content in `res`. @[manualfree] pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bool { if ctx.done { @@ -253,26 +253,26 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo return true } -// Response with payload and content-type `text/html` +// html responds with payload and content-type `text/html` pub fn (mut ctx Context) html(payload string) Result { ctx.send_response_to_client('text/html', payload) return Result{} } -// Response with s as payload and content-type `text/plain` +// text responds with s as payload and content-type `text/plain` pub fn (mut ctx Context) text(s string) Result { ctx.send_response_to_client('text/plain', s) return Result{} } -// Response with json_s as payload and content-type `application/json` +// json responds with json_s as payload and content-type `application/json` pub fn (mut ctx Context) json[T](j T) Result { json_s := json.encode(j) ctx.send_response_to_client('application/json', json_s) return Result{} } -// Response with a pretty-printed JSON result +// json_pretty responds with a pretty-printed JSON result pub fn (mut ctx Context) json_pretty[T](j T) Result { json_s := json.encode_pretty(j) ctx.send_response_to_client('application/json', json_s) @@ -280,7 +280,7 @@ pub fn (mut ctx Context) json_pretty[T](j T) Result { } // TODO: test -// Response with file as payload +// file responds with the content of the given file as payload. pub fn (mut ctx Context) file(f_path string) Result { if !os.exists(f_path) { eprintln('[vweb] file ${f_path} does not exist') @@ -302,7 +302,7 @@ pub fn (mut ctx Context) file(f_path string) Result { return Result{} } -// Response with s as payload and sets the status code to HTTP_OK +// ok responds with s as payload and sets the status code to HTTP_OK pub fn (mut ctx Context) ok(s string) Result { ctx.set_status(200, 'OK') ctx.send_response_to_client(ctx.content_type, s) @@ -310,7 +310,7 @@ pub fn (mut ctx Context) ok(s string) Result { } // TODO: test -// Response a server error +// server_error will send back an error response to the client. pub fn (mut ctx Context) server_error(ecode int) Result { $if debug { eprintln('> ctx.server_error ecode: ${ecode}') @@ -322,13 +322,14 @@ pub fn (mut ctx Context) server_error(ecode int) Result { return Result{} } +// RedirectParams represent the optional parameters to redirect/2 . @[params] pub struct RedirectParams { pub: status_code int = 302 } -// Redirect to an url +// redirect to an url. pub fn (mut ctx Context) redirect(url string, params RedirectParams) Result { if ctx.done { return Result{} @@ -344,7 +345,7 @@ pub fn (mut ctx Context) redirect(url string, params RedirectParams) Result { return Result{} } -// Send an not_found response +// not_found send an not_found response. pub fn (mut ctx Context) not_found() Result { // TODO: add a [must_be_returned] attribute, so that the caller is forced to use `return app.not_found()` if ctx.done { @@ -356,7 +357,7 @@ pub fn (mut ctx Context) not_found() Result { } // TODO: test -// Sets a cookie +// set_cookie sets a cookie. pub fn (mut ctx Context) set_cookie(cookie http.Cookie) { cookie_raw := cookie.str() if cookie_raw == '' { @@ -366,13 +367,13 @@ pub fn (mut ctx Context) set_cookie(cookie http.Cookie) { ctx.add_header('Set-Cookie', cookie_raw) } -// Sets the response content type +// set_content_type sets the response content type. pub fn (mut ctx Context) set_content_type(typ string) { ctx.content_type = typ } // TODO: test -// Sets a cookie with a `expire_date` +// set_cookie_with_expire_date sets a cookie with an `expire_date`. pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, expire_date time.Time) { cookie := http.Cookie{ name: key @@ -382,7 +383,7 @@ pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, exp ctx.set_cookie(cookie) } -// Gets a cookie by a key +// get_cookie get the value of a cookie, given its key. pub fn (ctx &Context) get_cookie(key string) !string { c := ctx.req.cookie(key) or { return error('Cookie not found') } return c.value @@ -413,12 +414,12 @@ pub fn (ctx &Context) get_header(key string) string { return ctx.req.header.get_custom(key) or { '' } } -// set_value sets a value on the context +// set_value sets a value on the context. pub fn (mut ctx Context) set_value(key context.Key, value context.Any) { ctx.ctx = context.with_value(ctx.ctx, key, value) } -// get_value gets a value from the context +// get_value gets a value from the context. pub fn (ctx &Context) get_value[T](key context.Key) ?T { if val := ctx.ctx.value(key) { match val { @@ -495,7 +496,7 @@ pub mut: controllers []&ControllerPath } -// controller generates a new Controller for the main app +// controller generates a new Controller for the main app. pub fn controller[T](path string, global_app &T) &ControllerPath { routes := generate_routes(global_app) or { panic(err.msg()) } @@ -513,14 +514,14 @@ pub fn controller[T](path string, global_app &T) &ControllerPath { } } -// controller_host generates a controller which only handles incoming requests from the `host` domain +// controller_host generates a controller which only handles incoming requests from the `host` domain. pub fn controller_host[T](host string, path string, global_app &T) &ControllerPath { mut ctrl := controller(path, global_app) ctrl.host = host return ctrl } -// run - start a new VWeb server, listening to all available addresses, at the specified `port` +// run - start a new VWeb server, listening to all available addresses, at the specified `port`. pub fn run[T](global_app &T, port int) { run_at[T](global_app, host: '', port: port, family: .ip6) or { panic(err.msg()) } } @@ -537,8 +538,8 @@ pub: startup_message string } -// run_at - start a new VWeb server, listening only on a specific address `host`, at the specified `port` -// Example: vweb.run_at(new_app(), vweb.RunParams{ host: 'localhost' port: 8099 family: .ip }) or { panic(err) } +// run_at - start a new VWeb server, listening only on a specific address `host`, at the specified `port`. +// Usage example: vweb.run_at(new_app(), host: 'localhost' port: 8099 family: .ip)! @[manualfree] pub fn run_at[T](global_app &T, params RunParams) ! { if params.port <= 0 || params.port > 65535 { diff --git a/vlib/x/crypto/slhdsa/slhdsa.v b/vlib/x/crypto/slhdsa/slhdsa.v index 716a343714..1d75e7fbcc 100644 --- a/vlib/x/crypto/slhdsa/slhdsa.v +++ b/vlib/x/crypto/slhdsa/slhdsa.v @@ -13,10 +13,10 @@ pub struct PrivateKey { // See `enum Kind` for all of availables choice's type (kind) of key. // Its also support to generate keys based on the seed or private bytes through // provided options. See available options in `KeyOpts`. -// Example: -// ``` -// PrivateKey.new()! -// PrivateKey.new(kind: .sha2_128s) +// Usage example: +// ```v +// pk1 := slhdsa.PrivateKey.new()!; println(pk1) +// pk2 := slhdsa.PrivateKey.new(kind: .sha2_128s)!; println(pk2) // ``` pub fn PrivateKey.new(opt KeyOpts) !PrivateKey { match opt.flag { diff --git a/vlib/x/encoding/asn1/bitstring.v b/vlib/x/encoding/asn1/bitstring.v index 0cf318b6ce..d49967be38 100644 --- a/vlib/x/encoding/asn1/bitstring.v +++ b/vlib/x/encoding/asn1/bitstring.v @@ -63,7 +63,8 @@ pub fn (bs BitString) payload() ![]u8 { return out } -fn (bs BitString) str() string { +// str returns a string representation of the current state of bs. +pub fn (bs BitString) str() string { return 'BitString: ${bs.data.hex()} (${bs.pad})' } @@ -115,10 +116,9 @@ fn BitString.decode_with_rule(bytes []u8, rule EncodingRule) !(BitString, int) { // seven bits of the last octet are not used and is interpreted as a pad value. // Example: // ```v -// import x.encoding.asn1 -// +// import x.encoding.asn1 // bs := asn1.BitString.from_binary_string('011010001')! -// assert (bs.pad == 7 && bs.data == [u8(0x68), 0x80]) == true +// assert bs.str() == 'BitString: 6880 (7)' // ``` pub fn BitString.from_binary_string(s string) !BitString { res, pad := parse_bits_string(s)! diff --git a/vlib/x/sessions/sessions.v b/vlib/x/sessions/sessions.v index bbb803983d..82f08fde53 100644 --- a/vlib/x/sessions/sessions.v +++ b/vlib/x/sessions/sessions.v @@ -38,9 +38,9 @@ pub fn verify_session_id(raw_sid string, secret []u8) (string, bool) { // CurrentSession contains the session data during a request. // If you use x.vweb you could embed it on your Context struct to have easy access to the session id and data. -// Example: +// Usage example: // ```v -// pub struct Context { +// struct Context { // vweb.Context // sessions.CurrentSessions[User] // } @@ -65,7 +65,7 @@ pub: // Sessions can be used to easily integrate sessions with x.vweb. // This struct contains the store that holds all session data it also provides // an easy way to manage sessions in your vweb app. -// Example: +// Usage example: // ```v // pub struct App { // pub mut: diff --git a/vlib/x/sessions/vweb2_middleware/vweb2_middleware.v b/vlib/x/sessions/vweb2_middleware/vweb2_middleware.v index 5f18b055d0..9d32ccbe86 100644 --- a/vlib/x/sessions/vweb2_middleware/vweb2_middleware.v +++ b/vlib/x/sessions/vweb2_middleware/vweb2_middleware.v @@ -6,8 +6,7 @@ import veb // middleware can be used to add session middleware to your vweb app to ensure // a valid session always exists. If a valid session exists the session data will // be loaded into `session_data`, else a new session id will be generated. -// You have to pass the Context type as the generic type -// Example: app.use(app.sessions.middleware[Context]()) +// You have to pass the Context type as the generic type. pub fn create[T, X](mut s sessions.Sessions[T]) veb.MiddlewareOptions[X] { return veb.MiddlewareOptions[X]{ handler: fn [mut s] [T, X](mut ctx X) bool {