@@ -384,6 +384,39 @@ def lsp_completion_item(
384
384
return completion_item
385
385
386
386
387
+ def _md_bold (value : str , markup_kind : MarkupKind ) -> str :
388
+ """Add bold surrounding when markup_kind is markdown."""
389
+ return f"**{ value } **" if markup_kind == MarkupKind .Markdown else value
390
+
391
+
392
+ def _md_italic (value : str , markup_kind : MarkupKind ) -> str :
393
+ """Add italic surrounding when markup_kind is markdown."""
394
+ return f"*{ value } *" if markup_kind == MarkupKind .Markdown else value
395
+
396
+
397
+ def _md_text (value : str , markup_kind : MarkupKind ) -> str :
398
+ """Surround a markdown string with a Python fence."""
399
+ return (
400
+ f"```text\n { value } \n ```"
401
+ if markup_kind == MarkupKind .Markdown
402
+ else value
403
+ )
404
+
405
+
406
+ def _md_python (value : str , markup_kind : MarkupKind ) -> str :
407
+ """Surround a markdown string with a Python fence."""
408
+ return (
409
+ f"```python\n { value } \n ```"
410
+ if markup_kind == MarkupKind .Markdown
411
+ else value
412
+ )
413
+
414
+
415
+ def _md_text_sl (value : str , markup_kind : MarkupKind ) -> str :
416
+ """Surround markdown text with single line backtick."""
417
+ return f"`{ value } `" if markup_kind == MarkupKind .Markdown else value
418
+
419
+
387
420
def convert_docstring (docstring : str , markup_kind : MarkupKind ) -> str :
388
421
"""Take a docstring and convert it to markup kind if possible.
389
422
@@ -398,58 +431,93 @@ def convert_docstring(docstring: str, markup_kind: MarkupKind) -> str:
398
431
try :
399
432
return docstring_to_markdown .convert (docstring ).strip ()
400
433
except docstring_to_markdown .UnknownFormatError :
401
- return docstring .strip ()
434
+ return _md_text ( docstring .strip (), markup_kind )
402
435
except Exception as error : # pylint: disable=broad-except
403
- return (
404
- docstring
436
+ result = (
437
+ docstring . strip ()
405
438
+ "\n "
406
439
+ "jedi-language-server error: "
407
440
+ "Uncaught exception while converting docstring to markdown. "
408
441
+ "Please open issue at "
409
442
+ "https://github.com/pappasam/jedi-language-server/issues. "
410
443
+ f"Traceback:\n { error } "
411
444
).strip ()
445
+ return _md_text (result , markup_kind )
412
446
return docstring .strip ()
413
447
414
448
415
- def _bold (value : str , markup_kind : MarkupKind ) -> str :
416
- """Add bold surrounding when markup_kind is markdown."""
417
- return f"**{ value } **" if markup_kind == MarkupKind .Markdown else value
418
-
449
+ _HOVER_SIGNATURE_TYPES = {"class" , "instance" , "function" }
419
450
420
- def _italic (value : str , markup_kind : MarkupKind ) -> str :
421
- """Add italic surrounding when markup_kind is markdown."""
422
- return f"*{ value } *" if markup_kind == MarkupKind .Markdown else value
451
+ _HOVER_TYPE_TRANSLATION = {
452
+ "module" : "module" ,
453
+ "class" : "class" ,
454
+ "instance" : "instance" ,
455
+ "function" : "def" ,
456
+ "param" : "param" ,
457
+ "path" : "path" ,
458
+ "keyword" : "keyword" ,
459
+ "property" : "property" ,
460
+ "statement" : "statement" ,
461
+ }
423
462
424
463
425
464
def hover_text (names : List [Name ], markup_kind : MarkupKind ) -> Optional [str ]:
426
465
"""Get a hover string from a list of names."""
466
+ # pylint: disable=too-many-branches
427
467
if not names :
428
468
return None
429
469
name = names [0 ]
470
+ name_type = name .type
471
+ hover_type = _HOVER_TYPE_TRANSLATION [name_type ]
472
+ signatures = (
473
+ [f"{ hover_type } { s .to_string ()} " for s in name .get_signatures ()]
474
+ if name_type in _HOVER_SIGNATURE_TYPES
475
+ else []
476
+ )
430
477
name_str = name .name
431
478
full_name = name .full_name
432
479
description = name .description
433
- docstring = name .docstring ()
434
- try :
435
- type_hint = name .get_type_hint ()
436
- except Exception : # pylint: disable=broad-except
437
- # jedi randomly raises NotImplemented, TypeError, and possibly more
438
- # errors here. One example from jls: test_hover.test_hover_on_method
480
+ docstring = name .docstring (raw = True )
481
+ if not signatures and name_type != "class" :
482
+ try :
483
+ type_hint = name .get_type_hint ()
484
+ except Exception : # pylint: disable=broad-except
485
+ # jedi randomly raises NotImplemented, TypeError, and possibly more
486
+ # errors here. One example from jls -
487
+ # test_hover.test_hover_on_method
488
+ type_hint = ""
489
+ else :
439
490
type_hint = ""
491
+
492
+ if signatures :
493
+ header_plain = "\n " .join (signatures )
494
+ elif name_type == "class" :
495
+ header_plain = f"{ hover_type } { name_str } "
496
+ elif type_hint :
497
+ header_plain = f"{ name_str } : { type_hint } "
498
+ else :
499
+ header_plain = f"{ hover_type } { name_str } "
500
+ header = _md_python (header_plain , markup_kind )
501
+
440
502
result : List [str ] = []
441
- if name :
442
- result .append (f"{ _bold ('Name:' , markup_kind )} { name_str } " )
443
- result .append ("" )
503
+ result .append (header )
444
504
if docstring :
505
+ result .append ("---" )
445
506
result .append (convert_docstring (docstring , markup_kind ))
446
- result .append ("" )
447
- if description :
448
- result .append (f"{ _italic ('Desc:' , markup_kind )} { description } " )
449
- if type_hint :
450
- result .append (f"{ _italic ('Type:' , markup_kind )} { type_hint } " )
507
+ elif header_plain .strip ().startswith (description .strip ()):
508
+ pass
509
+ else :
510
+ result .append ("---" )
511
+ result .append (_md_python (description , markup_kind ))
512
+
451
513
if full_name :
452
- result .append (f"{ _italic ('Path:' , markup_kind )} { full_name } " )
514
+ if len (result ) == 1 :
515
+ result .append ("---" )
516
+ result .append (
517
+ _md_bold ("Path:" , markup_kind )
518
+ + " "
519
+ + _md_text_sl (full_name , markup_kind )
520
+ )
453
521
if not result :
454
522
return None
455
523
return "\n " .join (result ).strip ()
0 commit comments