Skip to content

Commit e0f5ad5

Browse files
panglesdjonludlam
authored andcommitted
Reintroduce emptyness check in path components of references
1 parent dc3aeb8 commit e0f5ad5

File tree

4 files changed

+59
-43
lines changed

4 files changed

+59
-43
lines changed

src/model/reference.ml

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ type token = {
128128
location : Location_.span;
129129
}
130130

131-
type path_prefix = Path_prefix of string
131+
type path_prefix = Path_prefix of string * Location_.span
132132

133133
(* The string is scanned right-to-left, because we are interested in right-most
134134
hyphens. The tokens are also returned in right-to-left order, because the
@@ -207,7 +207,10 @@ let tokenize location s : token list * path_prefix option =
207207
let location = Location_.span [ location; identifier_location ] in
208208
(kind, location)
209209
and scan_path started_at tokens =
210-
(tokens, Some (Path_prefix (String.sub s 0 (started_at + 1))))
210+
let location =
211+
Location_.in_string s ~offset:0 ~length:(started_at + 1) location
212+
in
213+
(tokens, Some (Path_prefix (String.sub s 0 (started_at + 1), location)))
211214
in
212215

213216
scan_identifier (String.length s) 0 (String.length s - 1) []
@@ -221,15 +224,41 @@ let expected ?(expect_paths = false) allowed location =
221224
let allowed = List.map (Printf.sprintf "'%s-'") allowed @ unqualified in
222225
expected_err (pp_hum_comma_separated Format.pp_print_string) allowed location
223226

224-
let parse_path p =
227+
let parse_path whole_path_location p =
225228
let segs = String.split_on_char '/' p in
229+
let check segs start =
230+
let _finish =
231+
List.fold_left
232+
(fun offset seg ->
233+
match seg with
234+
| "" ->
235+
let location =
236+
Location_.in_string p ~offset ~length:0 whole_path_location
237+
in
238+
should_not_be_empty ~what:"Identifier in path reference" location
239+
|> Error.raise_exception
240+
| seg -> offset + String.length seg + 1)
241+
start segs
242+
in
243+
()
244+
in
226245
match segs with
227-
| "." :: segs -> (`TRelativePath, segs)
228-
| "" :: "" :: segs -> (`TCurrentPackage, segs)
229-
| "" :: segs -> (`TAbsolutePath, segs)
230-
| segs -> (`TRelativePath, segs)
231-
232-
let parse_path_prefix (Path_prefix p) identifier = parse_path (p ^ identifier)
246+
| "." :: segs ->
247+
check segs 2;
248+
(`TRelativePath, segs)
249+
| "" :: "" :: segs ->
250+
check segs 2;
251+
(`TCurrentPackage, segs)
252+
| "" :: segs ->
253+
check segs 1;
254+
(`TAbsolutePath, segs)
255+
| segs ->
256+
check segs 0;
257+
(`TRelativePath, segs)
258+
259+
let parse_path_prefix (Path_prefix (p, path_location)) identifier
260+
prefix_location =
261+
parse_path (Location_.span [ path_location; prefix_location ]) (p ^ identifier)
233262

234263
(* Parse references that do not contain a [/]. Raises errors and warnings. *)
235264
let parse whole_reference_location s :
@@ -255,7 +284,7 @@ let parse whole_reference_location s :
255284
| Some p -> (
256285
match kind with
257286
| `TUnknown | `TModule ->
258-
`Module_path (parse_path_prefix p identifier)
287+
`Module_path (parse_path_prefix p identifier location)
259288
| _ ->
260289
expected ~expect_paths:true [ "module" ] location
261290
|> Error.raise_exception))
@@ -287,7 +316,7 @@ let parse whole_reference_location s :
287316
| Some p -> (
288317
match kind with
289318
| `TUnknown | `TModule ->
290-
`Module_path (parse_path_prefix p identifier)
319+
`Module_path (parse_path_prefix p identifier location)
291320
| _ ->
292321
expected ~expect_paths:true [ "module" ] location
293322
|> Error.raise_exception))
@@ -335,20 +364,25 @@ let parse whole_reference_location s :
335364

336365
let label_parent_path kind path_prefix identifier location =
337366
match kind with
338-
| `TUnknown -> `Any_path (parse_path_prefix path_prefix identifier)
339-
| `TModule -> `Module_path (parse_path_prefix path_prefix identifier)
340-
| `TPage -> `Page_path (parse_path_prefix path_prefix identifier)
367+
| `TUnknown ->
368+
`Any_path (parse_path_prefix path_prefix identifier location)
369+
| `TModule ->
370+
`Module_path (parse_path_prefix path_prefix identifier location)
371+
| `TPage -> `Page_path (parse_path_prefix path_prefix identifier location)
341372
| _ ->
342373
expected ~expect_paths:true [ "module"; "page" ] location
343374
|> Error.raise_exception
344375
in
345376

