Packages
oaspec
0.36.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/yaml_loc_ffi.erl
-module(yaml_loc_ffi).
-export([build_location_index/1]).
%% Build a location index from a YAML string.
%% Returns a list of {BinaryPath, {Line, Column}} tuples that Gleam can
%% convert into a Dict(String, SourceLoc).
-spec build_location_index(binary()) -> {ok, list({binary(), {integer(), integer()}})} | {error, nil}.
build_location_index(Content) ->
try
application:ensure_all_started(yamerl),
[Doc | _] = yamerl_constr:string(
binary_to_list(Content),
[{detailed_constr, true}, {keep_duplicate_keys, true}]
),
{yamerl_doc, Root} = Doc,
Acc = walk_node(Root, <<>>, []),
{ok, Acc}
catch
_:_ -> {ok, []}
end.
%% Walk a yamerl node tree and collect {Path, {Line, Col}} entries.
-spec walk_node(tuple(), binary(), list()) -> list().
walk_node(Node, Path, Acc) ->
Loc = extract_loc(Node),
Acc1 = [{Path, Loc} | Acc],
case Node of
{yamerl_map, _, _, _, Pairs} when is_list(Pairs) ->
walk_map_pairs(Pairs, Path, Acc1);
{yamerl_seq, _, _, _, Items, _Count} when is_list(Items) ->
walk_seq_items(Items, Path, 0, Acc1);
_ ->
Acc1
end.
-spec walk_map_pairs(list(), binary(), list()) -> list().
walk_map_pairs([], _ParentPath, Acc) ->
Acc;
walk_map_pairs([{KeyNode, ValueNode} | Rest], ParentPath, Acc) ->
KeyStr = node_to_key(KeyNode),
ChildPath = case ParentPath of
<<>> -> KeyStr;
_ -> <<ParentPath/binary, ".", KeyStr/binary>>
end,
Acc1 = walk_node(ValueNode, ChildPath, Acc),
walk_map_pairs(Rest, ParentPath, Acc1).
-spec walk_seq_items(list(), binary(), integer(), list()) -> list().
walk_seq_items([], _ParentPath, _Idx, Acc) ->
Acc;
walk_seq_items([Item | Rest], ParentPath, Idx, Acc) ->
IdxBin = integer_to_binary(Idx),
ChildPath = <<ParentPath/binary, "[", IdxBin/binary, "]">>,
Acc1 = walk_node(Item, ChildPath, Acc),
walk_seq_items(Rest, ParentPath, Idx + 1, Acc1).
-spec extract_loc(tuple()) -> {integer(), integer()}.
extract_loc(Node) ->
Pres = element(4, Node),
Line = proplists:get_value(line, Pres, 0),
Col = proplists:get_value(column, Pres, 0),
{Line, Col}.
-spec node_to_key(tuple()) -> binary().
node_to_key({yamerl_str, _, _, _, Text}) ->
unicode:characters_to_binary(Text);
node_to_key({yamerl_int, _, _, _, Int}) ->
integer_to_binary(Int);
node_to_key({yamerl_bool, _, _, _, true}) ->
<<"true">>;
node_to_key({yamerl_bool, _, _, _, false}) ->
<<"false">>;
node_to_key(_) ->
<<"_unknown_">>.