mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-29 19:17:20 +00:00
[ty] display variance on hover over type variables (#20900)
This commit is contained in:
parent
0520d11a66
commit
a7c38eb122
6 changed files with 528 additions and 48 deletions
|
|
@ -11,6 +11,7 @@ use crate::{
|
|||
semantic_index::{
|
||||
SemanticIndex, reachability_constraints::ScopedReachabilityConstraintId, semantic_index,
|
||||
},
|
||||
types::{GenericContext, binding_type, infer_definition_types},
|
||||
};
|
||||
|
||||
/// A cross-module identifier of a scope that can be used as a salsa query parameter.
|
||||
|
|
@ -430,6 +431,38 @@ impl NodeWithScopeKind {
|
|||
pub(crate) fn expect_type_alias(&self) -> &AstNodeRef<ast::StmtTypeAlias> {
|
||||
self.as_type_alias().expect("expected type alias")
|
||||
}
|
||||
|
||||
pub(crate) fn generic_context<'db>(
|
||||
&self,
|
||||
db: &'db dyn Db,
|
||||
index: &SemanticIndex<'db>,
|
||||
) -> Option<GenericContext<'db>> {
|
||||
match self {
|
||||
NodeWithScopeKind::Class(class) => {
|
||||
let definition = index.expect_single_definition(class);
|
||||
binding_type(db, definition)
|
||||
.as_class_literal()?
|
||||
.generic_context(db)
|
||||
}
|
||||
NodeWithScopeKind::Function(function) => {
|
||||
let definition = index.expect_single_definition(function);
|
||||
infer_definition_types(db, definition)
|
||||
.undecorated_type()
|
||||
.expect("function should have undecorated type")
|
||||
.as_function_literal()?
|
||||
.last_definition_signature(db)
|
||||
.generic_context
|
||||
}
|
||||
NodeWithScopeKind::TypeAlias(type_alias) => {
|
||||
let definition = index.expect_single_definition(type_alias);
|
||||
binding_type(db, definition)
|
||||
.as_type_alias()?
|
||||
.as_pep_695_type_alias()?
|
||||
.generic_context(db)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, get_size2::GetSize)]
|
||||
|
|
|
|||
|
|
@ -479,6 +479,7 @@ impl_binding_has_ty_def!(ast::StmtClassDef);
|
|||
impl_binding_has_ty_def!(ast::Parameter);
|
||||
impl_binding_has_ty_def!(ast::ParameterWithDefault);
|
||||
impl_binding_has_ty_def!(ast::ExceptHandlerExceptHandler);
|
||||
impl_binding_has_ty_def!(ast::TypeParamTypeVar);
|
||||
|
||||
impl HasType for ast::Alias {
|
||||
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ pub(crate) use crate::types::narrow::infer_narrowing_constraint;
|
|||
use crate::types::signatures::{ParameterForm, walk_signature};
|
||||
use crate::types::tuple::{TupleSpec, TupleSpecBuilder};
|
||||
pub(crate) use crate::types::typed_dict::{TypedDictParams, TypedDictType, walk_typed_dict_type};
|
||||
use crate::types::variance::{TypeVarVariance, VarianceInferable};
|
||||
pub use crate::types::variance::TypeVarVariance;
|
||||
use crate::types::variance::VarianceInferable;
|
||||
use crate::types::visitor::any_over_type;
|
||||
use crate::unpack::EvaluationMode;
|
||||
use crate::{Db, FxOrderSet, Module, Program};
|
||||
|
|
@ -8394,6 +8395,21 @@ impl<'db> TypeVarInstance<'db> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_pep695(self, db: &'db dyn Db) -> Option<BoundTypeVarInstance<'db>> {
|
||||
if self.identity(db).kind(db) != TypeVarKind::Pep695 {
|
||||
return None;
|
||||
}
|
||||
let typevar_definition = self.definition(db)?;
|
||||
let index = semantic_index(db, typevar_definition.file(db));
|
||||
let (_, child) = index
|
||||
.child_scopes(typevar_definition.file_scope(db))
|
||||
.next()?;
|
||||
child
|
||||
.node()
|
||||
.generic_context(db, index)?
|
||||
.binds_typevar(db, self)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::ref_option)]
|
||||
|
|
@ -8544,7 +8560,7 @@ impl<'db> BoundTypeVarInstance<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn variance(self, db: &'db dyn Db) -> TypeVarVariance {
|
||||
pub fn variance(self, db: &'db dyn Db) -> TypeVarVariance {
|
||||
self.variance_with_polarity(db, TypeVarVariance::Covariant)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use crate::semantic_index::{SemanticIndex, semantic_index};
|
|||
use crate::types::class::ClassType;
|
||||
use crate::types::class_base::ClassBase;
|
||||
use crate::types::constraints::ConstraintSet;
|
||||
use crate::types::infer::infer_definition_types;
|
||||
use crate::types::instance::{Protocol, ProtocolInstanceType};
|
||||
use crate::types::signatures::{Parameter, Parameters, Signature};
|
||||
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
|
||||
|
|
@ -21,8 +20,7 @@ use crate::types::{
|
|||
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor,
|
||||
KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeContext,
|
||||
TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarIdentity, TypeVarInstance,
|
||||
TypeVarKind, TypeVarVariance, UnionType, binding_type, declaration_type,
|
||||
walk_bound_type_var_type,
|
||||
TypeVarKind, TypeVarVariance, UnionType, declaration_type, walk_bound_type_var_type,
|
||||
};
|
||||
use crate::{Db, FxIndexSet, FxOrderMap, FxOrderSet};
|
||||
|
||||
|
|
@ -35,31 +33,7 @@ pub(crate) fn enclosing_generic_contexts<'db>(
|
|||
) -> impl Iterator<Item = GenericContext<'db>> {
|
||||
index
|
||||
.ancestor_scopes(scope)
|
||||
.filter_map(|(_, ancestor_scope)| match ancestor_scope.node() {
|
||||
NodeWithScopeKind::Class(class) => {
|
||||
let definition = index.expect_single_definition(class);
|
||||
binding_type(db, definition)
|
||||
.as_class_literal()?
|
||||
.generic_context(db)
|
||||
}
|
||||
NodeWithScopeKind::Function(function) => {
|
||||
let definition = index.expect_single_definition(function);
|
||||
infer_definition_types(db, definition)
|
||||
.undecorated_type()
|
||||
.expect("function should have undecorated type")
|
||||
.as_function_literal()?
|
||||
.last_definition_signature(db)
|
||||
.generic_context
|
||||
}
|
||||
NodeWithScopeKind::TypeAlias(type_alias) => {
|
||||
let definition = index.expect_single_definition(type_alias);
|
||||
binding_type(db, definition)
|
||||
.as_type_alias()?
|
||||
.as_pep_695_type_alias()?
|
||||
.generic_context(db)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|(_, ancestor_scope)| ancestor_scope.node().generic_context(db, index))
|
||||
}
|
||||
|
||||
/// Binds an unbound typevar.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue