this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Decode panics

+402 -4
+2 -2
gleam.toml
··· 4 4 description = "Gleam bindings to Erlang's EUnit test framework" 5 5 repository = { type = "github", user = "lpil", repo = "gleeunit" } 6 6 links = [{ title = "Sponsor", href = "https://github.com/sponsors/lpil" }] 7 - gleam = ">= 0.33.0" 7 + gleam = ">= 1.11.0" 8 8 9 9 [javascript.deno] 10 10 allow_read = ["gleam.toml", "test", "build"] 11 11 12 12 [dependencies] 13 - gleam_stdlib = ">= 0.33.0 and < 2.0.0" 13 + gleam_stdlib = ">= 0.60.0 and < 2.0.0"
+2 -2
manifest.toml
··· 2 2 # You typically do not need to edit this file 3 3 4 4 packages = [ 5 - { name = "gleam_stdlib", version = "0.38.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "663CF11861179AF415A625307447775C09404E752FF99A24E2057C835319F1BE" }, 5 + { name = "gleam_stdlib", version = "0.60.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "621D600BB134BC239CB2537630899817B1A42E60A1D46C5E9F3FAE39F88C800B" }, 6 6 ] 7 7 8 8 [requirements] 9 - gleam_stdlib = { version = ">= 0.33.0 and < 2.0.0" } 9 + gleam_stdlib = { version = ">= 0.60.0 and < 2.0.0" }
+52
src/gleeunit/internal/gleam_panic.gleam
··· 1 + import gleam/dynamic 2 + 3 + pub type GleamPanic { 4 + GleamPanic( 5 + module: String, 6 + function: String, 7 + line: Int, 8 + message: String, 9 + kind: PanicKind, 10 + ) 11 + } 12 + 13 + pub type PanicKind { 14 + Todo 15 + Panic 16 + LetAssert( 17 + start: Int, 18 + pattern_start: Int, 19 + pattern_end: Int, 20 + value: dynamic.Dynamic, 21 + ) 22 + Assert( 23 + start: Int, 24 + expression_start: Int, 25 + expression_end: Int, 26 + kind: AssertKind, 27 + ) 28 + } 29 + 30 + pub type AssertKind { 31 + BinaryOperator( 32 + operator: String, 33 + left: AssertedExpression, 34 + right: AssertedExpression, 35 + ) 36 + FunctionCall(arguments: List(AssertedExpression)) 37 + OtherExpression(expression: AssertedExpression) 38 + } 39 + 40 + pub type AssertedExpression { 41 + AssertedExpression(start: Int, end: Int, kind: ExpressionKind) 42 + } 43 + 44 + pub type ExpressionKind { 45 + Literal(value: dynamic.Dynamic) 46 + Expression(value: dynamic.Dynamic) 47 + Unevaluated 48 + } 49 + 50 + @external(erlang, "gleam_panic_ffi", "from_dynamic") 51 + @external(javascript, "./gleam_panic_ffi.mjs", "from_dynamic") 52 + pub fn from_dynamic(data: dynamic.Dynamic) -> Result(GleamPanic, Nil)
+47
src/gleeunit/internal/gleam_panic_ffi.erl
··· 1 + -module(gleam_panic_ffi). 2 + -export([from_dynamic/1]). 3 + 4 + from_dynamic(#{ 5 + gleam_error := assert, 6 + start := Start, 7 + expression_start := EStart, 8 + expression_end := EEnd 9 + } = E) -> 10 + wrap(E, {assert, Start, EStart, EEnd, assert_kind(E)}); 11 + from_dynamic(#{ 12 + gleam_error := let_assert, 13 + start := Start, 14 + pattern_start := PStart, 15 + pattern_end := PEnd, 16 + value := Value 17 + } = E) -> 18 + wrap(E, {let_assert, Start, PStart, PEnd, Value}); 19 + from_dynamic(#{gleam_error := panic} = E) -> 20 + wrap(E, panic); 21 + from_dynamic(#{gleam_error := todo} = E) -> 22 + wrap(E, todo); 23 + from_dynamic(_) -> 24 + {error, nil}. 25 + 26 + assert_kind(#{kind := binary_operator, left := L, right := R, operator := O}) -> 27 + {binary_operator, atom_to_binary(O), expression(L), expression(R)}; 28 + assert_kind(#{kind := function_call, arguments := Arguments}) -> 29 + {function_call, lists:map(fun expression/1, Arguments)}; 30 + assert_kind(#{kind := expression, expression := Expression}) -> 31 + {other_expression, expression(Expression)}. 32 + 33 + expression(#{start := S, 'end' := E, kind := literal, value := Value}) -> 34 + {asserted_expression, S, E, {literal, Value}}; 35 + expression(#{start := S, 'end' := E, kind := expression, value := Value}) -> 36 + {asserted_expression, S, E, {expression, Value}}; 37 + expression(#{start := S, 'end' := E, kind := unevaluated}) -> 38 + {asserted_expression, S, E, unevaluated}. 39 + 40 + wrap(#{ 41 + gleam_error := _, 42 + module := Module, 43 + function := Function, 44 + line := Line, 45 + message := Message 46 + }, Kind) -> 47 + {ok, {gleam_panic, Module, Function, Line, Message, Kind}}.
+88
src/gleeunit/internal/gleam_panic_ffi.mjs
··· 1 + import { Ok, Error, Empty, NonEmpty } from "../../gleam.mjs"; 2 + import { 3 + GleamPanic, 4 + Todo, 5 + Panic, 6 + LetAssert, 7 + Assert, 8 + BinaryOperator, 9 + FunctionCall, 10 + OtherExpression, 11 + AssertedExpression, 12 + Literal, 13 + Expression, 14 + Unevaluated, 15 + } from "./gleam_panic.mjs"; 16 + 17 + export function from_dynamic(error) { 18 + if (!(error instanceof globalThis.Error) || !error.gleam_error) { 19 + return new Error(undefined); 20 + } 21 + 22 + if (error.gleam_error === "todo") { 23 + return wrap(error, new Todo()); 24 + } 25 + 26 + if (error.gleam_error === "panic") { 27 + return wrap(error, new Panic()); 28 + } 29 + 30 + if (error.gleam_error === "let_assert") { 31 + let kind = new LetAssert( 32 + error.start, 33 + error.pattern_start, 34 + error.pattern_end, 35 + error.value, 36 + ); 37 + return wrap(error, kind); 38 + } 39 + 40 + if (error.gleam_error === "assert") { 41 + let kind = new Assert( 42 + error.start, 43 + error.expression_start, 44 + error.expression_end, 45 + assert_kind(error), 46 + ); 47 + return wrap(error, kind); 48 + } 49 + 50 + return new Error(undefined); 51 + } 52 + 53 + function assert_kind(error) { 54 + if (error.kind == "binary_operator") { 55 + return new BinaryOperator( 56 + error.operator, 57 + expression(error.left), 58 + expression(error.right), 59 + ); 60 + } 61 + 62 + if (error.kind == "function_call") { 63 + let list = new Empty(); 64 + let i = error.arguments.length; 65 + while (i--) { 66 + list = new NonEmpty(expression(error.arguments[i]), list); 67 + } 68 + return new FunctionCall(list); 69 + } 70 + 71 + return new OtherExpression(expression(error.expression)); 72 + } 73 + 74 + function expression(data) { 75 + const expression = new AssertedExpression(data.start, data.end, undefined); 76 + if (data.kind == "literal") { 77 + expression.kind = new Literal(data.value); 78 + } else if (data.kind == "expression") { 79 + expression.kind = new Expression(data.value); 80 + } else { 81 + expression.kind = new Unevaluated(); 82 + } 83 + return expression; 84 + } 85 + 86 + function wrap(e, kind) { 87 + return new Ok(new GleamPanic(e.module, e.function, e.line, e.message, kind)); 88 + }
+193
test/gleam_panics_test.gleam
··· 1 + import gleam/dynamic 2 + import gleam/function 3 + import gleeunit/internal/gleam_panic.{ 4 + Assert, BinaryOperator, Expression, FunctionCall, LetAssert, Literal, 5 + OtherExpression, Panic, Todo, Unevaluated, 6 + } 7 + 8 + @external(erlang, "gleeunit_test_ffi", "rescue") 9 + @external(javascript, "./gleeunit_test_ffi.mjs", "rescue") 10 + fn rescue(f: fn() -> t) -> Result(t, dynamic.Dynamic) 11 + 12 + pub fn panic_test() { 13 + let assert Error(e) = rescue(fn() { panic }) 14 + let assert Ok(e) = gleam_panic.from_dynamic(e) 15 + assert e.kind == Panic 16 + assert e.function == "panic_test" 17 + assert e.module == "gleam_panics_test" 18 + assert e.line > 1 19 + assert e.message == "`panic` expression evaluated." 20 + } 21 + 22 + pub fn panic_message_test() { 23 + let assert Error(e) = rescue(fn() { panic as "oh my!" }) 24 + let assert Ok(e) = gleam_panic.from_dynamic(e) 25 + assert e.kind == Panic 26 + assert e.function == "panic_message_test" 27 + assert e.module == "gleam_panics_test" 28 + assert e.line > 1 29 + assert e.message == "oh my!" 30 + } 31 + 32 + pub fn todo_test() { 33 + let assert Error(e) = rescue(fn() { todo }) 34 + let assert Ok(e) = gleam_panic.from_dynamic(e) 35 + assert e.kind == Todo 36 + assert e.function == "todo_test" 37 + assert e.module == "gleam_panics_test" 38 + assert e.line > 1 39 + assert e.message 40 + == "`todo` expression evaluated. This code has not yet been implemented." 41 + } 42 + 43 + pub fn todo_message_test() { 44 + let assert Error(e) = rescue(fn() { todo as "oh my!" }) 45 + let assert Ok(e) = gleam_panic.from_dynamic(e) 46 + assert e.kind == Todo 47 + assert e.function == "todo_message_test" 48 + assert e.module == "gleam_panics_test" 49 + assert e.line > 1 50 + assert e.message == "oh my!" 51 + } 52 + 53 + pub fn let_assert_test() { 54 + let assert Error(e) = 55 + rescue(fn() { 56 + let assert 0 = function.identity(123) 57 + }) 58 + let assert Ok(e) = gleam_panic.from_dynamic(e) 59 + assert e.function == "let_assert_test" 60 + assert e.module == "gleam_panics_test" 61 + assert e.line > 1 62 + assert e.message == "Pattern match failed, no pattern matched the value." 63 + let assert LetAssert(value:, start:, pattern_start:, pattern_end:) = e.kind 64 + assert value == dynamic.int(123) 65 + assert start > 1 66 + assert pattern_start == start + 11 67 + assert pattern_end == pattern_start + 1 68 + } 69 + 70 + pub fn let_assert_message_test() { 71 + let assert Error(e) = 72 + rescue(fn() { 73 + let assert 0 = function.identity(321) as "oh dear" 74 + }) 75 + let assert Ok(e) = gleam_panic.from_dynamic(e) 76 + assert e.function == "let_assert_message_test" 77 + assert e.module == "gleam_panics_test" 78 + assert e.line > 1 79 + assert e.message == "oh dear" 80 + let assert LetAssert(value:, start:, pattern_start:, pattern_end:) = e.kind 81 + assert value == dynamic.int(321) 82 + assert start > 1 83 + assert pattern_start == start + 11 84 + assert pattern_end == pattern_start + 1 85 + } 86 + 87 + pub fn assert_expression_test() { 88 + let assert Error(e) = 89 + rescue(fn() { 90 + let x = function.identity(False) 91 + assert x 92 + }) 93 + let assert Ok(e) = gleam_panic.from_dynamic(e) 94 + assert e.function == "assert_expression_test" 95 + assert e.module == "gleam_panics_test" 96 + assert e.line > 1 97 + assert e.message == "Assertion failed." 98 + let assert Assert(start:, expression_start:, expression_end:, kind:) = e.kind 99 + assert start > 1 100 + assert expression_start == start + 7 101 + assert expression_end == expression_start + 1 102 + let assert OtherExpression(expression:) = kind 103 + assert expression.start == expression_start 104 + assert expression.end == expression_end 105 + assert expression.kind == Expression(value: dynamic.bool(False)) 106 + } 107 + 108 + pub fn assert_expression_message_test() { 109 + let assert Error(e) = 110 + rescue(fn() { 111 + let x = function.identity(False) 112 + assert x as "maybe?" 113 + }) 114 + let assert Ok(e) = gleam_panic.from_dynamic(e) 115 + assert e.function == "assert_expression_message_test" 116 + assert e.module == "gleam_panics_test" 117 + assert e.line > 1 118 + assert e.message == "maybe?" 119 + let assert Assert(start:, expression_start:, expression_end:, kind:) = e.kind 120 + assert start > 1 121 + assert expression_start == start + 7 122 + assert expression_end == expression_start + 1 123 + let assert OtherExpression(expression:) = kind 124 + assert expression.start == expression_start 125 + assert expression.end == expression_end 126 + assert expression.kind == Expression(value: dynamic.bool(False)) 127 + } 128 + 129 + pub fn assert_function_test() { 130 + let assert Error(e) = 131 + rescue(fn() { 132 + assert function.identity(False) 133 + }) 134 + let assert Ok(e) = gleam_panic.from_dynamic(e) 135 + assert e.function == "assert_function_test" 136 + assert e.module == "gleam_panics_test" 137 + assert e.line > 1 138 + assert e.message == "Assertion failed." 139 + let assert Assert(start:, expression_start:, expression_end:, kind:) = e.kind 140 + assert start > 1 141 + assert expression_start == start + 7 142 + assert expression_end == expression_start + 24 143 + let assert FunctionCall(arguments: [expression]) = kind 144 + assert expression.start == expression_start + 18 145 + assert expression.end == expression_end - 1 146 + assert expression.kind == Literal(value: dynamic.bool(False)) 147 + } 148 + 149 + pub fn assert_function_message_test() { 150 + let assert Error(e) = 151 + rescue(fn() { 152 + assert function.identity(False) as "oh!" 153 + }) 154 + let assert Ok(e) = gleam_panic.from_dynamic(e) 155 + assert e.function == "assert_function_message_test" 156 + assert e.module == "gleam_panics_test" 157 + assert e.line > 1 158 + assert e.message == "oh!" 159 + let assert Assert(start:, expression_start:, expression_end:, kind:) = e.kind 160 + assert start > 1 161 + assert expression_start == start + 7 162 + assert expression_end == expression_start + 24 163 + let assert FunctionCall(arguments: [expression]) = kind 164 + assert expression.start == expression_start + 18 165 + assert expression.end == expression_end - 1 166 + assert expression.kind == Literal(value: dynamic.bool(False)) 167 + } 168 + 169 + pub fn assert_binary_operator_test() { 170 + let assert Error(e) = 171 + rescue(fn() { 172 + let a = False 173 + assert a && function.identity(False) 174 + }) 175 + let assert Ok(e) = gleam_panic.from_dynamic(e) 176 + assert e.function == "assert_binary_operator_test" 177 + assert e.module == "gleam_panics_test" 178 + assert e.line > 1 179 + assert e.message == "Assertion failed." 180 + let assert Assert(start:, expression_start:, expression_end:, kind:) = e.kind 181 + assert start > 1 182 + assert expression_start == start + 7 183 + assert expression_end == expression_start + 29 184 + let assert BinaryOperator(operator:, left:, right:) = kind 185 + assert operator == "&&" 186 + assert left.start == expression_start 187 + assert left.end == left.start + 1 188 + assert left.kind == Expression(dynamic.bool(False)) 189 + assert right.start == left.end + 4 190 + assert right.end == right.start + 24 191 + assert right.end == expression_end 192 + assert right.kind == Unevaluated 193 + }
+9
test/gleeunit_test_ffi.erl
··· 1 + -module(gleeunit_test_ffi). 2 + -export([rescue/1]). 3 + 4 + rescue(F) -> 5 + try 6 + {ok, F()} 7 + catch 8 + _:Error:_ -> {error, Error} 9 + end.
+9
test/gleeunit_test_ffi.mjs
··· 1 + import { Ok, Error } from "./gleam.mjs"; 2 + 3 + export function rescue(f) { 4 + try { 5 + return new Ok(f()); 6 + } catch (e) { 7 + return new Error(e); 8 + } 9 + }