From b9e157c572ba2918be69d733efeda8f4cb826df8 Mon Sep 17 00:00:00 2001 From: bwireman Date: Sun, 7 Sep 2025 12:29:21 -0500 Subject: [PATCH 1/4] more stream --- src/testament/internal/util.gleam | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/testament/internal/util.gleam b/src/testament/internal/util.gleam index 4ef9635..ec98992 100644 --- a/src/testament/internal/util.gleam +++ b/src/testament/internal/util.gleam @@ -24,9 +24,7 @@ pub fn get_test_file_name(file: String) -> String { pub fn clean_doc_tests() -> Result(Nil, simplifile.FileError) { use files <- result.try(simplifile.get_files("src")) files - |> stream.new() - |> stream.map(get_test_file_name) - |> stream.to_list() + |> list.map(get_test_file_name) |> simplifile.delete_all() } @@ -156,16 +154,16 @@ pub fn combine_unqualified(imports: List(conf.Import)) -> List(String) { imports |> list.group(fn(i) { i.module }) |> dict.to_list() - |> list.fold([], fn(acc, i) { + |> stream.new() + |> stream.map(fn(i) { let #(module, imports) = i - acc - |> list.prepend(conf.Import( + conf.Import( module: module, unqualified: list.flat_map(imports, fn(v) { v.unqualified }), - )) + ) }) - |> list.map(fn(i) { + |> stream.map(fn(i) { let conf.Import(module, _) = i let tree = @@ -184,4 +182,5 @@ pub fn combine_unqualified(imports: List(conf.Import)) -> List(String) { |> string_tree.to_string() } }) + |> stream.to_list() } From 0d74b4973366f53d21123729512988f358bc94be Mon Sep 17 00:00:00 2001 From: bwireman Date: Sat, 27 Sep 2025 09:46:34 -0500 Subject: [PATCH 2/4] update deps --- example/manifest.toml | 2 +- manifest.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/manifest.toml b/example/manifest.toml index 4a0afb3..8f185a4 100644 --- a/example/manifest.toml +++ b/example/manifest.toml @@ -6,7 +6,7 @@ packages = [ { name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" }, { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, - { name = "gleam_stdlib", version = "0.63.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5E216C7D5E8BE22359C9D7DAA2CFBD66039BC12565542F34CD033C5BB57071ED" }, + { name = "gleam_stdlib", version = "0.64.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "EA2E13FC4E65750643E078487D5EF360BEBCA5EBBBA12042FB589C19F53E35C0" }, { name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" }, { name = "glexer", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "splitter"], otp_app = "glexer", source = "hex", outer_checksum = "40A1FB0919FA080AD6C5809B4C7DBA545841CAAC8168FACDFA0B0667C22475CC" }, { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, diff --git a/manifest.toml b/manifest.toml index c28aa1d..d7b4483 100644 --- a/manifest.toml +++ b/manifest.toml @@ -16,11 +16,11 @@ packages = [ { name = "gleam_community_colour", version = "2.0.2", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "E34DD2C896AC3792151EDA939DA435FF3B69922F33415ED3C4406C932FBE9634" }, { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, { name = "gleam_hexpm", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "gleam_hexpm", source = "hex", outer_checksum = "AAA7813FFD1F32B12C9C0BA5C0BA451324DAC16B7D76E0540EFA526B5208CDAB" }, - { name = "gleam_http", version = "4.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "DD0271B32C356FB684EC7E9F48B1E835D0480168848581F68983C0CC371405D4" }, + { name = "gleam_http", version = "4.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "FFE29C3832698AC3EF6202922EC534EE19540152D01A7C2D22CB97482E4AF211" }, { name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" }, { name = "gleam_json", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "874FA3C3BB6E22DD2BB111966BD40B3759E9094E05257899A7C08F5DE77EC049" }, { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, - { name = "gleam_stdlib", version = "0.63.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5E216C7D5E8BE22359C9D7DAA2CFBD66039BC12565542F34CD033C5BB57071ED" }, + { name = "gleam_stdlib", version = "0.64.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "EA2E13FC4E65750643E078487D5EF360BEBCA5EBBBA12042FB589C19F53E35C0" }, { name = "gleam_time", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "DCDDC040CE97DA3D2A925CDBBA08D8A78681139745754A83998641C8A3F6587E" }, { name = "gleamsver", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleamsver", source = "hex", outer_checksum = "EA74FDC66BF15CB2CF4F8FF9B6FA01D511712EE2B1F4BE0371076ED3F685EEAE" }, { name = "glearray", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "5E272F7CB278CC05A929C58DEB58F5D5AC6DB5B879A681E71138658D0061C38A" }, @@ -39,7 +39,7 @@ packages = [ { name = "splitter", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "05564A381580395DCDEFF4F88A64B021E8DAFA6540AE99B4623962F52976AA9D" }, { name = "term_size", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "term_size", source = "hex", outer_checksum = "D00BD2BC8FB3EBB7E6AE076F3F1FF2AC9D5ED1805F004D0896C784D06C6645F1" }, { name = "tom", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "74D0C5A3761F7A7D06994755D4D5AD854122EF8E9F9F76A3E7547606D8C77091" }, - { name = "trie_again", version = "1.1.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "trie_again", source = "hex", outer_checksum = "365FE609649F3A098D1D7FC7EA5222EE422F0B3745587BF2AB03352357CA70BB" }, + { name = "trie_again", version = "1.1.4", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "trie_again", source = "hex", outer_checksum = "E3BD66B4E126EF567EA8C4944EAB216413392ADF6C16C36047AF79EE5EF13466" }, { name = "yamerl", version = "0.10.0", build_tools = ["rebar3"], requirements = [], otp_app = "yamerl", source = "hex", outer_checksum = "346ADB2963F1051DC837A2364E4ACF6EB7D80097C0F53CBDC3046EC8EC4B4E6E" }, ] From 1bcaef27cc92f126a714c331b0336795e9f20ae4 Mon Sep 17 00:00:00 2001 From: bwireman Date: Sat, 27 Sep 2025 12:21:36 -0500 Subject: [PATCH 3/4] implicit assert first pass --- example/src/example.gleam | 5 +++++ src/testament/internal/parse.gleam | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/example/src/example.gleam b/example/src/example.gleam index 99f14b3..6f4fedf 100644 --- a/example/src/example.gleam +++ b/example/src/example.gleam @@ -15,6 +15,11 @@ import gleam/option ///: ///: assert y == {x * 2} + 1 /// ``` +/// with implicit assert +/// ``` +///: example.add(1, 2) +///:: 3 +/// ``` pub fn add(a: Int, b: Int) -> Int { a + b } diff --git a/src/testament/internal/parse.gleam b/src/testament/internal/parse.gleam index eabd5ce..854055f 100644 --- a/src/testament/internal/parse.gleam +++ b/src/testament/internal/parse.gleam @@ -116,12 +116,35 @@ pub fn split_imports_and_code( } } +fn prep_implicit_assert( + state: DocState, + lines: List(token.Token), + expected_val: CodeBlock, +) { + let assert #([token.CommentDoc(":" <> prev)], rest) = list.split(lines, 1) + as "improper use of ::" + + let prev = token.CommentDoc(": let fixme =" <> prev) + + let line = token.CommentDoc(": assert fixme == " <> expected_val) + + DocState(..state, in: True, lines: [line, prev, ..rest]) +} + pub fn fold_doc_state(state: DocState, line: token.Token) -> DocState { case state, line { + DocState(False, lines, _), token.CommentDoc("::" <> expected_val) + | DocState(False, lines, _), token.CommentModule("::" <> expected_val) + -> prep_implicit_assert(state, lines, expected_val) + DocState(False, lines, _), token.CommentDoc(":" <> _) | DocState(False, lines, _), token.CommentModule(":" <> _) -> DocState(..state, in: True, lines: [line, ..lines]) + DocState(True, lines, _), token.CommentDoc("::" <> expected_val) + | DocState(True, lines, _), token.CommentModule("::" <> expected_val) + -> prep_implicit_assert(state, lines, expected_val) + DocState(True, lines, _), token.CommentDoc(":" <> _) | DocState(True, lines, _), token.CommentModule(":" <> _) -> DocState(..state, lines: [line, ..lines]) From b631be975234652a95a12478c4f5c3efbb2ac470 Mon Sep 17 00:00:00 2001 From: bwireman Date: Sat, 27 Sep 2025 12:53:56 -0500 Subject: [PATCH 4/4] assign name --- example/src/example.gleam | 4 ++ src/testament/internal/parse.gleam | 64 ++++++++++++++++++++++++------ test/parse_test.gleam | 43 +++++++++++--------- 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/example/src/example.gleam b/example/src/example.gleam index 6f4fedf..c3eed2b 100644 --- a/example/src/example.gleam +++ b/example/src/example.gleam @@ -19,6 +19,8 @@ import gleam/option /// ``` ///: example.add(1, 2) ///:: 3 +///: example.add(3, 2) +///:: 5 /// ``` pub fn add(a: Int, b: Int) -> Int { a + b @@ -39,6 +41,8 @@ pub type SuperInt { ///: let x = example.super_add(SuperInt(1), SuperInt(2)) ///: assert x == Some(SuperInt(3)) ///: assert example.super_add(SuperInt(-10), SuperInt(1)) == None +///: example.super_add(SuperInt(1), SuperInt(1)) +///:: Some(SuperInt(2)) pub fn super_add(a: SuperInt, b: SuperInt) -> option.Option(SuperInt) { let sum = a.v + b.v case sum > 0 { diff --git a/src/testament/internal/parse.gleam b/src/testament/internal/parse.gleam index 854055f..21b91ff 100644 --- a/src/testament/internal/parse.gleam +++ b/src/testament/internal/parse.gleam @@ -74,7 +74,7 @@ pub fn get_doc_tests_imports_and_code(code: String) -> ImportsAndCode { } fn collect_test_lines(tokens: List(token.Token)) -> List(List(token.Token)) { - let state = list.fold(tokens, DocState(False, [], []), fold_doc_state) + let state = list.fold(tokens, DocState(False, [], [], 0), fold_doc_state) case state.lines { [] -> state.test_bodies @@ -103,6 +103,7 @@ pub type DocState { in: Bool, lines: List(token.Token), test_bodies: List(List(token.Token)), + implicit_asserts: Int, ) } @@ -116,44 +117,81 @@ pub fn split_imports_and_code( } } +const letters = [ + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", +] + fn prep_implicit_assert( state: DocState, lines: List(token.Token), expected_val: CodeBlock, ) { + let assert [v] = list.sample(letters, 1) as "failed to create implicit_assert" + let name = string.repeat(v, state.implicit_asserts + 1) + let assert #([token.CommentDoc(":" <> prev)], rest) = list.split(lines, 1) as "improper use of ::" - let prev = token.CommentDoc(": let fixme =" <> prev) + let prev = token.CommentDoc(": let " <> name <> " =" <> prev) - let line = token.CommentDoc(": assert fixme == " <> expected_val) + let line = token.CommentDoc(": assert " <> name <> " == " <> expected_val) - DocState(..state, in: True, lines: [line, prev, ..rest]) + DocState( + ..state, + in: True, + lines: [line, prev, ..rest], + implicit_asserts: state.implicit_asserts + 1, + ) } pub fn fold_doc_state(state: DocState, line: token.Token) -> DocState { case state, line { - DocState(False, lines, _), token.CommentDoc("::" <> expected_val) - | DocState(False, lines, _), token.CommentModule("::" <> expected_val) + DocState(False, lines, _, _), token.CommentDoc("::" <> expected_val) + | DocState(False, lines, _, _), token.CommentModule("::" <> expected_val) -> prep_implicit_assert(state, lines, expected_val) - DocState(False, lines, _), token.CommentDoc(":" <> _) - | DocState(False, lines, _), token.CommentModule(":" <> _) + DocState(False, lines, _, _), token.CommentDoc(":" <> _) + | DocState(False, lines, _, _), token.CommentModule(":" <> _) -> DocState(..state, in: True, lines: [line, ..lines]) - DocState(True, lines, _), token.CommentDoc("::" <> expected_val) - | DocState(True, lines, _), token.CommentModule("::" <> expected_val) + DocState(True, lines, _, _), token.CommentDoc("::" <> expected_val) + | DocState(True, lines, _, _), token.CommentModule("::" <> expected_val) -> prep_implicit_assert(state, lines, expected_val) - DocState(True, lines, _), token.CommentDoc(":" <> _) - | DocState(True, lines, _), token.CommentModule(":" <> _) + DocState(True, lines, _, _), token.CommentDoc(":" <> _) + | DocState(True, lines, _, _), token.CommentModule(":" <> _) -> DocState(..state, lines: [line, ..lines]) - DocState(True, lines, bodies), _ -> + DocState(True, lines, bodies, implicit_asserts), _ -> DocState( in: False, lines: [], test_bodies: list.prepend(bodies, list.reverse(lines)), + implicit_asserts: implicit_asserts, ) _, _ -> state diff --git a/test/parse_test.gleam b/test/parse_test.gleam index fd7198f..dbf129c 100644 --- a/test/parse_test.gleam +++ b/test/parse_test.gleam @@ -58,43 +58,48 @@ pub fn is_doctest_line_test() { } pub fn fold_doc_state_test() { - assert parse.DocState(False, [], []) + assert parse.DocState(False, [], [], 0) |> parse.fold_doc_state(token.String(": ")) - == parse.DocState(False, [], []) + == parse.DocState(False, [], [], 0) - assert parse.DocState(False, [], []) + assert parse.DocState(False, [], [], 0) |> parse.fold_doc_state(token.CommentDoc(": ")) - == parse.DocState(True, [token.CommentDoc(": ")], []) + == parse.DocState(True, [token.CommentDoc(": ")], [], 0) - assert parse.DocState(False, [], []) + assert parse.DocState(False, [], [], 0) |> parse.fold_doc_state(token.CommentModule(": ")) - == parse.DocState(True, [token.CommentModule(": ")], []) + == parse.DocState(True, [token.CommentModule(": ")], [], 0) - assert parse.DocState(True, [], []) + assert parse.DocState(True, [], [], 0) |> parse.fold_doc_state(token.CommentDoc(": ")) - == parse.DocState(True, [token.CommentDoc(": ")], []) + == parse.DocState(True, [token.CommentDoc(": ")], [], 0) - assert parse.DocState(True, [], []) + assert parse.DocState(True, [], [], 0) |> parse.fold_doc_state(token.CommentModule(": ")) - == parse.DocState(True, [token.CommentModule(": ")], []) + == parse.DocState(True, [token.CommentModule(": ")], [], 0) - assert parse.DocState(True, [token.CommentModule(": let x = 2 + 2")], []) + assert parse.DocState(True, [token.CommentModule(": let x = 2 + 2")], [], 0) |> parse.fold_doc_state(token.CommentModule(": assert x == 4")) |> parse.fold_doc_state(token.CommentModule("pub fn x")) - == parse.DocState(False, [], [ + == parse.DocState( + False, + [], [ - token.CommentModule(": let x = 2 + 2"), - token.CommentModule(": assert x == 4"), + [ + token.CommentModule(": let x = 2 + 2"), + token.CommentModule(": assert x == 4"), + ], ], - ]) + 0, + ) - assert parse.DocState(True, [], []) + assert parse.DocState(True, [], [], 0) |> parse.fold_doc_state(token.CommentDoc(" ")) - == parse.DocState(False, [], [[]]) + == parse.DocState(False, [], [[]], 0) - assert parse.DocState(True, [], []) + assert parse.DocState(True, [], [], 0) |> parse.fold_doc_state(token.CommentModule(" ")) - == parse.DocState(False, [], [[]]) + == parse.DocState(False, [], [[]], 0) } pub fn split_imports_and_code_test() {