Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8e000a9

Browse files
committed
fix(lsp): fix small bugs in snippet-parser
This fixes the following bugs:`${1:else_text}` -> format with if_text: "else_text"`${1:-else_text}` -> format with if_text: "else_text"`${1:}` (eg. empty else_text) -> error.
1 parent98e2da7 commit8e000a9

File tree

2 files changed

+150
-40
lines changed

2 files changed

+150
-40
lines changed

‎runtime/lua/vim/lsp/_snippet.lua‎

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ P.take_until = function(targets, specials)
77
targets=targetsor {}
88
specials=specialsor {}
99

10-
returnfunction(input,pos)
10+
returnfunction(input,pos,prevent_empty)
1111
localnew_pos=pos
1212
localraw= {}
1313
localesc= {}
@@ -33,7 +33,7 @@ P.take_until = function(targets, specials)
3333
end
3434
end
3535

36-
ifnew_pos==posthen
36+
ifnew_pos==posandprevent_emptythen
3737
returnP.unmatch(pos)
3838
end
3939

@@ -57,8 +57,8 @@ P.unmatch = function(pos)
5757
end
5858

5959
P.map=function(parser,map)
60-
returnfunction(input,pos)
61-
localresult=parser(input,pos)
60+
returnfunction(input,pos,prevent_empty)
61+
localresult=parser(input,pos,prevent_empty)
6262
ifresult.parsedthen
6363
return {
6464
parsed=true,
@@ -71,8 +71,8 @@ P.map = function(parser, map)
7171
end
7272

7373
P.lazy=function(factory)
74-
returnfunction(input,pos)
75-
returnfactory()(input,pos)
74+
returnfunction(input,pos,prevent_empty)
75+
returnfactory()(input,pos,prevent_empty)
7676
end
7777
end
7878

@@ -105,15 +105,26 @@ P.pattern = function(p)
105105
end
106106

107107
P.many=function(parser)
108+
-- an outer `prevent_empty` can, and should, be ignored by `many`.
109+
-- This is because `prevent_empty` is, in a way, `many`-local, so each `many`
110+
-- has its own `prevent_empty`, as it only has to keep its own value free
111+
-- from superfluous, empty, text.
108112
returnfunction(input,pos)
109113
localvalues= {}
110114
localnew_pos=pos
115+
localprevent_empty=false
111116
whilenew_pos<=#inputdo
112-
localresult=parser(input,new_pos)
117+
localresult=parser(input,new_pos,prevent_empty)
113118
ifnotresult.parsedthen
114119
break
115120
end
116121
table.insert(values,result.value)
122+
123+
-- only allow empty result in the first iteration.
124+
-- Otherwise, all `many` with text will include one superfluous empty
125+
-- string at the end.
126+
-- Assumption: if there is an empty child, it is the only one.
127+
prevent_empty=true
117128
new_pos=result.pos
118129
end
119130
if#values>0then
@@ -129,9 +140,9 @@ end
129140

130141
P.any=function(...)
131142
localparsers= {... }
132-
returnfunction(input,pos)
143+
returnfunction(input,pos,prevent_empty)
133144
for_,parserinipairs(parsers)do
134-
localresult=parser(input,pos)
145+
localresult=parser(input,pos,prevent_empty)
135146
ifresult.parsedthen
136147
returnresult
137148
end
@@ -141,8 +152,8 @@ P.any = function(...)
141152
end
142153

143154
P.opt=function(parser)
144-
returnfunction(input,pos)
145-
localresult=parser(input,pos)
155+
returnfunction(input,pos,prevent_empty)
156+
localresult=parser(input,pos,prevent_empty)
146157
return {
147158
parsed=true,
148159
value=result.value,
@@ -153,11 +164,11 @@ end
153164

154165
P.seq=function(...)
155166
localparsers= {... }
156-
returnfunction(input,pos)
167+
returnfunction(input,pos,prevent_empty)
157168
localvalues= {}
158169
localnew_pos=pos
159170
for_,parserinipairs(parsers)do
160-
localresult=parser(input,new_pos)
171+
localresult=parser(input,new_pos,prevent_empty)
161172
ifresult.parsedthen
162173
table.insert(values,result.value)
163174
new_pos=result.pos
@@ -274,8 +285,7 @@ S.format = P.any(
274285
S.colon,
275286
P.any(
276287
P.seq(S.question,P.take_until({':'}, {'\\'}),S.colon,P.take_until({'}'}, {'\\'})),
277-
P.seq(S.plus,P.take_until({'}'}, {'\\'})),
278-
P.seq(S.minus,P.take_until({'}'}, {'\\'}))
288+
P.seq(S.plus,P.take_until({'}'}, {'\\'}))
279289
),
280290
S.close
281291
),
@@ -287,6 +297,25 @@ S.format = P.any(
287297
else_text= (values[5][4]or {}).esc,
288298
},Node)
289299
end
300+
),
301+
P.map(
302+
P.seq(
303+
S.dollar,
304+
S.open,
305+
S.int,
306+
S.colon,
307+
P.opt(S.minus),
308+
P.take_until({'}'}, {'\\'}),
309+
S.close
310+
),
311+
function(values)
312+
returnsetmetatable({
313+
type=Node.Type.FORMAT,
314+
capture_index=values[3],
315+
-- if opt is not present, take_until becomes [5].
316+
else_text=#values==7andvalues[6].escorvalues[5].esc,
317+
},Node)
318+
end
290319
)
291320
)
292321

