@@ -711,7 +711,7 @@ collect_modifiers(Rest, Buffer) ->
711711% % Heredocs
712712
713713extract_heredoc_with_interpolation (Line , Column , Scope , Interpol , T , H ) ->
714- case extract_heredoc (Line , Column , T , H ) of
714+ case extract_heredoc (Line , Column , T , H , Scope ) of
715715 {ok , NewLine , NewColumn , Body , Rest } ->
716716 case elixir_interpolation :extract (Line + 1 , 1 , Scope , Interpol , Body , 0 ) of
717717 {error , Reason } ->
@@ -723,15 +723,15 @@ extract_heredoc_with_interpolation(Line, Column, Scope, Interpol, T, H) ->
723723 Error
724724 end .
725725
726- extract_heredoc (Line0 , Column0 , Rest0 , Marker ) ->
726+ extract_heredoc (Line0 , Column0 , Rest0 , Marker , Scope ) ->
727727 case extract_heredoc_header (Rest0 ) of
728728 {ok , Rest1 } ->
729729 % % We prepend a new line so we can transparently remove
730730 % % spaces later. This new line is removed by calling "tl"
731731 % % in the final heredoc body three lines below.
732732 case extract_heredoc_body (Line0 , Column0 , Marker , [$\n | Rest1 ], []) of
733733 {ok , Line1 , Body , Rest2 , Spaces } ->
734- {ok , Line1 , 1 , tl (remove_heredoc_spaces (Body , Spaces )), Rest2 };
734+ {ok , Line1 , 1 , tl (remove_heredoc_spaces (Body , Spaces , Marker , Scope )), Rest2 };
735735 {error , Reason , ErrorLine } ->
736736 Terminator = [Marker , Marker , Marker ],
737737 {Message , Token } = heredoc_error_message (Reason , Line0 , Terminator ),
@@ -746,23 +746,49 @@ heredoc_error_message(eof, Line, Terminator) ->
746746 {io_lib :format (" missing terminator: ~ts (for heredoc starting at line ~B )" ,
747747 [Terminator , Line ]),
748748 []};
749- heredoc_error_message (misplacedterminator , _Line , Terminator ) ->
749+ heredoc_error_message (badterminator , _Line , Terminator ) ->
750750 {" invalid location for heredoc terminator, please escape token or move it to its own line: " ,
751751 Terminator }.
752+
752753% % Remove spaces from heredoc based on the position of the final quotes.
753754
754- remove_heredoc_spaces (Body , 0 ) ->
755- lists :reverse ([0 | Body ]);
756- remove_heredoc_spaces (Body , Spaces ) ->
757- remove_heredoc_spaces ([0 | Body ], [], Spaces , Spaces ).
758- remove_heredoc_spaces ([H , $\n | T ], [Backtrack | Buffer ], Spaces , Original ) when Spaces > 0 , ? is_horizontal_space (H ) ->
759- remove_heredoc_spaces ([Backtrack , $\n | T ], Buffer , Spaces - 1 , Original );
760- remove_heredoc_spaces ([$\n = H | T ], Buffer , _Spaces , Original ) ->
761- remove_heredoc_spaces (T , [H | Buffer ], Original , Original );
762- remove_heredoc_spaces ([H | T ], Buffer , Spaces , Original ) ->
763- remove_heredoc_spaces (T , [H | Buffer ], Spaces , Original );
764- remove_heredoc_spaces ([], Buffer , _Spaces , _Original ) ->
765- Buffer .
755+ remove_heredoc_spaces (Body , Spaces , Marker , Scope ) ->
756+ case trim_spaces (Body , [0 ], Spaces , false ) of
757+ {Acc , false } ->
758+ Acc ;
759+ {Acc , Line } ->
760+ Msg = io_lib :format (" outdented heredoc line. The contents inside the heredoc should be indented "
761+ " at the same level as the closing ~ts . The following is forbidden:~n~n "
762+ " def text do~n "
763+ " \"\"\" ~n "
764+ " contents~n "
765+ " \"\"\" ~n "
766+ " end~n~n "
767+ " Instead make sure the contents are indented as much as the heredoc closing:~n~n "
768+ " def text do~n "
769+ " \"\"\" ~n "
770+ " contents~n "
771+ " \"\"\" ~n "
772+ " end~n~n "
773+ " The current heredoc line is indented too litle" , [[Marker , Marker , Marker ]]),
774+ elixir_errors :warn (Line , Scope # elixir_tokenizer .file , Msg ),
775+ Acc
776+ end .
777+
778+ trim_spaces ([{Line , Entry } | Rest ], Acc , Spaces , Warned ) ->
779+ case trim_space (lists :reverse (Entry ), Spaces ) of
780+ {Trimmed , true } when Warned == false ->
781+ trim_spaces (Rest , Trimmed ++ Acc , Spaces , Line );
782+ {Trimmed , _ } ->
783+ trim_spaces (Rest , Trimmed ++ Acc , Spaces , Warned )
784+ end ;
785+ trim_spaces ([], Acc , _Spaces , Warned ) ->
786+ {Acc , Warned }.
787+
788+ trim_space (Rest , 0 ) -> {Rest , false };
789+ trim_space ([$\n ], _ ) -> {[$\n ], false };
790+ trim_space ([H | T ], Spaces ) when ? is_horizontal_space (H ) -> trim_space (T , Spaces - 1 );
791+ trim_space (Rest , _Spaces ) -> {Rest , true }.
766792
767793% % Extract the heredoc header.
768794
@@ -780,11 +806,11 @@ extract_heredoc_header(_) ->
780806% % is aligned.
781807
782808extract_heredoc_body (Line , _Column , Marker , Rest , Buffer ) ->
783- case extract_heredoc_line (Marker , Rest , Buffer , 0 ) of
784- {ok , NewBuffer , NewRest } ->
785- extract_heredoc_body (Line + 1 , 1 , Marker , NewRest , NewBuffer );
786- {ok , NewBuffer , NewRest , Spaces } ->
787- {ok , Line , NewBuffer , NewRest , Spaces };
809+ case extract_heredoc_line (Marker , Rest , [] , 0 ) of
810+ {ok , Entry , NewRest } ->
811+ extract_heredoc_body (Line + 1 , 1 , Marker , NewRest , [{ Line , Entry } | Buffer ] );
812+ {done , Entry , NewRest , Spaces } ->
813+ {ok , Line , [{ Line , Entry } | Buffer ] , NewRest , Spaces };
788814 {error , Reason } ->
789815 {error , Reason , Line }
790816 end .
@@ -797,7 +823,7 @@ extract_heredoc_line(Marker, [$\\, $\\ | T], Buffer) ->
797823extract_heredoc_line (Marker , [$\\ , Marker | T ], Buffer ) ->
798824 extract_heredoc_line (Marker , T , [Marker , $\\ | Buffer ]);
799825extract_heredoc_line (Marker , [Marker , Marker , Marker | _ ], _ ) ->
800- {error , misplacedterminator };
826+ {error , badterminator };
801827extract_heredoc_line (_ , " \r\n " ++ Rest , Buffer ) ->
802828 {ok , [$\n | Buffer ], Rest };
803829extract_heredoc_line (_ , " \n " ++ Rest , Buffer ) ->
@@ -812,7 +838,7 @@ extract_heredoc_line(_, _, _) ->
812838extract_heredoc_line (Marker , [H | T ], Buffer , Counter ) when ? is_horizontal_space (H ) ->
813839 extract_heredoc_line (Marker , T , [H | Buffer ], Counter + 1 );
814840extract_heredoc_line (Marker , [Marker , Marker , Marker | T ], Buffer , Counter ) ->
815- {ok , Buffer , T , Counter };
841+ {done , Buffer , T , Counter };
816842extract_heredoc_line (Marker , Rest , Buffer , _Counter ) ->
817843 extract_heredoc_line (Marker , Rest , Buffer ).
818844
0 commit comments