346377
let any_path kind path_prefix identifier location =
347378
match kind with
348-
| `TUnknown -> `Any_path (parse_path_prefix path_prefix identifier)
349-
| `TModule -> `Module_path (parse_path_prefix path_prefix identifier)
350-
| `TPage -> `Page_path (parse_path_prefix path_prefix identifier)
351-
| `TAsset -> `Asset_path (parse_path_prefix path_prefix identifier)
379+
| `TUnknown ->
380+
`Any_path (parse_path_prefix path_prefix identifier location)
381+
| `TModule ->
382+
`Module_path (parse_path_prefix path_prefix identifier location)
383+
| `TPage -> `Page_path (parse_path_prefix path_prefix identifier location)
384+
| `TAsset ->
385+
`Asset_path (parse_path_prefix path_prefix identifier location)
352386
| _ ->
353387
expected ~expect_paths:true [ "module"; "page" ] location
354388
|> Error.raise_exception
@@ -534,9 +568,9 @@ let parse whole_reference_location s :
534568
|> Error.raise_exception)
535569

536570
(* Parse references that do not contain a [/]. Raises errors and warnings. *)
537-
let parse_asset (* whole_reference_location *) s :
571+
let parse_asset whole_reference_location s :
538572
Paths.Reference.Asset.t Error.with_errors_and_warnings =
539-
let path = parse_path s in
573+
let path = parse_path whole_reference_location s in
540574
Error.catch_errors_and_warnings (fun () -> `Asset_path path)
541575

542576
let read_path_longident location s =

src/model/reference.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ val parse :
44
Location_.span -> string -> Paths.Reference.t Error.with_errors_and_warnings
55

66
val parse_asset :
7-
(* Location_.span -> *)
7+
Location_.span ->
88
string ->
99
Paths.Reference.Asset.t Error.with_errors_and_warnings
1010

src/model/semantics.ml

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ let rec nestable_block_element :
281281
| {
282282
value =
283283
`Media
284-
(kind, { value = `Reference href; location = _href_location }, content, m);
284+
(kind, { value = `Reference href; location = href_location }, content, m);
285285
location;
286286
} -> (
287287
let fallback error =
@@ -295,27 +295,9 @@ let rec nestable_block_element :
295295
(inline_elements status [ placeholder |> Location.at location ])
296296
|> Location.at location
297297
in
298-
match
299-
Error.raise_warnings (Reference.parse_asset (* href_location *) href)
300-
with
298+
match Error.raise_warnings (Reference.parse_asset href_location href) with
301299
| Result.Ok target ->
302300
let text = inline_elements status content in
303-
(* let asset_ref_of_ref : *)
304-
(* Paths.Reference.t -> (Paths.Reference.Asset.t, _) Result.result = *)
305-
(* function *)
306-
(* | `Asset_path _ as a -> Result.Ok a *)
307-
(* (\* | `Root (_, `TAsset) as a -> Ok a *\) *)
308-
(* (\* | `Root (s, `TUnknown) -> Ok (`Root (s, `TAsset)) *\) *)
309-
(* (\* | `Dot (p, s) -> Ok (`Dot (p, s)) *\) *)
310-
(* | _ -> *)
311-
(* Error *)
312-
(* (not_allowed ~suggestion:"Use a reference to an asset" *)
313-
(* href_location ~what:"Non-asset reference" *)
314-
(* ~in_what:"media target") *)
315-
(* in *)
316-
(* match asset_ref_of_ref target with *)
317-
(* | Error error -> fallback error *)
318-
(* | Ok target -> *)
319301
`Media (`Reference target, m, text) |> Location.at location
320302
| Result.Error error -> fallback error)
321303

test/model/semantics/test.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,12 +2858,12 @@ let%expect_test _ =
28582858
let err_relative_empty_component =
28592859
test "{!foo//bar}";
28602860
[%expect
2861-
{| {"value":[{"`Paragraph":[{"`Reference":[{"`Any_path":["`TRelativePath",["foo","","bar"]]},[]]}]}],"warnings":[]} |}]
2861+
{| {"value":[{"`Paragraph":[{"`Code_span":"foo//bar"}]}],"warnings":["File \"f.ml\", line 1, characters 6-6:\nIdentifier in path reference should not be empty."]} |}]
28622862

28632863
let err_current_package_empty_component =
28642864
test "{!///bar}";
28652865
[%expect
2866-
{| {"value":[{"`Paragraph":[{"`Reference":[{"`Any_path":["`TCurrentPackage",["","bar"]]},[]]}]}],"warnings":[]} |}]
2866+
{| {"value":[{"`Paragraph":[{"`Code_span":"///bar"}]}],"warnings":["File \"f.ml\", line 1, characters 4-4:\nIdentifier in path reference should not be empty."]} |}]
28672867

28682868
let err_last_empty_component =
28692869
test "{!foo/}";

0 commit comments

Comments
 (0)