@@ -985,9 +985,45 @@ def do_func_def(
985985 _dummy_fallback ,
986986 )
987987
988- # End position is always the same.
989- end_line = getattr (n , "end_lineno" , None )
990- end_column = getattr (n , "end_col_offset" , None )
988+ # We don't want the end positions for functions to include the entire
989+ # body, which is what `ast` gives us; we want to highlight only the
990+ # function signature as the error / note.
991+
992+ # First, check for return typehint
993+ ret = n .returns
994+ if ret is not None :
995+ # There is a return typehint; highlight to the end of it.
996+ end_line = ret .end_lineno
997+ end_column = ret .end_col_offset
998+ elif len (n .body ) > 0 :
999+ # There's no return type, but there is a body (which includes
1000+ # docstrings).
1001+ def_line = n .lineno
1002+ body_line = n .body [0 ].lineno
1003+ if def_line == body_line :
1004+ # Single line definition, e.g. `def foo(): pass`
1005+ # NOTE: this will not highlight the colon in the nonstandard
1006+ # case of `def foo():pass`
1007+ end_line = def_line
1008+ end_column = n .body [0 ].col_offset - 1
1009+ else :
1010+ # "Proper" body starting on a different line after `:`
1011+ # We highlight up to the line in which the body starts
1012+ # but at column 0, effectively ending at the end of the
1013+ # previous line.
1014+ # NOTE: this causes funny highlighting in the non-standard
1015+ # case below:
1016+ #
1017+ # def foo(x: int
1018+ # ): pass
1019+ #
1020+ # The error will show from `d` of `def to `t` of `int`.
1021+ end_line = n .body [0 ].lineno
1022+ end_column = 0
1023+ else :
1024+ # Fall back to whole function.
1025+ end_line = getattr (n , "end_lineno" , None )
1026+ end_column = getattr (n , "end_col_offset" , None )
9911027
9921028 self .class_and_function_stack .pop ()
9931029 self .class_and_function_stack .append ("F" )
0 commit comments