Skip to content

Commit 7440637

Browse files
v0.17~preview.129.11+135
1 parent b312070 commit 7440637

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1389
-1205
lines changed

runtime/expectation.ml

Lines changed: 174 additions & 145 deletions
Large diffs are not rendered by default.

runtime/expectation_intf.ml

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -49,42 +49,38 @@ module Definitions = struct
4949
end
5050

5151
module Behavior = struct
52-
(** A [('output, 'behavior_type) behavior] describes how to handle a test node when
53-
running tests and writing corrections.
54-
55-
['output] determines the type of payload used when running tests and writing
56-
corrections at that node; it is [Payload.String.t] for [expect_exact] nodes and
57-
[Payload.Pretty.t] for all other nodes.
52+
(** A ['behavior_type t] describes how to handle a test node when running tests
53+
and writing corrections.
5854
5955
['behavior_type] determines the types of rewrites that are possible at this node.
6056
It is either [`Expect] (indicating that both corrections for unexpected output and
6157
rewrites for unreachability are possible) or [`Unreachable] (indicating that only
6258
corrections for unexpected output are possible).
6359
*)
64-
type (_, _) t =
60+
type _ t =
6561
| Expect :
66-
{ payload : 'output Payload.t
62+
{ payload : Output.Payload.t
6763
; on_unreachable : On_unreachable.t
6864
; reachability : Expect_reachability.t
6965
}
70-
-> ('output, [ `Expect ]) t
66+
-> [ `Expect ] t
7167
| Unreachable :
7268
{ reachability_of_corrected : Expect_reachability.t
7369
(** The reachability of the node inserted if this unreachable node is
7470
unexpectedly reached *)
7571
}
76-
-> (Payload.Pretty.Contents.t, [ `Unreachable ]) t
72+
-> [ `Unreachable ] t
7773
end
7874

79-
(** A [('output, 'behavior_type) t] carries information about how to run tests for a
75+
(** A [('behavior_type) t] carries information about how to run tests for a
8076
specific expect node and rewrite it in the source file if there are corrections. The
81-
['output] and ['behavior_type] type variables have the same meanings as in
82-
[('output, 'behavior_type) behavior].
77+
['behavior_type] type variable has the same meanings as in
78+
['behavior_type Behavior.t].
8379
*)
84-
type ('output, 'behavior_type) t =
80+
type 'behavior_type t =
8581
{ position : Insert_loc.t
86-
; behavior : ('output, 'behavior_type) Behavior.t
87-
; payload_type : (module Payload.Type with type Contents.t = 'output)
82+
; behavior : 'behavior_type Behavior.t
83+
; payload_type : Output.Type.t
8884
; on_incorrect_output : String_node_format.Shape.t
8985
(** The name and syntax style of the extension point or attribute used to write
9086
corrections when receiving "incorrect" output for this test node. For each [t],
@@ -111,66 +107,57 @@ module type Expectation = sig
111107
include Insert_loc
112108
end
113109

114-
val loc : t -> Compact_loc.t
110+
val loc : Insert_loc.t -> Compact_loc.t
115111
end
116112

117-
val with_behavior
118-
: ('output, 'old_behavior) t
119-
-> ('output, 'new_behavior) Behavior.t
120-
-> ('output, 'new_behavior) t
113+
val with_behavior : 'old_behavior t -> 'new_behavior Behavior.t -> 'new_behavior t
121114

122115
(** [formatter ~expect_node_formatting t] returns the [Output.Formatter.t] that formats
123116
test output according to the type ([exact] or [pretty]) of [t], using information
124117
about the location and payload of [t] for formatting. *)
125118
val formatter
126119
: expect_node_formatting:Expect_node_formatting.t
127-
-> (_, _) t
120+
-> _ t
128121
-> Output.Formatter.t
129122

130-
val loc : _ t -> Compact_loc.t
131-
132123
(** [[%expect _]] *)
133124
val expect
134-
: payload_loc:Compact_loc.t option
135-
-> string Payload.t
136-
-> Compact_loc.t
137-
-> (Payload.Pretty.Contents.t, [ `Expect ]) t
125+
: formatting_flexibility:Expect_node_formatting.Flexibility.t
126+
-> node_loc:Compact_loc.t
127+
-> located_payload:(Output.Payload.t * Compact_loc.t) option
128+
-> [ `Expect ] t
138129

139130
(** [[%expect_exact _]] *)
140131
val expect_exact
141-
: payload_loc:Compact_loc.t option
142-
-> string Payload.t
143-
-> Compact_loc.t
144-
-> (Payload.Exact.Contents.t, [ `Expect ]) t
132+
: formatting_flexibility:Expect_node_formatting.Flexibility.t
133+
-> node_loc:Compact_loc.t
134+
-> located_payload:(Output.Payload.t * Compact_loc.t) option
135+
-> [ `Expect ] t
145136

146137
(** [[%expect.unreachable]] *)
147-
val expect_unreachable
148-
: Compact_loc.t
149-
-> (Payload.Pretty.Contents.t, [ `Unreachable ]) t
138+
val expect_unreachable : node_loc:Compact_loc.t -> [ `Unreachable ] t
150139

151140
(** [[@@expect.uncaught_exn _]] *)
152141
val expect_uncaught_exn
153-
: payload_loc:Compact_loc.t option
154-
-> string Payload.t
155-
-> Compact_loc.t
156-
-> (Payload.Pretty.Contents.t, [ `Expect ]) t
142+
: formatting_flexibility:Expect_node_formatting.Flexibility.t
143+
-> node_loc:Compact_loc.t
144+
-> located_payload:(Output.Payload.t * Compact_loc.t) option
145+
-> [ `Expect ] t
157146

158147
(** Runtime representation of the implicit [[%expect {||}]] at the end of every expect
159148
test. *)
160-
val expect_trailing : Virtual_loc.t -> (Payload.Pretty.Contents.t, [ `Expect ]) t
149+
val expect_trailing : insert_loc:Virtual_loc.t -> [ `Expect ] t
161150

162151
(** Runtime representation of the assertion that a test does not produce uncaught
163152
exceptions, which a user implicitly makes by omitting an [[@@expect.uncaught_exn _]]
164153
attribute. *)
165-
val expect_no_uncaught_exn
166-
: Virtual_loc.t
167-
-> (Payload.Pretty.Contents.t, [ `Unreachable ]) t
154+
val expect_no_uncaught_exn : insert_loc:Virtual_loc.t -> [ `Unreachable ] t
168155

169156
module For_apply_style : sig
170157
type format_payload :=
171158
expect_node_formatting:Expect_node_formatting.t
172159
-> payload_loc:Compact_loc.t
173-
-> loc:Compact_loc.t
160+
-> node_loc:Compact_loc.t
174161
-> String_node_format.Delimiter.t
175162
-> string
176163
-> string option

runtime/output.ml

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ module Payload = struct
4545
}
4646

4747
let default contents = { contents; tag = String_node_format.Delimiter.default }
48+
49+
let to_source_code_string { contents; tag } =
50+
let escape_lines test_output =
51+
test_output
52+
|> String.split ~on:'\n'
53+
|> List.map ~f:String.escaped
54+
|> String.concat ~sep:"\n"
55+
in
56+
match tag with
57+
| T (Tag tag) -> Printf.sprintf "{%s|%s|%s}" tag contents tag
58+
| T Quote -> Printf.sprintf {|"%s"|} (escape_lines contents)
59+
;;
4860
end
4961

5062
let reconcile ~expected_output ~test_output : Test_result.t =
@@ -53,58 +65,57 @@ let reconcile ~expected_output ~test_output : Test_result.t =
5365

5466
let fail error_output : Test_result.t = Fail error_output
5567

68+
let fix_delimiter_conflicts
69+
(type handedness)
70+
~contents
71+
~(delimiter : handedness String_node_format.Delimiter.unpacked)
72+
: handedness String_node_format.Delimiter.unpacked
73+
=
74+
let rec fix_tag_conflicts ~contents ~tag =
75+
let tag_conflicts_with fstr =
76+
String.is_substring ~substring:(Printf.sprintf fstr tag) contents
77+
in
78+
if tag_conflicts_with "{%s|" || tag_conflicts_with "|%s}"
79+
then fix_tag_conflicts ~contents ~tag:(tag ^ "xxx")
80+
else tag
81+
in
82+
match delimiter with
83+
| Quote -> Quote
84+
| Tag tag -> Tag (fix_tag_conflicts ~contents ~tag)
85+
;;
86+
87+
let to_formatted_payload ~tag:(T delimiter : String_node_format.Delimiter.t) contents
88+
: Payload.t
89+
=
90+
{ contents; tag = T (fix_delimiter_conflicts ~contents ~delimiter) }
91+
;;
92+
5693
let to_source_code_string
5794
~(expect_node_formatting : Expect_node_formatting.t)
58-
~(node_shape : String_node_format.Shape.t option)
95+
~node_shape:(T shape : String_node_format.Shape.t)
5996
~(tag : String_node_format.Delimiter.t)
6097
contents
6198
=
62-
let rec fix_tag_conflicts test_output tag =
63-
let bad_tag tag fstr =
64-
String.is_substring ~substring:(Printf.sprintf fstr tag) test_output
65-
in
66-
if bad_tag tag "{%s|" || bad_tag tag "|%s}"
67-
then fix_tag_conflicts test_output (tag ^ "xxx")
68-
else tag
69-
in
70-
let escape_lines test_output =
71-
test_output
72-
|> String.split ~on:'\n'
73-
|> List.map ~f:String.escaped
74-
|> String.concat ~sep:"\n"
99+
let delimiter =
100+
fix_delimiter_conflicts
101+
~contents
102+
~delimiter:(String_node_format.Delimiter.handed tag shape.hand)
75103
in
76-
let tag, extension =
77-
match node_shape with
78-
| None -> tag, None
79-
| Some (T shape) ->
80-
let delimiter = String_node_format.Delimiter.handed tag shape.hand in
81-
T delimiter, Some (String_node_format.T { shape; delimiter })
82-
in
83-
let payload_string =
84-
lazy
85-
(match tag with
86-
| T (Tag tag) ->
87-
let tag = fix_tag_conflicts contents tag in
88-
Printf.sprintf "{%s|%s|%s}" tag contents tag
89-
| T Quote -> Printf.sprintf {|"%s"|} (escape_lines contents))
90-
in
91-
match extension with
92-
| None -> force payload_string
93-
| Some (T { shape; delimiter }) ->
94-
(match shape.hand with
95-
| Longhand ->
96-
let prefix =
97-
match shape.kind with
98-
| Extension -> expect_node_formatting.extension_sigil
99-
| Attribute -> expect_node_formatting.attribute_sigil
100-
in
101-
Printf.sprintf "[%s%s %s]" prefix shape.name (force payload_string)
102-
| Shorthand ->
103-
let prefix =
104-
match shape.kind with
105-
| Extension -> expect_node_formatting.extension_sigil
106-
in
107-
(match delimiter with
108-
| Tag "" -> Printf.sprintf "{%s%s|%s|}" prefix shape.name contents
109-
| Tag tag -> Printf.sprintf "{%s%s %s|%s|%s}" prefix shape.name tag contents tag))
104+
let payload : Payload.t = { contents; tag = T delimiter } in
105+
match shape.hand with
106+
| Longhand ->
107+
let prefix =
108+
match shape.kind with
109+
| Extension -> expect_node_formatting.extension_sigil
110+
| Attribute -> expect_node_formatting.attribute_sigil
111+
in
112+
Printf.sprintf "[%s%s %s]" prefix shape.name (Payload.to_source_code_string payload)
113+
| Shorthand ->
114+
let prefix =
115+
match shape.kind with
116+
| Extension -> expect_node_formatting.extension_sigil
117+
in
118+
(match delimiter with
119+
| Tag "" -> Printf.sprintf "{%s%s|%s|}" prefix shape.name contents
120+
| Tag tag -> Printf.sprintf "{%s%s %s|%s|%s}" prefix shape.name tag contents tag)
110121
;;

runtime/output.mli

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ module Payload : sig
5555

5656
(** Add the default tags to a payload. *)
5757
val default : string -> t
58+
59+
(** The source-code representation of a payload. *)
60+
val to_source_code_string : t -> string
5861
end
5962

6063
(** Returns [Pass] if [test_output] is considered to match [expected_output]; otherwise
@@ -66,15 +69,23 @@ val reconcile : expected_output:string -> test_output:Formatted.t -> Test_result
6669
"reconciled" output. *)
6770
val fail : Formatted.t -> Test_result.t
6871

69-
(** The source-code representation of a payload.
72+
(** The new payload represented by a reconciled expectation.
73+
74+
If [tag] is not compatible with the new payload contents (for example, the tag
75+
represents a [{x| delimited string |x}] and the new contents contain ["|x}"]), the tag
76+
is adjusted so the resulting payload can be parsed.
77+
*)
78+
val to_formatted_payload : tag:String_node_format.Delimiter.t -> Reconciled.t -> Payload.t
79+
80+
(** The source-code representation of a reconciled expect node.
7081
71-
If [node_shape] is [Some shape], then the produced string is an extension point or
72-
attribute containing a payload with the reconciled contents, using the name and syntax
73-
specified in [shape]. If [node_shape] is [None], the produced string is a string
74-
literal. *)
82+
If [tag] is not compatible with the new payload contents (for example, the tag
83+
represents a [{x| delimited string |x}] and the new contents contain ["|x}"]), the tag
84+
is adjusted so the resulting payload can be parsed.
85+
*)
7586
val to_source_code_string
7687
: expect_node_formatting:Expect_node_formatting.t
77-
-> node_shape:String_node_format.Shape.t option
88+
-> node_shape:String_node_format.Shape.t
7889
-> tag:String_node_format.Delimiter.t
7990
-> Reconciled.t
8091
-> string

0 commit comments

Comments
 (0)