‎test/functional/plugin/lsp/snippet_spec.lua‎

Lines changed: 106 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ describe('vim.lsp._snippet', function()
1919
{
2020
type=snippet.NodeType.TEXT,
2121
raw='TE\\$\\}XT',
22-
esc='TE$}XT'
23-
}
24-
}
22+
esc='TE$}XT',
23+
},
24+
},
2525
},parse('TE\\$\\}XT'))
2626
end)
2727

@@ -36,8 +36,8 @@ describe('vim.lsp._snippet', function()
3636
{
3737
type=snippet.NodeType.TABSTOP,
3838
tabstop=2,
39-
}
40-
}
39+
},
40+
},
4141
},parse('$1${2}'))
4242
end)
4343

@@ -56,7 +56,7 @@ describe('vim.lsp._snippet', function()
5656
{
5757
type=snippet.NodeType.TEXT,
5858
raw='TE\\$\\}XT',
59-
esc='TE$}XT'
59+
esc='TE$}XT',
6060
},
6161
{
6262
type=snippet.NodeType.TABSTOP,
@@ -73,21 +73,21 @@ describe('vim.lsp._snippet', function()
7373
{
7474
type=snippet.NodeType.FORMAT,
7575
capture_index=1,
76-
modifier='upcase'
77-
}
78-
}
76+
modifier='upcase',
77+
},
78+
},
7979
},
8080
},
8181
{
8282
type=snippet.NodeType.TEXT,
8383
raw='TE\\$\\}XT',
84-
esc='TE$}XT'
84+
esc='TE$}XT',
8585
},
86-
}
87-
}
88-
}
86+
},
87+
},
88+
},
8989
},
90-
}
90+
},
9191
},parse('${1:${2:TE\\$\\}XT$3${1/regex/${1:/upcase}/i}TE\\$\\}XT}}'))
9292
end)
9393

@@ -110,8 +110,8 @@ describe('vim.lsp._snippet', function()
110110
{
111111
type=snippet.NodeType.TABSTOP,
112112
tabstop=1,
113-
}
114-
}
113+
},
114+
},
115115
},
116116
{
117117
type=snippet.NodeType.VARIABLE,
@@ -124,11 +124,11 @@ describe('vim.lsp._snippet', function()
124124
type=snippet.NodeType.FORMAT,
125125
capture_index=1,
126126
modifier='upcase',
127-
}
128-
}
129-
}
127+
},
128+
},
129+
},
130130
},
131-
}
131+
},
132132
},parse('$VAR${VAR}${VAR:$1}${VAR/regex/${1:/upcase}/}'))
133133
end)
134134

@@ -141,12 +141,93 @@ describe('vim.lsp._snippet', function()
141141
tabstop=1,
142142
items= {
143143
',',
144-
'|'
145-
}
146-
}
147-
}
144+
'|',
145+
},
146+
},
147+
},
148148
},parse('${1|\\,,\\||}'))
149149
end)
150150

151-
end)
151+
it('should parse format',function()
152+
eq({
153+
type=snippet.NodeType.SNIPPET,
154+
children= {
155+
{
156+
type=snippet.NodeType.VARIABLE,
157+
name='VAR',
158+
transform= {
159+
type=snippet.NodeType.TRANSFORM,
160+
pattern='regex',
161+
format= {
162+
{
163+
type=snippet.NodeType.FORMAT,
164+
capture_index=1,
165+
modifier='upcase',
166+
},
167+
{
168+
type=snippet.NodeType.FORMAT,
169+
capture_index=1,
170+
if_text='if_text',
171+
},
172+
{
173+
type=snippet.NodeType.FORMAT,
174+
capture_index=1,
175+
else_text='else_text',
176+
},
177+
{
178+
type=snippet.NodeType.FORMAT,
179+
capture_index=1,
180+
else_text='else_text',
181+
if_text='if_text',
182+
},
183+
{
184+
type=snippet.NodeType.FORMAT,
185+
capture_index=1,
186+
else_text='else_text',
187+
},
188+
},
189+
},
190+
},
191+
},
192+
},parse('${VAR/regex/${1:/upcase}${1:+if_text}${1:-else_text}${1:?if_text:else_text}${1:else_text}/}'))
193+
end)
152194

195+
it('should parse empty strings',function()
196+
eq({
197+
children= {
198+
{
199+
children= { {
200+
esc='',
201+
raw='',
202+
type=7,
203+
} },
204+
tabstop=1,
205+
type=2,
206+
},
207+
{
208+
esc='',
209+
raw='',
210+
type=7,
211+
},
212+
{
213+
name='VAR',
214+
transform= {
215+
format= {
216+
{
217+
capture_index=1,
218+
else_text='',
219+
if_text='',
220+
type=6,
221+
},
222+
},
223+
option='g',
224+
pattern='erg',
225+
type=5,
226+
},
227+
type=3,
228+
},
229+
},
230+
type=0,
231+
},parse('${1:} ${VAR/erg/${1:?:}/g}'))
232+
end)
233+
end)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp