Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change end line and column for untyped function defs to line of function definition #17006

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions mypy/checker.py
Expand Up @@ -1493,6 +1493,9 @@ def is_unannotated_any(t: Type) -> bool:
show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub
check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation
if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs):
# TODO: changing end line and column here changes this information for the node itself
# fdef.end_line = fdef.line
# fdef.end_column = fdef.column + 1
if fdef.type is None and self.options.disallow_untyped_defs:
if not fdef.arguments or (
len(fdef.arguments) == 1
Expand Down
18 changes: 15 additions & 3 deletions mypy/messages.py
Expand Up @@ -256,16 +256,28 @@ def span_from_context(ctx: Context) -> Iterable[int]:
assert origin_span is not None
origin_span = itertools.chain(origin_span, span_from_context(secondary_context))

column = context.column if context else -1
end_line = context.end_line if context else -1
end_column = context.end_column if context else -1

# set end line and column to same as start of context for function definitions
# this avoids errors being reported in IDEs for the whole function
# TODO: figure out if it's possible to find the end of the function definition line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One approach for this could be to add a new attribute to the FuncDef class and set it when we're creating the FuncDef object in fastparse.py.

if isinstance(context, FuncDef):
end_line = context.line
# column is 1-based, see also format_messages in errors.py
end_column = column + 1

self.errors.report(
context.line if context else -1,
context.column if context else -1,
column,
msg,
severity=severity,
file=file,
offset=offset,
origin_span=origin_span,
end_line=context.end_line if context else -1,
end_column=context.end_column if context else -1,
end_line=end_line,
end_column=end_column,
code=code,
allow_dups=allow_dups,
)
Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-columns.test
Expand Up @@ -178,6 +178,18 @@ if int():
def g(x): # E:5: Function is missing a type annotation
pass

[case testColumnEndFunctionMissingTypeAnnotation]
# flags: --disallow-untyped-defs --show-error-end
if int():
def f(x: int):
pass

def g(x):
pass
[out]
main:3:5:3:5: error: Function is missing a return type annotation
main:6:5:6:5: error: Function is missing a type annotation

[case testColumnNameIsNotDefined]
((x)) # E:3: Name "x" is not defined

Expand Down