1use gpui::{FontWeight, HighlightStyle, SharedString, TestAppContext};
2use lsp::{Documentation, MarkupContent, MarkupKind};
3
4use project::lsp_command::signature_help::SignatureHelp;
5
6fn current_parameter() -> HighlightStyle {
7 HighlightStyle {
8 font_weight: Some(FontWeight::EXTRA_BOLD),
9 ..Default::default()
10 }
11}
12
13#[gpui::test]
14fn test_create_signature_help_markdown_string_1(cx: &mut TestAppContext) {
15 let signature_help = lsp::SignatureHelp {
16 signatures: vec![lsp::SignatureInformation {
17 label: "fn test(foo: u8, bar: &str)".to_string(),
18 documentation: Some(Documentation::String(
19 "This is a test documentation".to_string(),
20 )),
21 parameters: Some(vec![
22 lsp::ParameterInformation {
23 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
24 documentation: None,
25 },
26 lsp::ParameterInformation {
27 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
28 documentation: None,
29 },
30 ]),
31 active_parameter: None,
32 }],
33 active_signature: Some(0),
34 active_parameter: Some(0),
35 };
36 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
37 assert!(maybe_markdown.is_some());
38
39 let markdown = maybe_markdown.unwrap();
40 let signature = markdown.signatures[markdown.active_signature].clone();
41 let markdown = (signature.label, signature.highlights);
42 assert_eq!(
43 markdown,
44 (
45 SharedString::new("fn test(foo: u8, bar: &str)"),
46 vec![(8..15, current_parameter())]
47 )
48 );
49 assert_eq!(
50 signature
51 .documentation
52 .unwrap()
53 .update(cx, |documentation, _| documentation.source().to_owned()),
54 "This is a test documentation",
55 )
56}
57
58#[gpui::test]
59fn test_create_signature_help_markdown_string_2(cx: &mut TestAppContext) {
60 let signature_help = lsp::SignatureHelp {
61 signatures: vec![lsp::SignatureInformation {
62 label: "fn test(foo: u8, bar: &str)".to_string(),
63 documentation: Some(Documentation::MarkupContent(MarkupContent {
64 kind: MarkupKind::Markdown,
65 value: "This is a test documentation".to_string(),
66 })),
67 parameters: Some(vec![
68 lsp::ParameterInformation {
69 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
70 documentation: None,
71 },
72 lsp::ParameterInformation {
73 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
74 documentation: None,
75 },
76 ]),
77 active_parameter: None,
78 }],
79 active_signature: Some(0),
80 active_parameter: Some(1),
81 };
82 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
83 assert!(maybe_markdown.is_some());
84
85 let markdown = maybe_markdown.unwrap();
86 let signature = markdown.signatures[markdown.active_signature].clone();
87 let markdown = (signature.label, signature.highlights);
88 assert_eq!(
89 markdown,
90 (
91 SharedString::new("fn test(foo: u8, bar: &str)"),
92 vec![(17..26, current_parameter())]
93 )
94 );
95 assert_eq!(
96 signature
97 .documentation
98 .unwrap()
99 .update(cx, |documentation, _| documentation.source().to_owned()),
100 "This is a test documentation",
101 )
102}
103
104#[gpui::test]
105fn test_create_signature_help_markdown_string_3(cx: &mut TestAppContext) {
106 let signature_help = lsp::SignatureHelp {
107 signatures: vec![
108 lsp::SignatureInformation {
109 label: "fn test1(foo: u8, bar: &str)".to_string(),
110 documentation: None,
111 parameters: Some(vec![
112 lsp::ParameterInformation {
113 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
114 documentation: None,
115 },
116 lsp::ParameterInformation {
117 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
118 documentation: None,
119 },
120 ]),
121 active_parameter: None,
122 },
123 lsp::SignatureInformation {
124 label: "fn test2(hoge: String, fuga: bool)".to_string(),
125 documentation: None,
126 parameters: Some(vec![
127 lsp::ParameterInformation {
128 label: lsp::ParameterLabel::Simple("hoge: String".to_string()),
129 documentation: None,
130 },
131 lsp::ParameterInformation {
132 label: lsp::ParameterLabel::Simple("fuga: bool".to_string()),
133 documentation: None,
134 },
135 ]),
136 active_parameter: None,
137 },
138 ],
139 active_signature: Some(0),
140 active_parameter: Some(0),
141 };
142 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
143 assert!(maybe_markdown.is_some());
144
145 let markdown = maybe_markdown.unwrap();
146 let signature = markdown.signatures[markdown.active_signature].clone();
147 let markdown = (signature.label, signature.highlights);
148 assert_eq!(
149 markdown,
150 (
151 SharedString::new("fn test1(foo: u8, bar: &str)"),
152 vec![(9..16, current_parameter())]
153 )
154 );
155}
156
157#[gpui::test]
158fn test_create_signature_help_markdown_string_4(cx: &mut TestAppContext) {
159 let signature_help = lsp::SignatureHelp {
160 signatures: vec![
161 lsp::SignatureInformation {
162 label: "fn test1(foo: u8, bar: &str)".to_string(),
163 documentation: None,
164 parameters: Some(vec![
165 lsp::ParameterInformation {
166 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
167 documentation: None,
168 },
169 lsp::ParameterInformation {
170 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
171 documentation: None,
172 },
173 ]),
174 active_parameter: None,
175 },
176 lsp::SignatureInformation {
177 label: "fn test2(hoge: String, fuga: bool)".to_string(),
178 documentation: None,
179 parameters: Some(vec![
180 lsp::ParameterInformation {
181 label: lsp::ParameterLabel::Simple("hoge: String".to_string()),
182 documentation: None,
183 },
184 lsp::ParameterInformation {
185 label: lsp::ParameterLabel::Simple("fuga: bool".to_string()),
186 documentation: None,
187 },
188 ]),
189 active_parameter: None,
190 },
191 ],
192 active_signature: Some(1),
193 active_parameter: Some(0),
194 };
195 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
196 assert!(maybe_markdown.is_some());
197
198 let markdown = maybe_markdown.unwrap();
199 let signature = markdown.signatures[markdown.active_signature].clone();
200 let markdown = (signature.label, signature.highlights);
201 assert_eq!(
202 markdown,
203 (
204 SharedString::new("fn test2(hoge: String, fuga: bool)"),
205 vec![(9..21, current_parameter())]
206 )
207 );
208}
209
210#[gpui::test]
211fn test_create_signature_help_markdown_string_5(cx: &mut TestAppContext) {
212 let signature_help = lsp::SignatureHelp {
213 signatures: vec![
214 lsp::SignatureInformation {
215 label: "fn test1(foo: u8, bar: &str)".to_string(),
216 documentation: None,
217 parameters: Some(vec![
218 lsp::ParameterInformation {
219 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
220 documentation: None,
221 },
222 lsp::ParameterInformation {
223 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
224 documentation: None,
225 },
226 ]),
227 active_parameter: None,
228 },
229 lsp::SignatureInformation {
230 label: "fn test2(hoge: String, fuga: bool)".to_string(),
231 documentation: None,
232 parameters: Some(vec![
233 lsp::ParameterInformation {
234 label: lsp::ParameterLabel::Simple("hoge: String".to_string()),
235 documentation: None,
236 },
237 lsp::ParameterInformation {
238 label: lsp::ParameterLabel::Simple("fuga: bool".to_string()),
239 documentation: None,
240 },
241 ]),
242 active_parameter: None,
243 },
244 ],
245 active_signature: Some(1),
246 active_parameter: Some(1),
247 };
248 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
249 assert!(maybe_markdown.is_some());
250
251 let markdown = maybe_markdown.unwrap();
252 let signature = markdown.signatures[markdown.active_signature].clone();
253 let markdown = (signature.label, signature.highlights);
254 assert_eq!(
255 markdown,
256 (
257 SharedString::new("fn test2(hoge: String, fuga: bool)"),
258 vec![(23..33, current_parameter())]
259 )
260 );
261}
262
263#[gpui::test]
264fn test_create_signature_help_markdown_string_6(cx: &mut TestAppContext) {
265 let signature_help = lsp::SignatureHelp {
266 signatures: vec![
267 lsp::SignatureInformation {
268 label: "fn test1(foo: u8, bar: &str)".to_string(),
269 documentation: None,
270 parameters: Some(vec![
271 lsp::ParameterInformation {
272 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
273 documentation: None,
274 },
275 lsp::ParameterInformation {
276 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
277 documentation: None,
278 },
279 ]),
280 active_parameter: None,
281 },
282 lsp::SignatureInformation {
283 label: "fn test2(hoge: String, fuga: bool)".to_string(),
284 documentation: None,
285 parameters: Some(vec![
286 lsp::ParameterInformation {
287 label: lsp::ParameterLabel::Simple("hoge: String".to_string()),
288 documentation: None,
289 },
290 lsp::ParameterInformation {
291 label: lsp::ParameterLabel::Simple("fuga: bool".to_string()),
292 documentation: None,
293 },
294 ]),
295 active_parameter: None,
296 },
297 ],
298 active_signature: Some(1),
299 active_parameter: None,
300 };
301 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
302 assert!(maybe_markdown.is_some());
303
304 let markdown = maybe_markdown.unwrap();
305 let signature = markdown.signatures[markdown.active_signature].clone();
306 let markdown = (signature.label, signature.highlights);
307 assert_eq!(
308 markdown,
309 (
310 SharedString::new("fn test2(hoge: String, fuga: bool)"),
311 vec![(9..21, current_parameter())]
312 )
313 );
314}
315
316#[gpui::test]
317fn test_create_signature_help_markdown_string_7(cx: &mut TestAppContext) {
318 let signature_help = lsp::SignatureHelp {
319 signatures: vec![
320 lsp::SignatureInformation {
321 label: "fn test1(foo: u8, bar: &str)".to_string(),
322 documentation: None,
323 parameters: Some(vec![
324 lsp::ParameterInformation {
325 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
326 documentation: None,
327 },
328 lsp::ParameterInformation {
329 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
330 documentation: None,
331 },
332 ]),
333 active_parameter: None,
334 },
335 lsp::SignatureInformation {
336 label: "fn test2(hoge: String, fuga: bool)".to_string(),
337 documentation: None,
338 parameters: Some(vec![
339 lsp::ParameterInformation {
340 label: lsp::ParameterLabel::Simple("hoge: String".to_string()),
341 documentation: None,
342 },
343 lsp::ParameterInformation {
344 label: lsp::ParameterLabel::Simple("fuga: bool".to_string()),
345 documentation: None,
346 },
347 ]),
348 active_parameter: None,
349 },
350 lsp::SignatureInformation {
351 label: "fn test3(one: usize, two: u32)".to_string(),
352 documentation: None,
353 parameters: Some(vec![
354 lsp::ParameterInformation {
355 label: lsp::ParameterLabel::Simple("one: usize".to_string()),
356 documentation: None,
357 },
358 lsp::ParameterInformation {
359 label: lsp::ParameterLabel::Simple("two: u32".to_string()),
360 documentation: None,
361 },
362 ]),
363 active_parameter: None,
364 },
365 ],
366 active_signature: Some(2),
367 active_parameter: Some(1),
368 };
369 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
370 assert!(maybe_markdown.is_some());
371
372 let markdown = maybe_markdown.unwrap();
373 let signature = markdown.signatures[markdown.active_signature].clone();
374 let markdown = (signature.label, signature.highlights);
375 assert_eq!(
376 markdown,
377 (
378 SharedString::new("fn test3(one: usize, two: u32)"),
379 vec![(21..29, current_parameter())]
380 )
381 );
382}
383
384#[gpui::test]
385fn test_create_signature_help_markdown_string_8(cx: &mut TestAppContext) {
386 let signature_help = lsp::SignatureHelp {
387 signatures: vec![],
388 active_signature: None,
389 active_parameter: None,
390 };
391 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
392 assert!(maybe_markdown.is_none());
393}
394
395#[gpui::test]
396fn test_create_signature_help_markdown_string_9(cx: &mut TestAppContext) {
397 let signature_help = lsp::SignatureHelp {
398 signatures: vec![lsp::SignatureInformation {
399 label: "fn test(foo: u8, bar: &str)".to_string(),
400 documentation: None,
401 parameters: Some(vec![
402 lsp::ParameterInformation {
403 label: lsp::ParameterLabel::LabelOffsets([8, 15]),
404 documentation: None,
405 },
406 lsp::ParameterInformation {
407 label: lsp::ParameterLabel::LabelOffsets([17, 26]),
408 documentation: None,
409 },
410 ]),
411 active_parameter: None,
412 }],
413 active_signature: Some(0),
414 active_parameter: Some(0),
415 };
416 let maybe_markdown = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
417 assert!(maybe_markdown.is_some());
418
419 let markdown = maybe_markdown.unwrap();
420 let signature = markdown.signatures[markdown.active_signature].clone();
421 let markdown = (signature.label, signature.highlights);
422 assert_eq!(
423 markdown,
424 (
425 SharedString::new("fn test(foo: u8, bar: &str)"),
426 vec![(8..15, current_parameter())]
427 )
428 );
429}
430
431#[gpui::test]
432fn test_parameter_documentation(cx: &mut TestAppContext) {
433 let signature_help = lsp::SignatureHelp {
434 signatures: vec![lsp::SignatureInformation {
435 label: "fn test(foo: u8, bar: &str)".to_string(),
436 documentation: Some(Documentation::String(
437 "This is a test documentation".to_string(),
438 )),
439 parameters: Some(vec![
440 lsp::ParameterInformation {
441 label: lsp::ParameterLabel::Simple("foo: u8".to_string()),
442 documentation: Some(Documentation::String("The foo parameter".to_string())),
443 },
444 lsp::ParameterInformation {
445 label: lsp::ParameterLabel::Simple("bar: &str".to_string()),
446 documentation: Some(Documentation::String("The bar parameter".to_string())),
447 },
448 ]),
449 active_parameter: None,
450 }],
451 active_signature: Some(0),
452 active_parameter: Some(0),
453 };
454 let maybe_signature_help = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
455 assert!(maybe_signature_help.is_some());
456
457 let signature_help = maybe_signature_help.unwrap();
458 let signature = &signature_help.signatures[signature_help.active_signature];
459
460 // Check that parameter documentation is extracted
461 assert_eq!(signature.parameters.len(), 2);
462 assert_eq!(
463 signature.parameters[0]
464 .documentation
465 .as_ref()
466 .unwrap()
467 .update(cx, |documentation, _| documentation.source().to_owned()),
468 "The foo parameter",
469 );
470 assert_eq!(
471 signature.parameters[1]
472 .documentation
473 .as_ref()
474 .unwrap()
475 .update(cx, |documentation, _| documentation.source().to_owned()),
476 "The bar parameter",
477 );
478
479 // Check that the active parameter is correct
480 assert_eq!(signature.active_parameter, Some(0));
481}
482
483#[gpui::test]
484fn test_create_signature_help_implements_utf16_spec(cx: &mut TestAppContext) {
485 let signature_help = lsp::SignatureHelp {
486 signatures: vec![lsp::SignatureInformation {
487 label: "fn test(🦀: u8, 🦀: &str)".to_string(),
488 documentation: None,
489 parameters: Some(vec![
490 lsp::ParameterInformation {
491 label: lsp::ParameterLabel::LabelOffsets([8, 10]),
492 documentation: None,
493 },
494 lsp::ParameterInformation {
495 label: lsp::ParameterLabel::LabelOffsets([16, 18]),
496 documentation: None,
497 },
498 ]),
499 active_parameter: None,
500 }],
501 active_signature: Some(0),
502 active_parameter: Some(0),
503 };
504 let signature_help = cx.update(|cx| SignatureHelp::new(signature_help, None, None, cx));
505 assert!(signature_help.is_some());
506
507 let markdown = signature_help.unwrap();
508 let signature = markdown.signatures[markdown.active_signature].clone();
509 let markdown = (signature.label, signature.highlights);
510 assert_eq!(
511 markdown,
512 (
513 SharedString::new("fn test(🦀: u8, 🦀: &str)"),
514 vec![(8..12, current_parameter())]
515 )
516 );
517}