signature_help.rs

  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}