@@ -6,6 +6,11 @@ function is_eventually_call(ex)
6
6
is_eventually_call (ex. args[1 ]))
7
7
end
8
8
9
+ function is_stringchunk (node)
10
+ k = kind (node)
11
+ return k == K " String" || k == K " CmdString"
12
+ end
13
+
9
14
function _to_expr (node:: SyntaxNode , iteration_spec= false , need_linenodes= true )
10
15
if ! haschildren (node)
11
16
val = node. val
@@ -24,10 +29,62 @@ function _to_expr(node::SyntaxNode, iteration_spec=false, need_linenodes=true)
24
29
return val
25
30
end
26
31
end
27
- headstr = untokenize (head (node), include_flag_suff= false )
28
- headsym = ! isnothing (headstr) ? Symbol (headstr) :
29
- error (" Can't untokenize head of kind $(kind (node)) " )
32
+ if kind (node) == K " ?"
33
+ headsym = :if
34
+ else
35
+ headstr = untokenize (head (node), include_flag_suff= false )
36
+ headsym = ! isnothing (headstr) ? Symbol (headstr) :
37
+ error (" Can't untokenize head of kind $(kind (node)) " )
38
+ end
30
39
node_args = children (node)
40
+ if headsym == :string || headsym == :cmdstring
41
+ # Julia string literals may be interspersed with trivia in two situations:
42
+ # 1. Triple quoted string indentation is trivia
43
+ # 2. An \ before newline removes the newline and any following indentation
44
+ #
45
+ # Such trivia is eagerly removed by the reference parser, so here we
46
+ # concatenate adjacent string chunks together for compatibility.
47
+ args = Vector {Any} ()
48
+ i = 1
49
+ while i <= length (node_args)
50
+ if is_stringchunk (node_args[i])
51
+ if i < length (node_args) && is_stringchunk (node_args[i+ 1 ])
52
+ buf = IOBuffer ()
53
+ while i <= length (node_args) && is_stringchunk (node_args[i])
54
+ write (buf, node_args[i]. val)
55
+ i += 1
56
+ end
57
+ push! (args, String (take! (buf)))
58
+ else
59
+ push! (args, node_args[i]. val)
60
+ i += 1
61
+ end
62
+ else
63
+ e = _to_expr (node_args[i])
64
+ if e isa String && headsym == :string
65
+ # Wrap interpolated literal strings in (string) so we can
66
+ # distinguish them from the surrounding text (issue #38501)
67
+ # Ie, "$("str")" vs "str"
68
+ # https://github.com/JuliaLang/julia/pull/38692
69
+ e = Expr (:string , e)
70
+ end
71
+ push! (args, e)
72
+ i += 1
73
+ end
74
+ end
75
+ if length (args) == 1 && args[1 ] isa String
76
+ # If there's a single string remaining after joining, we unwrap
77
+ # to give a string literal.
78
+ # """\n a\n b""" ==> "a\nb"
79
+ # headsym === :cmdstring follows this branch
80
+ return only (args)
81
+ else
82
+ @check headsym === :string
83
+ return Expr (headsym, args... )
84
+ end
85
+ end
86
+
87
+ # Convert children
31
88
insert_linenums = (headsym == :block || headsym == :toplevel ) && need_linenodes
32
89
args = Vector {Any} (undef, length (node_args)* (insert_linenums ? 2 : 1 ))
33
90
if headsym == :for && length (node_args) == 2
@@ -121,38 +178,6 @@ function _to_expr(node::SyntaxNode, iteration_spec=false, need_linenodes=true)
121
178
pushfirst! (args, numeric_flags (flags (node)))
122
179
elseif headsym == :typed_ncat
123
180
insert! (args, 2 , numeric_flags (flags (node)))
124
- elseif headsym == :string && length (args) > 1
125
- # Julia string literals may be interspersed with trivia in two situations:
126
- # 1. Triple quoted string indentation is trivia
127
- # 2. An \ before newline removes the newline and any following indentation
128
- #
129
- # Such trivia is eagerly removed by the reference parser, so here we
130
- # concatenate adjacent string chunks together for compatibility.
131
- #
132
- # TODO : Manage the non-interpolation cases with String and CmdString
133
- # kinds instead?
134
- args2 = Vector {Any} ()
135
- i = 1
136
- while i <= length (args)
137
- if args[i] isa String && i < length (args) && args[i+ 1 ] isa String
138
- buf = IOBuffer ()
139
- while i <= length (args) && args[i] isa String
140
- write (buf, args[i])
141
- i += 1
142
- end
143
- push! (args2, String (take! (buf)))
144
- else
145
- push! (args2, args[i])
146
- i += 1
147
- end
148
- end
149
- args = args2
150
- if length (args2) == 1 && args2[1 ] isa String
151
- # If there's a single string remaining after joining we unwrap to
152
- # give a string literal.
153
- # """\n a\n b""" ==> "a\nb"
154
- return args2[1 ]
155
- end
156
181
# elseif headsym == :string && length(args) == 1 && version <= (1,5)
157
182
# Strip string from interpolations in 1.5 and lower to preserve
158
183
# "hi$("ho")" ==> (string "hi" "ho")
0 commit comments