withered-magic / starpls

An LSP implementation for Starlark, the configuration language used by Bazel and Buck2.
Apache License 2.0
98 stars 10 forks source link

(Possibly) incorrect handling of type comments for non-variadic function with keyword-only parameters #257

Open Strum355 opened 3 months ago

Strum355 commented 3 months ago

(Discovered upon using bazel_env here: https://github.com/buildbuddy-io/bazel_env.bzl/blob/main/bazel_env.bzl#L339)

Given the function def bazel_env(*, name, tools = {}, toolchains = {}, **kwargs): with the type comment # type: (string, dict[string, string | Label], dict[string, string | Label]) -> None, starpls treats the * as being of type string, name as dict[string, string | Label] etc.

From the Starlark spec on fuction signatures:

A non-variadic function may also declare keyword-only parameters, by using a bare in place of the args parameter. This form does not declare a parameter but marks the boundary between the earlier parameters and the keyword-only parameters. This form must be followed by at least one optional parameter.

withered-magic commented 3 months ago

Ah, I ended up just copying the behavior from Pyright here, which emits an error diagnostic if the bare * parameter isn't annotated, e.g.

def foo(*, x):
    # type: (str) -> None
    pass

yields

Parameter annotation count mismatch: expected 2 but received 1

while

def foo(*, x):
    # type: (None, str) -> None
    pass

seems to make Pyright happy.

withered-magic commented 3 months ago

I'll take a look through the pep 484 doc again and see if it says anything about annotating * parameters