@@ -500,6 +500,49 @@ def process_docstring(
500500 delattr (app .config , "_annotation_globals" )
501501
502502
503+ def _get_sphinx_line_keyword_and_argument (line : str ) -> tuple [str , str | None ] | None :
504+ """
505+ Extract a keyword, and its optional argument out of a sphinx field option line.
506+
507+ For example
508+ >>> _get_sphinx_line_keyword_and_argument(":param parameter:")
509+ ("param", "parameter")
510+ >>> _get_sphinx_line_keyword_and_argument(":return:")
511+ ("return", None)
512+ >>> _get_sphinx_line_keyword_and_argument("some invalid line")
513+ None
514+ """
515+
516+ param_line_without_description = line .split (":" , maxsplit = 2 ) # noqa: SC200
517+ if len (param_line_without_description ) != 3 :
518+ return None
519+
520+ split_directive_and_name = param_line_without_description [1 ].split (maxsplit = 1 ) # noqa: SC200
521+ if len (split_directive_and_name ) != 2 :
522+ return (split_directive_and_name [0 ], None )
523+
524+ return tuple (split_directive_and_name ) # type: ignore
525+
526+
527+ def _line_is_param_line_for_arg (line : str , arg_name : str ) -> bool :
528+ """Return True if `line` is a valid parameter line for `arg_name`, false otherwise."""
529+ keyword_and_name = _get_sphinx_line_keyword_and_argument (line )
530+ if keyword_and_name is None :
531+ return False
532+
533+ keyword , doc_name = keyword_and_name
534+ if doc_name is None :
535+ return False
536+
537+ if keyword not in {"param" , "parameter" , "arg" , "argument" }:
538+ return False
539+
540+ for prefix in ("" , r"\*" , r"\**" , r"\*\*" ):
541+ if doc_name == prefix + arg_name :
542+ return True
543+ return False
544+
545+
503546def _inject_types_to_docstring (
504547 type_hints : dict [str , Any ],
505548 signature : inspect .Signature | None ,
@@ -521,10 +564,12 @@ def _inject_types_to_docstring(
521564
522565 formatted_annotation = format_annotation (annotation , app .config )
523566
524- search_for = {f":{ field } { arg_name } :" for field in ("param" , "parameter" , "arg" , "argument" )}
525567 insert_index = None
526568 for at , line in enumerate (lines ):
527- if any (line .startswith (search_string ) for search_string in search_for ):
569+ if _line_is_param_line_for_arg (line , arg_name ):
570+ # Get the arg_name from the doc to match up for type in case it has a star prefix.
571+ # Line is in the correct format so this is guaranteed to return tuple[str, str].
572+ _ , arg_name = _get_sphinx_line_keyword_and_argument (line ) # type: ignore[assignment, misc]
528573 insert_index = at
529574 break
530575
0 commit comments