diff --git a/crates/ty_ide/src/completion.rs b/crates/ty_ide/src/completion.rs index 1268482c6c..68cf6a44c3 100644 --- a/crates/ty_ide/src/completion.rs +++ b/crates/ty_ide/src/completion.rs @@ -3212,7 +3212,7 @@ quux. assert_snapshot!( builder.skip_keywords().skip_builtins().type_signatures().build().snapshot(), @r" count :: bound method Quux.count(value: Any, /) -> int - index :: bound method Quux.index(value: Any, start: SupportsIndex = Literal[0], stop: SupportsIndex = int, /) -> int + index :: bound method Quux.index(value: Any, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int x :: int y :: str __add__ :: Overload[(value: tuple[int | str, ...], /) -> tuple[int | str, ...], (value: tuple[_T@__add__, ...], /) -> tuple[int | str | _T@__add__, ...]] diff --git a/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md b/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md index 7841d04f79..c8c42793d0 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md +++ b/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md @@ -144,7 +144,7 @@ from typing import Any def _(a: Any, tuple_of_any: tuple[Any]): reveal_type(inspect.getattr_static(a, "x", "default")) # revealed: Any | Literal["default"] - # revealed: def index(self, value: Any, start: SupportsIndex = Literal[0], stop: SupportsIndex = int, /) -> int + # revealed def index(self, value: Any, start: SupportsIndex = 0, stop: SupportsIndex = int, /) -> int reveal_type(inspect.getattr_static(tuple_of_any, "index", "default")) ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/methods.md b/crates/ty_python_semantic/resources/mdtest/call/methods.md index eb02c134f3..74eecad4fb 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/methods.md +++ b/crates/ty_python_semantic/resources/mdtest/call/methods.md @@ -600,9 +600,9 @@ from typing_extensions import Self reveal_type(object.__new__) # revealed: def __new__(cls) -> Self@__new__ reveal_type(object().__new__) # revealed: def __new__(cls) -> Self@__new__ -# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = Literal[0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__] +# revealed Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = 0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__ reveal_type(int.__new__) -# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = Literal[0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__] +# revealed Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = 0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__ reveal_type((42).__new__) class X: diff --git a/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md b/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md index 60bfd36176..3e8837aba6 100644 --- a/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md +++ b/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md @@ -69,7 +69,7 @@ class D: y: str = "default" z: int | None = 1 + 2 -reveal_type(D.__init__) # revealed: (self: D, x: int, y: str = Literal["default"], z: int | None = Literal[3]) -> None +reveal_type(D.__init__) # revealed: (self: D, x: int, y: str = "default", z: int | None = 3) -> None ``` This also works if the declaration and binding are split: @@ -221,7 +221,7 @@ class D: (x): int = 1 # TODO: should ideally not include a `x` parameter -reveal_type(D.__init__) # revealed: (self: D, x: int = Literal[1]) -> None +reveal_type(D.__init__) # revealed (self: D, x: int = 1) -> None ``` ## `@dataclass` calls with arguments @@ -670,7 +670,7 @@ class A: a: str = field(kw_only=False) b: int = 0 -reveal_type(A.__init__) # revealed: (self: A, a: str, *, b: int = Literal[0]) -> None +reveal_type(A.__init__) # revealed (self: A, a: str, *, b: int = 0) -> None A("hi") ``` @@ -991,7 +991,7 @@ class C: class_variable1: ClassVar[Final[int]] = 1 class_variable2: ClassVar[Final[int]] = 1 -reveal_type(C.__init__) # revealed: (self: C, instance_variable_no_default: int, instance_variable: int = Literal[1]) -> None +reveal_type(C.__init__) # revealed (self: C, instance_variable_no_default: int, instance_variable: int = 1) -> None c = C(1) # error: [invalid-assignment] "Cannot assign to final attribute `instance_variable` on type `C`" @@ -1082,7 +1082,7 @@ class C(Base): z: int = 10 x: int = 15 -reveal_type(C.__init__) # revealed: (self: C, x: int = Literal[15], y: int = Literal[0], z: int = Literal[10]) -> None +reveal_type(C.__init__) # revealed (self: C, x: int = Literal[15], y: int = Literal[0], z: int = 10) -> None ``` ## Conditionally defined fields @@ -1289,7 +1289,7 @@ class ConvertToLength: class C: converter: ConvertToLength = ConvertToLength() -reveal_type(C.__init__) # revealed: (self: C, converter: str = Literal[""]) -> None +reveal_type(C.__init__) # revealed: (self: C, converter: str = "") -> None c = C("abc") reveal_type(c.converter) # revealed: int diff --git a/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md b/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md index 28a69081e5..64c95d47a6 100644 --- a/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md +++ b/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md @@ -11,7 +11,7 @@ class Member: role: str = field(default="user") tag: str | None = field(default=None, init=False) -# revealed: (self: Member, name: str, role: str = Literal["user"]) -> None +# revealed: (self: Member, name: str, role: str = "user") -> None reveal_type(Member.__init__) alice = Member(name="Alice", role="admin") @@ -63,7 +63,7 @@ class Person: age: int | None = field(default=None, kw_only=True) role: str = field(default="user", kw_only=True) -# revealed: (self: Person, name: str, *, age: int | None = None, role: str = Literal["user"]) -> None +# revealed: (self: Person, name: str, *, age: int | None = None, role: str = "user") -> None reveal_type(Person.__init__) alice = Person(role="admin", name="Alice") diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/paramspec.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/paramspec.md index e6e6acd35c..c3373c9118 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/paramspec.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/paramspec.md @@ -477,7 +477,7 @@ def keyword_only_with_default_2(*, y: int = 42) -> int: # parameter list i.e., `()` # TODO: This shouldn't error # error: [invalid-argument-type] -# revealed: (*, x: int = Literal[42]) -> bool +# revealed (*, x: int = 42) -> bool reveal_type(multiple(keyword_only_with_default_1, keyword_only_with_default_2)) def keyword_only1(*, x: int) -> int: diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/missing_argument.md_-_Missing_argument_dia…_(f0811e84fcea1085).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/missing_argument.md_-_Missing_argument_dia…_(f0811e84fcea1085).snap index 5311a64551..b29da05ac4 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/missing_argument.md_-_Missing_argument_dia…_(f0811e84fcea1085).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/missing_argument.md_-_Missing_argument_dia…_(f0811e84fcea1085).snap @@ -73,8 +73,8 @@ error[missing-argument]: No argument provided for required parameter `a` of func 13 | 14 | Foo().method() # error: [missing-argument] | -info: Union variant `def f(a, b=Literal[42]) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Union variant `def f(a, b=42) -> Unknown` is incompatible with this call site +info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `missing-argument` is enabled by default ``` @@ -91,7 +91,7 @@ error[missing-argument]: No argument provided for required parameter `a` of func 14 | Foo().method() # error: [missing-argument] | info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `missing-argument` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/too_many_positionals…_-_too-many-positional-…_(eafa522239b42502).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/too_many_positionals…_-_too-many-positional-…_(eafa522239b42502).snap index 85d54b772b..661f46ac0b 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/too_many_positionals…_-_too-many-positional-…_(eafa522239b42502).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/too_many_positionals…_-_too-many-positional-…_(eafa522239b42502).snap @@ -73,8 +73,8 @@ error[too-many-positional-arguments]: Too many positional arguments to function 13 | 14 | Foo().method(1, 2) # error: [too-many-positional-arguments] | -info: Union variant `def f(a, b=Literal[42]) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Union variant `def f(a, b=42) -> Unknown` is incompatible with this call site +info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `too-many-positional-arguments` is enabled by default ``` @@ -91,7 +91,7 @@ error[too-many-positional-arguments]: Too many positional arguments to function 14 | Foo().method(1, 2) # error: [too-many-positional-arguments] | info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `too-many-positional-arguments` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/unknown_argument.md_-_Unknown_argument_dia…_(f419c2a8e2ce2412).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/unknown_argument.md_-_Unknown_argument_dia…_(f419c2a8e2ce2412).snap index e311271fe8..2e384bd517 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/unknown_argument.md_-_Unknown_argument_dia…_(f419c2a8e2ce2412).snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/unknown_argument.md_-_Unknown_argument_dia…_(f419c2a8e2ce2412).snap @@ -73,8 +73,8 @@ error[unknown-argument]: Argument `d` does not match any known parameter of func 13 | 14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument] | -info: Union variant `def f(a, b, c=Literal[42]) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b, c=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Union variant `def f(a, b, c=42) -> Unknown` is incompatible with this call site +info: Attempted to call union type `(def f(a, b, c=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `unknown-argument` is enabled by default ``` @@ -91,7 +91,7 @@ error[unknown-argument]: Argument `d` does not match any known parameter of func 14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument] | info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site -info: Attempted to call union type `(def f(a, b, c=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)` +info: Attempted to call union type `(def f(a, b, c=42) -> Unknown) | (def g(a, b) -> Unknown)` info: rule `unknown-argument` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/initvar.md b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/initvar.md index 7d6c14b1c6..77478861b0 100644 --- a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/initvar.md +++ b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/initvar.md @@ -67,7 +67,7 @@ class Person: metadata: InitVar[str] = "default" -reveal_type(Person.__init__) # revealed: (self: Person, name: str, age: int, metadata: str = Literal["default"]) -> None +reveal_type(Person.__init__) # revealed: (self: Person, name: str, age: int, metadata: str = "default") -> None alice = Person("Alice", 30) bob = Person("Bob", 25, "custom metadata") diff --git a/crates/ty_python_semantic/src/types/display.rs b/crates/ty_python_semantic/src/types/display.rs index 885c9cb7f0..539d3dcec2 100644 --- a/crates/ty_python_semantic/src/types/display.rs +++ b/crates/ty_python_semantic/src/types/display.rs @@ -1838,13 +1838,20 @@ impl<'db> FmtDetailed<'db> for DisplayParameter<'_, 'db> { } } // Default value can only be specified if `name` is given. - if let Some(default_ty) = self.param.default_type() { + if let Some(default_value) = self.param.default_value() { if self.param.annotated_type().is_some() { f.write_str(" = ")?; } else { f.write_str("=")?; } - default_ty + write!(f, "{default_value}")?; + } else if let Some(default_type) = self.param.default_type() { + if self.param.annotated_type().is_some() { + f.write_str(" = ")?; + } else { + f.write_str("=")?; + } + default_type .display_with(self.db, self.settings.clone()) .fmt_detailed(f)?; } @@ -2683,9 +2690,7 @@ mod tests { ], Some(KnownClass::Bytes.to_instance(&db)) ), - @"(a, b: int, c=Literal[1], d: int = Literal[2], \ - /, e=Literal[3], f: int = Literal[4], *args: object, \ - *, g=Literal[5], h: int = Literal[6], **kwargs: str) -> bytes" + @"(a, b: int, c=Literal[1], d: int = Literal[2], /, e=Literal[3], f: int = Literal[4], *args: object, *, g=Literal[5], h: int = Literal[6], **kwargs: str) -> bytes" ); } diff --git a/crates/ty_python_semantic/src/types/signatures.rs b/crates/ty_python_semantic/src/types/signatures.rs index dd6fe02334..370bb0a84e 100644 --- a/crates/ty_python_semantic/src/types/signatures.rs +++ b/crates/ty_python_semantic/src/types/signatures.rs @@ -917,10 +917,12 @@ impl<'db> Signature<'db> { ParameterKind::PositionalOrKeyword { name: self_name, default_type: self_default, + default_value: _, }, ParameterKind::PositionalOrKeyword { name: other_name, default_type: other_default, + default_value: _, }, ) if self_default.is_some() == other_default.is_some() && self_name == other_name => {} @@ -931,10 +933,12 @@ impl<'db> Signature<'db> { ParameterKind::KeywordOnly { name: self_name, default_type: self_default, + default_value: _, }, ParameterKind::KeywordOnly { name: other_name, default_type: other_default, + default_value: _, }, ) if self_default.is_some() == other_default.is_some() && self_name == other_name => {} @@ -1218,10 +1222,12 @@ impl<'db> Signature<'db> { ParameterKind::PositionalOrKeyword { name: self_name, default_type: self_default, + default_value: _, }, ParameterKind::PositionalOrKeyword { name: other_name, default_type: other_default, + default_value: _, }, ) => { if self_name != other_name { @@ -1359,10 +1365,12 @@ impl<'db> Signature<'db> { ParameterKind::KeywordOnly { name: other_name, default_type: other_default, + default_value: _, } | ParameterKind::PositionalOrKeyword { name: other_name, default_type: other_default, + default_value: _, } => { if let Some(self_parameter) = self_keywords.remove(other_name.as_str()) { match self_parameter.kind() { @@ -1689,6 +1697,15 @@ impl<'db> Parameters<'db> { }; let pos_only_param = |param: &ast::ParameterWithDefault| { + let mut default_value = None; + if let Some(default) = ¶m.default { + use ruff_text_size::Ranged; + let file = definition.file(db); + let source = ruff_db::source::source_text(db, file); + let text = source.as_str().get(default.range().to_std_range()); + default_value = text.map(Box::from); + } + Parameter::from_node_and_kind( db, definition, @@ -1696,6 +1713,7 @@ impl<'db> Parameters<'db> { ParameterKind::PositionalOnly { name: Some(param.parameter.name.id.clone()), default_type: default_type(param), + default_value, }, ) }; @@ -1721,6 +1739,15 @@ impl<'db> Parameters<'db> { } let positional_or_keyword = pos_or_keyword_iter.map(|arg| { + let mut default_value = None; + if let Some(default) = &arg.default { + use ruff_text_size::Ranged; + let file = definition.file(db); + let source = ruff_db::source::source_text(db, file); + let text = source.as_str().get(default.range().to_std_range()); + default_value = text.map(Box::from); + } + Parameter::from_node_and_kind( db, definition, @@ -1728,6 +1755,7 @@ impl<'db> Parameters<'db> { ParameterKind::PositionalOrKeyword { name: arg.parameter.name.id.clone(), default_type: default_type(arg), + default_value, }, ) }); @@ -1744,6 +1772,15 @@ impl<'db> Parameters<'db> { }); let keyword_only = kwonlyargs.iter().map(|arg| { + let mut default_value = None; + if let Some(default) = &arg.default { + use ruff_text_size::Ranged; + let file = definition.file(db); + let source = ruff_db::source::source_text(db, file); + let text = source.as_str().get(default.range().to_std_range()); + default_value = text.map(Box::from); + } + Parameter::from_node_and_kind( db, definition, @@ -1751,6 +1788,7 @@ impl<'db> Parameters<'db> { ParameterKind::KeywordOnly { name: arg.parameter.name.id.clone(), default_type: default_type(arg), + default_value, }, ) }); @@ -1914,6 +1952,7 @@ impl<'db> Parameter<'db> { kind: ParameterKind::PositionalOnly { name, default_type: None, + default_value: None, }, form: ParameterForm::Value, } @@ -1926,6 +1965,7 @@ impl<'db> Parameter<'db> { kind: ParameterKind::PositionalOrKeyword { name, default_type: None, + default_value: None, }, form: ParameterForm::Value, } @@ -1947,6 +1987,7 @@ impl<'db> Parameter<'db> { kind: ParameterKind::KeywordOnly { name, default_type: None, + default_value: None, }, form: ParameterForm::Value, } @@ -2033,19 +2074,29 @@ impl<'db> Parameter<'db> { ParameterKind::PositionalOnly { name: _, default_type, + default_value, } => ParameterKind::PositionalOnly { name: None, default_type: default_type.map(|_| Type::Never), + default_value: default_value.clone(), }, - ParameterKind::PositionalOrKeyword { name, default_type } => { - ParameterKind::PositionalOrKeyword { - name: name.clone(), - default_type: default_type.map(|_| Type::Never), - } - } - ParameterKind::KeywordOnly { name, default_type } => ParameterKind::KeywordOnly { + ParameterKind::PositionalOrKeyword { + name, + default_type, + default_value, + } => ParameterKind::PositionalOrKeyword { name: name.clone(), default_type: default_type.map(|_| Type::Never), + default_value: default_value.clone(), + }, + ParameterKind::KeywordOnly { + name, + default_type, + default_value, + } => ParameterKind::KeywordOnly { + name: name.clone(), + default_type: default_type.map(|_| Type::Never), + default_value: default_value.clone(), }, ParameterKind::Variadic { name: _ } => ParameterKind::Variadic { name: Name::new_static("args"), @@ -2086,7 +2137,11 @@ impl<'db> Parameter<'db> { }; let kind = match kind { - ParameterKind::PositionalOnly { name, default_type } => ParameterKind::PositionalOnly { + ParameterKind::PositionalOnly { + name, + default_type, + default_value, + } => ParameterKind::PositionalOnly { name: name.clone(), default_type: match default_type { Some(ty) if nested => Some(ty.recursive_type_normalized_impl(db, div, true)?), @@ -2096,23 +2151,13 @@ impl<'db> Parameter<'db> { ), None => None, }, + default_value: default_value.clone(), }, - ParameterKind::PositionalOrKeyword { name, default_type } => { - ParameterKind::PositionalOrKeyword { - name: name.clone(), - default_type: match default_type { - Some(ty) if nested => { - Some(ty.recursive_type_normalized_impl(db, div, true)?) - } - Some(ty) => Some( - ty.recursive_type_normalized_impl(db, div, true) - .unwrap_or(div), - ), - None => None, - }, - } - } - ParameterKind::KeywordOnly { name, default_type } => ParameterKind::KeywordOnly { + ParameterKind::PositionalOrKeyword { + name, + default_type, + default_value, + } => ParameterKind::PositionalOrKeyword { name: name.clone(), default_type: match default_type { Some(ty) if nested => Some(ty.recursive_type_normalized_impl(db, div, true)?), @@ -2122,6 +2167,23 @@ impl<'db> Parameter<'db> { ), None => None, }, + default_value: default_value.clone(), + }, + ParameterKind::KeywordOnly { + name, + default_type, + default_value, + } => ParameterKind::KeywordOnly { + name: name.clone(), + default_type: match default_type { + Some(ty) if nested => Some(ty.recursive_type_normalized_impl(db, div, true)?), + Some(ty) => Some( + ty.recursive_type_normalized_impl(db, div, true) + .unwrap_or(div), + ), + None => None, + }, + default_value: default_value.clone(), }, ParameterKind::Variadic { name } => ParameterKind::Variadic { name: name.clone() }, ParameterKind::KeywordVariadic { name } => { @@ -2238,9 +2300,19 @@ impl<'db> Parameter<'db> { ParameterKind::Variadic { .. } | ParameterKind::KeywordVariadic { .. } => None, } } + + /// Default-value of the parameter, if any. + pub(crate) fn default_value(&self) -> Option<&str> { + match &self.kind { + ParameterKind::PositionalOnly { default_value, .. } + | ParameterKind::PositionalOrKeyword { default_value, .. } + | ParameterKind::KeywordOnly { default_value, .. } => default_value.as_deref(), + ParameterKind::Variadic { .. } | ParameterKind::KeywordVariadic { .. } => None, + } + } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, salsa::Update, get_size2::GetSize)] +#[derive(Clone, Debug, salsa::Update, get_size2::GetSize)] pub enum ParameterKind<'db> { /// Positional-only parameter, e.g. `def f(x, /): ...` PositionalOnly { @@ -2250,6 +2322,7 @@ pub enum ParameterKind<'db> { /// nameless (e.g. via `Callable` annotations). name: Option, default_type: Option>, + default_value: Option>, }, /// Positional-or-keyword parameter, e.g. `def f(x): ...` @@ -2257,6 +2330,7 @@ pub enum ParameterKind<'db> { /// Parameter name. name: Name, default_type: Option>, + default_value: Option>, }, /// Variadic parameter, e.g. `def f(*args): ...` @@ -2270,6 +2344,7 @@ pub enum ParameterKind<'db> { /// Parameter name. name: Name, default_type: Option>, + default_value: Option>, }, /// Variadic keywords parameter, e.g. `def f(**kwargs): ...` @@ -2279,6 +2354,94 @@ pub enum ParameterKind<'db> { }, } +impl PartialEq for ParameterKind<'_> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::PositionalOnly { + name: l_name, + default_type: l_default_type, + default_value: _, + }, + Self::PositionalOnly { + name: r_name, + default_type: r_default_type, + default_value: _, + }, + ) => l_name == r_name && l_default_type == r_default_type, + ( + Self::PositionalOrKeyword { + name: l_name, + default_type: l_default_type, + default_value: _, + }, + Self::PositionalOrKeyword { + name: r_name, + default_type: r_default_type, + default_value: _, + }, + ) => l_name == r_name && l_default_type == r_default_type, + (Self::Variadic { name: l_name }, Self::Variadic { name: r_name }) => l_name == r_name, + ( + Self::KeywordOnly { + name: l_name, + default_type: l_default_type, + default_value: _, + }, + Self::KeywordOnly { + name: r_name, + default_type: r_default_type, + default_value: _, + }, + ) => l_name == r_name && l_default_type == r_default_type, + (Self::KeywordVariadic { name: l_name }, Self::KeywordVariadic { name: r_name }) => { + l_name == r_name + } + _ => false, + } + } +} + +impl Eq for ParameterKind<'_> {} + +impl std::hash::Hash for ParameterKind<'_> { + fn hash(&self, state: &mut H) { + core::mem::discriminant(self).hash(state); + match self { + ParameterKind::PositionalOnly { + name, + default_type, + default_value: _, + } => { + name.hash(state); + default_type.hash(state); + } + ParameterKind::PositionalOrKeyword { + name, + default_type, + default_value: _, + } => { + name.hash(state); + default_type.hash(state); + } + ParameterKind::Variadic { name } => { + name.hash(state); + } + ParameterKind::KeywordOnly { + name, + default_type, + default_value: _, + } => { + name.hash(state); + default_type.hash(state); + } + ParameterKind::KeywordVariadic { name } => { + name.hash(state); + } + } + } +} + impl<'db> ParameterKind<'db> { fn apply_type_mapping_impl<'a>( &self, @@ -2298,16 +2461,31 @@ impl<'db> ParameterKind<'db> { }; match self { - Self::PositionalOnly { default_type, name } => Self::PositionalOnly { + Self::PositionalOnly { + default_type, + default_value, + name, + } => Self::PositionalOnly { default_type: apply_to_default_type(default_type), + default_value: default_value.clone(), name: name.clone(), }, - Self::PositionalOrKeyword { default_type, name } => Self::PositionalOrKeyword { + Self::PositionalOrKeyword { + default_type, + default_value, + name, + } => Self::PositionalOrKeyword { default_type: apply_to_default_type(default_type), + default_value: default_value.clone(), name: name.clone(), }, - Self::KeywordOnly { default_type, name } => Self::KeywordOnly { + Self::KeywordOnly { + default_type, + default_value, + name, + } => Self::KeywordOnly { default_type: apply_to_default_type(default_type), + default_value: default_value.clone(), name: name.clone(), }, Self::Variadic { .. } | Self::KeywordVariadic { .. } => self.clone(), diff --git a/crates/ty_server/tests/e2e/snapshots/e2e__signature_help__works_in_function_name.snap b/crates/ty_server/tests/e2e/snapshots/e2e__signature_help__works_in_function_name.snap index 19e4d2d1b0..624472d058 100644 --- a/crates/ty_server/tests/e2e/snapshots/e2e__signature_help__works_in_function_name.snap +++ b/crates/ty_server/tests/e2e/snapshots/e2e__signature_help__works_in_function_name.snap @@ -5,7 +5,7 @@ expression: signature_help { "signatures": [ { - "label": "(pattern: str | Pattern[str], string: str, flags: int = Literal[0]) -> Match[str] | None", + "label": "(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None", "documentation": "Try to apply the pattern at the start of the string, returning/na Match object, or None if no match was found.\n", "parameters": [ { @@ -15,12 +15,12 @@ expression: signature_help "label": "string: str" }, { - "label": "flags: int = Literal[0]" + "label": "flags: int = 0" } ] }, { - "label": "(pattern: bytes | Pattern[bytes], string: Buffer, flags: int = Literal[0]) -> Match[bytes] | None", + "label": "(pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None", "parameters": [ { "label": "pattern: bytes | Pattern[bytes]" @@ -29,7 +29,7 @@ expression: signature_help "label": "string: Buffer" }, { - "label": "flags: int = Literal[0]" + "label": "flags: int = 0" } ] }