From 37513121a31460af1448cbe957f474d30e6f0516 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 28 Apr 2026 18:30:46 +0300 Subject: [PATCH] all: fix more tests --- doc/docs.md | 13 +++++++--- vlib/compress/snappy/snappy_block.v | 4 +-- vlib/compress/snappy/snappy_framing.v | 18 ++++++------- vlib/encoding/binary/README.md | 2 +- vlib/regex/README.md | 8 +++++- vlib/v/gen/c/array.v | 4 ++- vlib/v/gen/c/cgen.v | 21 ++++++++++------ .../gen/c/cheaders_manual_stdlib_decls_test.v | 25 ++++++++++++++++--- vlib/v/gen/c/fn.v | 1 + ...ows_clang_bootstrap_regression.c.must_have | 2 +- vlib/veb/request_id/README.md | 2 ++ vlib/x/markdown/README.md | 25 +++++++++++++------ 12 files changed, 88 insertions(+), 37 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index fe882dc49..2df8fcb11 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -2023,6 +2023,7 @@ match true { 2 == 2 { println('else if2') } else { println('else') } } + // 'else if2' should be printed ``` @@ -2035,6 +2036,7 @@ match false { 2 == 2 { println('else if2') } else { println('else') } } + // 'if' should be printed ``` @@ -2067,6 +2069,7 @@ typ := match c { `a`...`z` { 'lowercase' } else { 'other' } } + println(typ) // 'lowercase' ``` @@ -2109,6 +2112,7 @@ num := match c { 0 } } + println(num) // 1000 ``` @@ -3758,6 +3762,7 @@ match color { .green { println('the color was green') } .blue { println('the color was blue') } } + println(int(color)) // prints 1 ``` @@ -3799,7 +3804,7 @@ Output: `Grocery IDs: 0, 5, 6`. Compile-time `$if` blocks can also be used inside enum bodies to include fields conditionally. -```v +```v nofmt enum Feature { base $if beta ? { @@ -7532,7 +7537,7 @@ Operator overloading is possible for the following binary operators: Indexing can be overloaded too: -```v +```v oksyntax struct Buffer { mut: data []int @@ -8568,7 +8573,7 @@ If you export your own `DllMain`, V will not generate the default one. Call `C._vinit_caller()` and `C._vcleanup_caller()` from your entry point to keep the standard V runtime setup and teardown: -```v +```v oksyntax pub type C.DWORD = u32 pub type C.LPVOID = voidptr @@ -8584,7 +8589,7 @@ pub fn dll_main(hinst C.HINSTANCE, reason C.DWORD, reserved C.LPVOID) C.BOOL { } else if reason == C.DWORD(0) { C._vcleanup_caller() } - return 1 + return C.BOOL(1) } ``` diff --git a/vlib/compress/snappy/snappy_block.v b/vlib/compress/snappy/snappy_block.v index c6129e3d0..47878d9dd 100644 --- a/vlib/compress/snappy/snappy_block.v +++ b/vlib/compress/snappy/snappy_block.v @@ -62,8 +62,8 @@ pub fn compress(input []u8) []u8 { return out } -// decompress decompresses a Snappy-compressed slice and returns the -// original bytes, or an error if the data is malformed. +// decompress decompresses a Snappy-compressed slice. +// It returns the original bytes, or an error if the data is malformed. pub fn decompress(input []u8) ![]u8 { // Read the varint-encoded uncompressed length from the header. ulen, hdr_end, ok := read_uvarint(input, 0) diff --git a/vlib/compress/snappy/snappy_framing.v b/vlib/compress/snappy/snappy_framing.v index d0b1beeed..2037b0209 100644 --- a/vlib/compress/snappy/snappy_framing.v +++ b/vlib/compress/snappy/snappy_framing.v @@ -56,8 +56,8 @@ const max_chunk_data_size = 65536 // One-shot API // --------------------------------------------------------------------------- -// encode_stream wraps `input` in the Snappy framing format and returns the -// complete byte stream. Input is split into ≤64 KiB blocks automatically. +// encode_stream wraps `input` in the Snappy framing format. +// It returns the complete byte stream. Input is split into <=64 KiB blocks automatically. pub fn encode_stream(input []u8) []u8 { // Upper bound: identifier chunk + one compressed chunk per block. // Each block: 4-byte header + 4-byte CRC + max_compressed_length. @@ -77,8 +77,8 @@ pub fn encode_stream(input []u8) []u8 { return out } -// decode_stream decodes a Snappy framing stream and returns the concatenated -// uncompressed data, or an error if the stream is malformed. +// decode_stream decodes a Snappy framing stream. +// It returns the concatenated uncompressed data, or an error if the stream is malformed. pub fn decode_stream(input []u8) ![]u8 { // The compressed stream is typically smaller than the uncompressed data, // so use a larger initial capacity estimate. @@ -201,8 +201,8 @@ mut: closed bool } -// write appends `buf` to the decoder's input buffer and processes as many -// complete chunks as possible. Returns an error if the stream is malformed. +// write appends `buf` to the decoder's input buffer. +// It processes as many complete chunks as possible and errors if the stream is malformed. pub fn (mut dec StreamDecoder) write(buf []u8) !int { if dec.closed { return error('snappy: write to closed stream decoder') @@ -285,9 +285,9 @@ pub fn (mut dec StreamDecoder) write(buf []u8) !int { return buf.len } -// read removes and returns decoded bytes. When the output buffer is empty it -// surfaces any error recorded during write()/close(). Only then does it return -// io.Eof{} for a cleanly terminated stream. +// read removes and returns decoded bytes. +// When the output buffer is empty it surfaces any error recorded during write()/close(). +// Only then does it return io.Eof{} for a cleanly terminated stream. pub fn (mut dec StreamDecoder) read(mut buf []u8) !int { // Always drain already-decoded output first so the caller never loses data. if dec.output.len > 0 { diff --git a/vlib/encoding/binary/README.md b/vlib/encoding/binary/README.md index 2342c5187..073b166d2 100644 --- a/vlib/encoding/binary/README.md +++ b/vlib/encoding/binary/README.md @@ -28,7 +28,7 @@ sequence in big endian, we get `0x12345678`. For generic `T` data encoding/decoding, you can use `encode_binary[T]()` and `decode_binary[T]()`: -```v +```v oksyntax module main import encoding.binary diff --git a/vlib/regex/README.md b/vlib/regex/README.md index 833ff1ace..446e3ef53 100644 --- a/vlib/regex/README.md +++ b/vlib/regex/README.md @@ -206,6 +206,8 @@ that is an `[]int` inside the `RE` struct. **example:** ```v oksyntax +import regex + text := 'cpaz cpapaz cpapapaz' query := r'(c(pa)+z ?)+' mut re := regex.regex_opt(query) or { panic(err) } @@ -246,6 +248,8 @@ pub: Here is an example of use: ```v oksyntax +import regex + /* This simple function converts an HTML RGB value with 3 or 6 hex digits to an u32 value, this function is not optimized and it is only for didatical @@ -419,6 +423,8 @@ use a name map in the `re` struct, using the function `re.get_group_by_name`. Here is a more complex example of using them: ```v oksyntax +import regex + // This function demonstrate the use of the named groups fn convert_html_rgb_n(in_col string) u32 { mut n_digit := if in_col.len == 4 { 1 } else { 2 } @@ -820,4 +826,4 @@ fn main() { ``` More examples are available in the test code for the `regex` module, -see `vlib/regex/regex_test.v`. +see `vlib/regex/regex_test.v`. \ No newline at end of file diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 8d03b8a90..c6a6749fa 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -523,9 +523,11 @@ fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type, var_name st } else if elem_sym.kind == .array_fixed { // nested fixed array -- [N][N]type arr_info := elem_sym.array_fixed_info() + mut exprs := []ast.Expr{cap: 1} + exprs << ast.IntegerLiteral{} { g.expr(ast.ArrayInit{ - exprs: [ast.IntegerLiteral{}] + exprs: exprs typ: node.elem_type elem_type: arr_info.elem_type }) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 6bfe27255..31f3403f7 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6102,12 +6102,12 @@ fn (mut g Gen) expr(node_ ast.Expr) { typ := g.styp(((node.right as ast.ParExpr).expr as ast.AsCast).typ) tmp_var = g.new_tmp_var() g.writeln('${typ} ${tmp_var};') - g.stmts_with_tmp_var([ - ast.ExprStmt{ - pos: node.pos - expr: node.right - }, - ], tmp_var) + mut stmts := []ast.Stmt{cap: 1} + stmts << ast.ExprStmt{ + pos: node.pos + expr: node.right + } + g.stmts_with_tmp_var(stmts, tmp_var) g.set_current_pos_as_last_stmt_pos() g.write(str) } @@ -10467,12 +10467,19 @@ fn (mut g Gen) check_expr_is_const(expr ast.Expr) bool { return g.check_expr_is_const(expr.expr) } ast.InfixExpr { + if expr.op in [.div, .mod] + && g.table.final_sym(g.unwrap_generic(expr.promoted_type)).is_int() { + return false + } return g.check_expr_is_const(expr.left) && g.check_expr_is_const(expr.right) } ast.Ident { return expr.kind == .function || g.table.final_sym(expr.obj.typ).kind != .array_fixed } - ast.StructInit, ast.EnumVal { + ast.StructInit { + return expr.init_fields.all(g.check_expr_is_const(it.expr)) + } + ast.EnumVal { return true } ast.CastExpr { diff --git a/vlib/v/gen/c/cheaders_manual_stdlib_decls_test.v b/vlib/v/gen/c/cheaders_manual_stdlib_decls_test.v index c72646583..e7dd022db 100644 --- a/vlib/v/gen/c/cheaders_manual_stdlib_decls_test.v +++ b/vlib/v/gen/c/cheaders_manual_stdlib_decls_test.v @@ -33,7 +33,7 @@ fn test_default_c_prelude_uses_manual_stdio_stdlib_string_and_stdarg_decls() { assert generated_c.contains('V_CRT_LINKAGE double V_CRT_CALL atof(const char *str);'), generated_c assert generated_c.contains('extern FILE* stdout;'), generated_c assert generated_c.contains('#define stdout (__acrt_iob_func(1))'), generated_c - assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n#include \n#include \n#include \n#include '), generated_c + assert generated_c.contains('#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus)\n// Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep\n// noexcept specifiers consistent'), generated_c assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n\t#define V_CRT_LINKAGE __declspec(dllimport)\n\t#define V_CRT_CALL VCALLCONV(cdecl)\n#else\n\t#define V_CRT_LINKAGE\n\t#define V_CRT_CALL\n#endif'), generated_c assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);'), generated_c assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap);'), generated_c @@ -67,12 +67,12 @@ fn test_msvc_windows_prelude_uses_msvc_crt_headers() { res := os.execute(cmd) assert res.exit_code == 0, '${cmd}\n${res.output}' generated_c := os.read_file(output_path)!.replace('\r\n', '\n') - assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n#include \n#include \n#include \n#include '), generated_c + assert generated_c.contains('#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__cplusplus)\n// Under C++ (g++/clang++), let libc declare FILE/stdio/string/stdlib to keep\n// noexcept specifiers consistent'), generated_c assert !generated_c.contains('V_CRT_IMPORT'), generated_c assert !generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\ntypedef struct _iobuf FILE;'), generated_c assert generated_c.contains('#ifndef va_copy\n\t#define va_copy(dest, src) ((dest) = (src))\n#endif\n#ifndef _TRUNCATE'), generated_c assert generated_c.contains('#if defined(_MSC_VER) && !defined(__clang__)\n\t#define V_CRT_LINKAGE __declspec(dllimport)\n\t#define V_CRT_CALL VCALLCONV(cdecl)\n#else\n\t#define V_CRT_LINKAGE\n\t#define V_CRT_CALL\n#endif'), generated_c - assert generated_c.contains('#if !defined(_MSC_VER) || defined(__clang__)\n#ifdef __cplusplus\nextern "C" {\n#endif\n'), generated_c + assert generated_c.contains('#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus)\n// mingw-w64 stdio.h declares these as static __mingw_ovr inline overrides'), generated_c assert generated_c.contains('#if !((defined(__MINGW32__) || defined(__MINGW64__)) && !defined(__clang__))\nV_CRT_LINKAGE int V_CRT_CALL vfprintf(FILE *stream, const char *format, va_list ap);'), generated_c assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vscprintf(const char *format, va_list ap);'), generated_c assert generated_c.contains('V_CRT_LINKAGE int V_CRT_CALL _vsnprintf_s(char *buffer, size_t size, size_t count, const char *format, va_list ap);'), generated_c @@ -177,3 +177,22 @@ fn test_manual_stdio_decls_allow_direct_atof_calls() { res := os.execute(cmd) assert res.exit_code == 0, '${cmd}\n${res.output}' } + +fn test_c_prelude_ctype_decls_do_not_conflict_with_later_ctype_includes() { + $if !linux { + return + } + tmp_dir := os.join_path(os.vtmp_dir(), 'cheaders_manual_stdlib_ctype_${os.getpid()}') + os.mkdir_all(tmp_dir)! + defer { + os.rmdir_all(tmp_dir) or {} + } + source_path := os.join_path(tmp_dir, 'c_ctype.v') + os.write_file(source_path, + ['fn C.__ctype_b_loc() &&u16', '', 'fn main() {', '\tC.__ctype_b_loc()', '}'].join('\n') + + '\n')! + output_path := os.join_path(tmp_dir, 'c_ctype') + cmd := '${os.quoted_path(cheaders_manual_stdlib_vexe)} -cc clang -show-c-output -o ${os.quoted_path(output_path)} ${os.quoted_path(source_path)}' + res := os.execute(cmd) + assert res.exit_code == 0, '${cmd}\n${res.output}' +} diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 1c80ea424..3b1e24443 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -81,6 +81,7 @@ const c_manual_prelude_decl_names = [ 'strrchr', 'fseek', 'getline', + '__ctype_b_loc', ] fn collect_function_defer_stmts(node &ast.FnDecl) []ast.DeferStmt { diff --git a/vlib/v/gen/c/testdata/windows_clang_bootstrap_regression.c.must_have b/vlib/v/gen/c/testdata/windows_clang_bootstrap_regression.c.must_have index d6900d79a..da3794ac8 100644 --- a/vlib/v/gen/c/testdata/windows_clang_bootstrap_regression.c.must_have +++ b/vlib/v/gen/c/testdata/windows_clang_bootstrap_regression.c.must_have @@ -3,7 +3,7 @@ #elif defined(__MINGW32__) || defined(__MINGW64__) || (defined(__clang__) && (defined(_WIN32) || defined(_WIN64))) FILE* __cdecl __acrt_iob_func(unsigned index); #define stdout (__acrt_iob_func(1)) -#if !defined(_MSC_VER) || defined(__clang__) +#if (!defined(_MSC_VER) || defined(__clang__)) && !defined(__cplusplus) int V_CRT_CALL _fileno(FILE *stream); FILE * V_CRT_CALL _wfopen(const unsigned short *filename, const unsigned short *mode); int V_CRT_CALL _vscprintf(const char *format, va_list ap); diff --git a/vlib/veb/request_id/README.md b/vlib/veb/request_id/README.md index ffc93cd7e..896f3e428 100644 --- a/vlib/veb/request_id/README.md +++ b/vlib/veb/request_id/README.md @@ -99,6 +99,8 @@ fn (app &App) handler(mut ctx Context) veb.Result { The `Config` struct provides several configuration options: ```v okfmt +import rand + pub struct Config { pub: next ?fn (ctx &veb.Context) bool diff --git a/vlib/x/markdown/README.md b/vlib/x/markdown/README.md index 96ad43e4f..e27145e7a 100644 --- a/vlib/x/markdown/README.md +++ b/vlib/x/markdown/README.md @@ -47,7 +47,9 @@ fn main() { ### With Extensions ```v oksyntax -mut md := markdown.new(Options{ +import x.markdown + +mut md := markdown.Markdown.new(markdown.Options{ extensions: markdown.gfm() }) html := md.convert('| Name |\n|------|\n| Alice |') @@ -60,7 +62,7 @@ println(html) // Renders as HTML table import x.markdown fn main() { - mut md := markdown.new(markdown.Options{ + mut md := markdown.Markdown.new(markdown.Options{ extensions: [markdown.Extension(markdown.footnote()), markdown.typographer()] parser_opts: markdown.ParserOptions{ auto_heading_id: true @@ -82,7 +84,7 @@ fn main() { import x.markdown fn main() { - mut md := markdown.new(markdown.Options{}) + mut md := markdown.Markdown.new(markdown.Options{}) source := '# Hello\n\n`x`' doc := md.parse(source) doc.walk(fn (node &markdown.Node) bool { @@ -105,13 +107,14 @@ fn main() { ### Top-Level Functions - `to_html(src: string) string` - Convert Markdown to HTML with default settings -- `to_html_opts(src: string, opts: Options) string` - Convert with custom options +- `to_html(src: string, opts: Options) string` - Convert with custom options - `parse_inline(src: string, opts: Options, ref_map: map) []&Node` - Parse inline content only ### Main Structs #### `Markdown` -The main processor. Create with `new()`, reuse across multiple calls to share link references. +The main processor. Create with `Markdown.new()`, reuse across multiple calls +to share link references. Methods: - `convert(src: string) string` - Parse and render to HTML in one call @@ -204,26 +207,32 @@ html = markdown.to_html('```v\nfn main() {}\n```') ### Lists ```v oksyntax +import x.markdown + // Bullet list html := markdown.to_html('- item 1\n- item 2') // Ordered list html = markdown.to_html('1. first\n2. second') // Task list (enable via extension or task_list option) -html = markdown.to_html_opts('- [x] done', Options{ task_list: true }) +html = markdown.to_html('- [x] done', markdown.Options{ task_list: true }) ``` ### Tables (GFM) ```v oksyntax +import x.markdown + src := '| Left | Center | Right |\n|:--|:--:|--:|\n| A | B | C |' -html := markdown.to_html_opts(src, Options{ tables: true }) +html := markdown.to_html(src, markdown.Options{ tables: true }) ``` ### Footnotes ```v oksyntax +import x.markdown + src := 'Text[^1]\n\n[^1]: Footnote body.' -html := markdown.to_html_opts(src, Options{ footnotes: true }) +html := markdown.to_html(src, markdown.Options{ footnotes: true }) // Renders with reference and footnote section at bottom ``` -- 2.39.5