@@ -6,6 +6,7 @@ defmodule ElixirSense.Core.Compiler.Quote do
66 file: nil ,
77 context: nil ,
88 op: :escape ,
9+ # :escape | :escape_and_prune | {:struct, module} | :quote
910 aliases_hygiene: nil ,
1011 imports_hygiene: nil ,
1112 unquote: true ,
@@ -128,16 +129,22 @@ defmodule ElixirSense.Core.Compiler.Quote do
128129 defp default ( :generated ) , do: false
129130
130131 def escape ( expr , op , unquote , state ) do
131- q = % __MODULE__ {
132- line: true ,
133- file: nil ,
134- op: op ,
135- unquote: unquote
136- }
137-
138- case unquote do
139- true -> do_quote ( expr , q , state )
140- false -> do_escape ( expr , q , state )
132+ try do
133+ q = % __MODULE__ {
134+ line: true ,
135+ file: nil ,
136+ op: op ,
137+ unquote: unquote
138+ }
139+
140+ case unquote do
141+ true -> do_quote ( expr , q , state )
142+ false -> do_escape ( expr , q , state )
143+ end
144+ catch
145+ _kind , _reason ->
146+ # elixir reraises here with trimmed stacktrace
147+ { nil , state }
141148 end
142149 end
143150
@@ -536,23 +543,36 @@ defmodule ElixirSense.Core.Compiler.Quote do
536543
537544 defp do_escape ( map , q , state ) when is_map ( map ) do
538545 with % { __struct__: module } when is_atom ( module ) <- map ,
539- true <- Code . ensure_loaded? ( module ) ,
540- true <- function_exported? ( module , :__escape__ , 1 ) do
541- module . __escape__ ( map )
546+ true <- q . op != { :struct , module } ,
547+ { :module , ^ module } <- Code . ensure_loaded ( module ) ,
548+ true <- function_exported? ( module , :__escape__ , 1 ) do
549+ case q . op do
550+ { :struct , _module } ->
551+ # elixir raises here error about custom escaping rules in struct defaults
552+ { { :%{} , [ ] , [ ] } , state }
553+
554+ _ ->
555+ expr = module . __escape__ ( map )
556+
557+ # elixir validates if expr is valid AST
558+ # we skip validation
559+ { expr , state }
560+ end
542561 else
543562 _ ->
544- # elixir errors if value is reference
545- keys = map
546- |> Map . to_list
547- |> Enum . filter ( fn
548- { _k , v } when is_reference ( v ) -> false
549- { _k , v } when is_tuple ( v ) ->
550- not find_tuple_ref ( v , 0 )
551- _ -> true
552- end )
553- |> Enum . sort
554- { tt , state } = do_escape ( keys , q , state )
555- { { :%{} , [ ] , tt } , state }
563+ # elixir errors if value is reference
564+ keys =
565+ map
566+ |> Map . to_list ( )
567+ |> Enum . filter ( fn
568+ { _k , v } when is_reference ( v ) -> false
569+ { _k , v } when is_tuple ( v ) -> not find_tuple_ref ( v , 0 )
570+ _ -> true
571+ end )
572+ |> Enum . sort ( )
573+
574+ { tt , state } = do_escape ( keys , q , state )
575+ { { :%{} , [ ] , tt } , state }
556576 end
557577 end
558578
@@ -579,7 +599,7 @@ defmodule ElixirSense.Core.Compiler.Quote do
579599 l = Enum . reverse ( t , [ h ] )
580600 do_quote_tail ( l , q , state )
581601 catch
582- _ ->
602+ _ , _ ->
583603 { l , r } = reverse_improper ( t , [ h ] )
584604 { tl , state } = do_quote_splice ( l , q , [ ] , [ ] , state )
585605 { tr , state } = do_escape ( r , q , state )
0 commit comments