Skip to content

Commit

Permalink
Only return error for duplicate blocks if blocks are nested (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
mworrell authored Dec 15, 2024
1 parent 2a05c59 commit 7e9cabe
Showing 1 changed file with 23 additions and 26 deletions.
49 changes: 23 additions & 26 deletions src/template_compiler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -422,27 +422,24 @@ cs(Module, Filename, Options, Context) ->
}.

compile_tokens({ok, {extends, {string_literal, _, Extend}, Elements}}, CState, _Options) ->
Blocks = find_blocks(Elements),
case check_duplicate_blocks(Blocks) of
ok ->
case find_blocks(Elements) of
{ok, Blocks} ->
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
{ok, {Extend, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
{error, _} = Error ->
Error
end;
compile_tokens({ok, {overrules, Elements}}, CState, _Options) ->
Blocks = find_blocks(Elements),
case check_duplicate_blocks(Blocks) of
ok ->
case find_blocks(Elements) of
{ok, Blocks} ->
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
{ok, {overrules, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
{error, _} = Error ->
Error
end;
compile_tokens({ok, {base, Elements}}, CState, _Options) ->
Blocks = find_blocks(Elements),
case check_duplicate_blocks(Blocks) of
ok ->
case find_blocks(Elements) of
{ok, Blocks} ->
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
CStateElts = CState#cs{blocks = BlockAsts},
{Ws1, TemplateAsts} = template_compiler_element:compile(Elements, CStateElts, Ws),
Expand Down Expand Up @@ -517,12 +514,26 @@ reset_block_ws(Ws) ->

%% @doc Extract all block definitions from the parse tree, returns deepest nested blocks first
find_blocks(Elements) ->
find_blocks(Elements, []).
case find_blocks(Elements, {ok, [], []}) of
{ok, Acc, _Stack} ->
{ok, Acc};
{error, _} = Error ->
Error
end.

find_blocks(_, {error, _} = Error) ->
Error;
find_blocks(List, Acc) when is_list(List) ->
lists:foldl(fun find_blocks/2, Acc, List);
find_blocks({block, _Name, Elements} = Block, Acc) ->
find_blocks(Elements, [Block|Acc]);
find_blocks({block, {identifier, _Pos, Name}, Elements} = Block, {ok, Acc, Stack}) ->
case lists:member(Name, Stack) of
true ->
{error, {duplicate_block, Name}};
false ->
Acc1 = [ Block | Acc ],
Stack1 = [ Name | Stack ],
find_blocks(Elements, {ok, Acc1, Stack1})
end;
find_blocks(Element, Acc) ->
find_blocks(block_elements(Element), Acc).

Expand All @@ -537,20 +548,6 @@ block_elements({filter, _, Elts}) -> Elts;
block_elements(_) -> [].


check_duplicate_blocks(Blocks) ->
check_duplicate_blocks_1(Blocks, #{}).

check_duplicate_blocks_1([], _Acc) ->
ok;
check_duplicate_blocks_1([{block, {identifier, _Pos, Name}, _Elements}|Blocks], Acc) ->
case maps:is_key(Name, Acc) of
true ->
{error, {duplicate_block, Name}};
false ->
check_duplicate_blocks_1(Blocks, Acc#{ Name => true })
end.


%% @doc Optionally drop text before {% extends %} or {% overrules %}.
maybe_drop_text([{text, _SrcRef, _Text}|Rest], OrgTks) ->
maybe_drop_text(Rest, OrgTks);
Expand Down

0 comments on commit 7e9cabe

Please sign in to comment.