@@ -121,8 +121,8 @@ tokenize(String, Line, Column, Opts) ->
121121 lists :foldl (fun
122122 ({check_terminators , false }, Acc ) ->
123123 Acc # elixir_tokenizer {cursor_completion = false , terminators = none };
124- ({check_terminators , {cursor , Terminators }}, Acc ) ->
125- Acc # elixir_tokenizer {cursor_completion = prune_and_cursor , terminators = Terminators };
124+ ({check_terminators , {cursor , Sigils , Terminators }}, Acc ) ->
125+ Acc # elixir_tokenizer {cursor_completion = { prune_and_cursor , Sigils } , terminators = Terminators };
126126 ({existing_atoms_only , ExistingAtomsOnly }, Acc ) when is_boolean (ExistingAtomsOnly ) ->
127127 Acc # elixir_tokenizer {existing_atoms_only = ExistingAtomsOnly };
128128 ({static_atoms_encoder , StaticAtomsEncoder }, Acc ) when is_function (StaticAtomsEncoder ) ->
@@ -144,12 +144,9 @@ tokenize(String, Line, Opts) ->
144144
145145tokenize ([], Line , Column , # elixir_tokenizer {cursor_completion = Cursor } = Scope , Tokens ) when Cursor /= false ->
146146 # elixir_tokenizer {ascii_identifiers_only = Ascii , terminators = Terminators , warnings = Warnings } = Scope ,
147-
148- {CursorColumn , AccTerminators , AccTokens } =
149- add_cursor (Line , Column , Cursor , Terminators , Tokens ),
150-
147+ {CursorColumn , AccTokens } = add_cursor (Line , Column , Cursor , Tokens ),
151148 AllWarnings = maybe_unicode_lint_warnings (Ascii , Tokens , Warnings ),
152- {ok , Line , CursorColumn , AllWarnings , AccTokens , AccTerminators };
149+ {ok , Line , CursorColumn , AllWarnings , AccTokens , Terminators };
153150
154151tokenize ([], EndLine , EndColumn , # elixir_tokenizer {terminators = [{Start , {StartLine , StartColumn , _ }, _ } | _ ]} = Scope , Tokens ) ->
155152 End = terminator (Start ),
@@ -515,7 +512,7 @@ tokenize([$:, H | T] = Original, Line, Column, BaseScope, Tokens) when ?is_quote
515512 end ,
516513
517514 case elixir_interpolation :extract (Line , Column + 2 , Scope , true , T , H ) of
518- {NewLine , NewColumn , Parts , Rest , InterScope } ->
515+ {NewLine , NewColumn , Parts , Rest , _Done , InterScope } ->
519516 NewScope = case is_unnecessary_quote (Parts , InterScope ) of
520517 true ->
521518 WarnMsg = io_lib :format (
@@ -788,7 +785,7 @@ handle_char(_) -> false.
788785
789786handle_heredocs (T , Line , Column , H , Scope , Tokens ) ->
790787 case extract_heredoc_with_interpolation (Line , Column , Scope , true , T , H ) of
791- {ok , NewLine , NewColumn , Parts , Rest , NewScope } ->
788+ {ok , NewLine , NewColumn , Parts , Rest , _Done , NewScope } ->
792789 case unescape_tokens (Parts , Line , Column , NewScope ) of
793790 {ok , Unescaped } ->
794791 Token = {heredoc_type (H ), {Line , Column , nil }, NewColumn - 4 , Unescaped },
@@ -807,7 +804,7 @@ handle_strings(T, Line, Column, H, Scope, Tokens) ->
807804 {error , Reason } ->
808805 interpolation_error (Reason , [H | T ], Scope , Tokens , " (for string starting at line ~B )" , [Line ], Line , Column - 1 , [H ], [H ]);
809806
810- {NewLine , NewColumn , Parts , [$: | Rest ], InterScope } when ? is_space (hd (Rest )) ->
807+ {NewLine , NewColumn , Parts , [$: | Rest ], _Done , InterScope } when ? is_space (hd (Rest )) ->
811808 NewScope = case is_unnecessary_quote (Parts , InterScope ) of
812809 true ->
813810 WarnMsg = io_lib :format (
@@ -850,7 +847,7 @@ handle_strings(T, Line, Column, H, Scope, Tokens) ->
850847 error (Reason , Rest , NewScope , Tokens )
851848 end ;
852849
853- {NewLine , NewColumn , Parts , Rest , InterScope } ->
850+ {NewLine , NewColumn , Parts , Rest , _Done , InterScope } ->
854851 NewScope =
855852 case H of
856853 $' ->
@@ -961,7 +958,7 @@ handle_dot([$., H | T] = Original, Line, Column, DotInfo, BaseScope, Tokens) whe
961958 end ,
962959
963960 case elixir_interpolation :extract (Line , Column + 1 , Scope , true , T , H ) of
964- {NewLine , NewColumn , [Part ], Rest , InterScope } when is_list (Part ) ->
961+ {NewLine , NewColumn , [Part ], Rest , _Done , InterScope } when is_list (Part ) ->
965962 NewScope = case is_unnecessary_quote ([Part ], InterScope ) of
966963 true ->
967964 WarnMsg = io_lib :format (
@@ -992,7 +989,7 @@ handle_dot([$., H | T] = Original, Line, Column, DotInfo, BaseScope, Tokens) whe
992989 error (Reason , Original , NewScope , Tokens )
993990 end ;
994991
995- {_NewLine , _NewColumn , _Parts , Rest , NewScope } ->
992+ {_NewLine , _NewColumn , _Parts , Rest , _Done , NewScope } ->
996993 Message = " interpolation is not allowed when calling function/macro. Found interpolation in a call starting with: " ,
997994 error ({? LOC (Line , Column ), Message , [H ]}, Rest , NewScope , Tokens );
998995 {error , Reason } ->
@@ -1149,11 +1146,11 @@ unsafe_to_atom(List, Line, Column, #elixir_tokenizer{}) when is_list(List) ->
11491146 end
11501147 end .
11511148
1152- collect_modifiers ([H | T ], Buffer ) when ? is_downcase (H ) or ? is_upcase (H ) or ? is_digit (H ) ->
1153- collect_modifiers (T , [H | Buffer ]);
1149+ collect_modifiers ([H | T ], Column , Buffer ) when ? is_downcase (H ) or ? is_upcase (H ) or ? is_digit (H ) ->
1150+ collect_modifiers (T , Column + 1 , [H | Buffer ]);
11541151
1155- collect_modifiers (Rest , Buffer ) ->
1156- {Rest , lists :reverse (Buffer )}.
1152+ collect_modifiers (Rest , Column , Buffer ) ->
1153+ {Rest , Column , lists :reverse (Buffer )}.
11571154
11581155% % Heredocs
11591156
@@ -1164,14 +1161,14 @@ extract_heredoc_with_interpolation(Line, Column, Scope, Interpol, T, H) ->
11641161 % % spaces later. This new line is removed by calling "tl"
11651162 % % in the final heredoc body three lines below.
11661163 case elixir_interpolation :extract (Line , Column , Scope , Interpol , [$\n |Headerless ], [H ,H ,H ]) of
1167- {NewLine , NewColumn , Parts0 , Rest , InterScope } ->
1164+ {NewLine , NewColumn , Parts0 , Rest , Done , InterScope } ->
11681165 Indent = NewColumn - 4 ,
11691166 Fun = fun (Part , Acc ) -> extract_heredoc_indent (Part , Acc , Indent ) end ,
11701167 {Parts1 , {ShouldWarn , _ }} = lists :mapfoldl (Fun , {false , Line }, Parts0 ),
11711168 Parts2 = extract_heredoc_head (Parts1 ),
11721169 NewScope = maybe_heredoc_warn (ShouldWarn , Column , InterScope , H ),
11731170 try
1174- {ok , NewLine , NewColumn , tokens_to_binary (Parts2 ), Rest , NewScope }
1171+ {ok , NewLine , NewColumn , tokens_to_binary (Parts2 ), Rest , Done , NewScope }
11751172 catch
11761173 error :#{'__struct__' := 'Elixir.UnicodeConversionError' , message := Message } ->
11771174 {error , interpolation_format (Message , " (for heredoc starting at line ~B )" , [Line ], Line , Column , [H , H , H ], [H , H , H ])}
@@ -1746,9 +1743,9 @@ sigil_name_error() ->
17461743tokenize_sigil_contents ([H , H , H | T ] = Original , [S | _ ] = SigilName , Line , Column , Scope , Tokens )
17471744 when ? is_quote (H ) ->
17481745 case extract_heredoc_with_interpolation (Line , Column , Scope , ? is_downcase (S ), T , H ) of
1749- {ok , NewLine , NewColumn , Parts , Rest , NewScope } ->
1746+ {ok , NewLine , NewColumn , Parts , Rest , Done , NewScope } ->
17501747 Indentation = NewColumn - 4 ,
1751- add_sigil_token (SigilName , Line , Column , NewLine , NewColumn , Parts , Rest , NewScope , Tokens , Indentation , <<H , H , H >>);
1748+ add_sigil_token (SigilName , Line , Column , NewLine , NewColumn , Parts , Rest , Done , NewScope , Tokens , Indentation , <<H , H , H >>);
17521749
17531750 {error , Reason } ->
17541751 error (Reason , [$~ ] ++ SigilName ++ Original , Scope , Tokens )
@@ -1757,9 +1754,10 @@ tokenize_sigil_contents([H, H, H | T] = Original, [S | _] = SigilName, Line, Col
17571754tokenize_sigil_contents ([H | T ] = Original , [S | _ ] = SigilName , Line , Column , Scope , Tokens )
17581755 when ? is_sigil (H ) ->
17591756 case elixir_interpolation :extract (Line , Column + 1 , Scope , ? is_downcase (S ), T , sigil_terminator (H )) of
1760- {NewLine , NewColumn , Parts , Rest , NewScope } ->
1757+ {NewLine , NewColumn , Parts , Rest , Done , NewScope } ->
17611758 Indentation = nil ,
1762- add_sigil_token (SigilName , Line , Column , NewLine , NewColumn , tokens_to_binary (Parts ), Rest , NewScope , Tokens , Indentation , <<H >>);
1759+ add_sigil_token (SigilName , Line , Column , NewLine , NewColumn ,
1760+ tokens_to_binary (Parts ), Rest , Done , NewScope , Tokens , Indentation , <<H >>);
17631761
17641762 {error , Reason } ->
17651763 Sigil = [$~ , S , H ],
@@ -1779,7 +1777,7 @@ tokenize_sigil_contents([H | _] = Original, SigilName, Line, Column, Scope, Toke
17791777tokenize_sigil_contents ([], _SigilName , Line , Column , Scope , Tokens ) ->
17801778 tokenize ([], Line , Column , Scope , Tokens ).
17811779
1782- add_sigil_token (SigilName , Line , Column , NewLine , NewColumn , Parts , Rest , Scope , Tokens , Indentation , Delimiter ) ->
1780+ add_sigil_token (SigilName , Line , Column , NewLine , NewColumn , Parts , Rest , Done , Scope , Tokens , Indentation , Delimiter ) ->
17831781 TokenColumn = Column - 1 - length (SigilName ),
17841782 MaybeEncoded = case SigilName of
17851783 % Single-letter sigils present no risk of atom exhaustion (limited possibilities)
@@ -1788,9 +1786,12 @@ add_sigil_token(SigilName, Line, Column, NewLine, NewColumn, Parts, Rest, Scope,
17881786 end ,
17891787 case MaybeEncoded of
17901788 {ok , Atom } ->
1791- {Final , Modifiers } = collect_modifiers (Rest , []),
1792- Token = {sigil , {Line , TokenColumn , nil }, Atom , Parts , Modifiers , Indentation , Delimiter },
1793- NewColumnWithModifiers = NewColumn + length (Modifiers ),
1789+ {Final , NewColumnWithModifiers , Modifiers } = case Done of
1790+ true -> collect_modifiers (Rest , NewColumn , []);
1791+ false -> {Rest , NewColumn , false }
1792+ end ,
1793+ Token = {sigil , {Line , TokenColumn , {NewLine , NewColumnWithModifiers }},
1794+ Atom , Parts , Modifiers , Indentation , Delimiter },
17941795 tokenize (Final , NewLine , NewColumnWithModifiers , Scope , [Token | Tokens ]);
17951796
17961797 {error , Reason } ->
@@ -1903,9 +1904,19 @@ format_error({Location, Error, Token}) ->
19031904
19041905% % Cursor handling
19051906
1906- add_cursor (_Line , Column , noprune , Terminators , Tokens ) ->
1907- {Column , Terminators , Tokens };
1908- add_cursor (Line , Column , prune_and_cursor , Terminators , Tokens ) ->
1907+ add_cursor (_Line , Column , noprune , Tokens ) ->
1908+ {Column , Tokens };
1909+
1910+ add_cursor (Line , Column , {prune_and_cursor , true },
1911+ [{sigil , {_ , _ , {Line , Column }} = Location , Name , Parts , Modifier , Identation , Delimiter } | Rest ]) ->
1912+ Cursor = {'__cursor__' , [{line , Line }, {column , Column }], []},
1913+ CursorModifier = case Modifier of
1914+ false -> Cursor ;
1915+ List -> List ++ [Cursor ]
1916+ end ,
1917+ {Column + 12 , [{sigil , Location , Name , Parts , CursorModifier , Identation , Delimiter } | Rest ]};
1918+
1919+ add_cursor (Line , Column , {prune_and_cursor , _ }, Tokens ) ->
19091920 PrePrunedTokens = prune_identifier (Tokens ),
19101921 PrunedTokens = prune_tokens (PrePrunedTokens , []),
19111922 CursorTokens = [
@@ -1914,7 +1925,7 @@ add_cursor(Line, Column, prune_and_cursor, Terminators, Tokens) ->
19141925 {paren_identifier , {Line , Column , nil }, '__cursor__' }
19151926 | PrunedTokens
19161927 ],
1917- {Column + 12 , Terminators , CursorTokens }.
1928+ {Column + 12 , CursorTokens }.
19181929
19191930prune_identifier ([{identifier , _ , _ } | Tokens ]) -> Tokens ;
19201931prune_identifier (Tokens ) -> Tokens .
0 commit comments