mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 12:05:57 +00:00 
			
		
		
		
	[ty] Provide completions on TypeVars (#20943)
				
					
				
			## Summary closes https://github.com/astral-sh/ty/issues/1370 ## Test Plan New snapshot tests
This commit is contained in:
		
							parent
							
								
									c7e2bfd759
								
							
						
					
					
						commit
						6e7ff07065
					
				
					 2 changed files with 73 additions and 2 deletions
				
			
		|  | @ -3896,6 +3896,55 @@ print(t'''{Foo} and Foo.zqzq<CURSOR> | |||
|         assert_snapshot!(test.completions_without_builtins(), @"<No completions found>"); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn typevar_with_upper_bound() { | ||||
|         let test = cursor_test( | ||||
|             "\ | ||||
| def f[T: str](msg: T): | ||||
|     msg.<CURSOR> | ||||
| ",
 | ||||
|         ); | ||||
|         test.assert_completions_include("upper"); | ||||
|         test.assert_completions_include("capitalize"); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn typevar_with_constraints() { | ||||
|         // Test TypeVar with constraints
 | ||||
|         let test = cursor_test( | ||||
|             "\ | ||||
| from typing import TypeVar | ||||
| 
 | ||||
| class A: | ||||
|     only_on_a: int | ||||
|     on_a_and_b: str | ||||
| 
 | ||||
| class B: | ||||
|     only_on_b: float | ||||
|     on_a_and_b: str | ||||
| 
 | ||||
| T = TypeVar('T', A, B) | ||||
| 
 | ||||
| def f(x: T): | ||||
|     x.<CURSOR> | ||||
| ",
 | ||||
|         ); | ||||
|         test.assert_completions_include("on_a_and_b"); | ||||
|         test.assert_completions_do_not_include("only_on_a"); | ||||
|         test.assert_completions_do_not_include("only_on_b"); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn typevar_without_bounds_or_constraints() { | ||||
|         let test = cursor_test( | ||||
|             "\ | ||||
| def f[T](x: T): | ||||
|     x.<CURSOR> | ||||
| ",
 | ||||
|         ); | ||||
|         test.assert_completions_include("__repr__"); | ||||
|     } | ||||
| 
 | ||||
|     // NOTE: The methods below are getting somewhat ridiculous.
 | ||||
|     // We should refactor this by converting to using a builder
 | ||||
|     // to set different modes. ---AG
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ use crate::types::call::{CallArguments, MatchedArgument}; | |||
| use crate::types::signatures::Signature; | ||||
| use crate::types::{ | ||||
|     ClassBase, ClassLiteral, DynamicType, KnownClass, KnownInstanceType, Type, | ||||
|     class::CodeGeneratorKind, | ||||
|     TypeVarBoundOrConstraints, class::CodeGeneratorKind, | ||||
| }; | ||||
| use crate::{Db, HasType, NameKind, SemanticModel}; | ||||
| use ruff_db::files::{File, FileRange}; | ||||
|  | @ -177,6 +177,29 @@ impl<'db> AllMembers<'db> { | |||
| 
 | ||||
|             Type::TypeAlias(alias) => self.extend_with_type(db, alias.value_type(db)), | ||||
| 
 | ||||
|             Type::TypeVar(bound_typevar) => { | ||||
|                 match bound_typevar.typevar(db).bound_or_constraints(db) { | ||||
|                     None => { | ||||
|                         self.extend_with_type(db, Type::object()); | ||||
|                     } | ||||
|                     Some(TypeVarBoundOrConstraints::UpperBound(bound)) => { | ||||
|                         self.extend_with_type(db, bound); | ||||
|                     } | ||||
|                     Some(TypeVarBoundOrConstraints::Constraints(constraints)) => { | ||||
|                         self.members.extend( | ||||
|                             constraints | ||||
|                                 .elements(db) | ||||
|                                 .iter() | ||||
|                                 .map(|ty| AllMembers::of(db, *ty).members) | ||||
|                                 .reduce(|acc, members| { | ||||
|                                     acc.intersection(&members).cloned().collect() | ||||
|                                 }) | ||||
|                                 .unwrap_or_default(), | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             Type::IntLiteral(_) | ||||
|             | Type::BooleanLiteral(_) | ||||
|             | Type::StringLiteral(_) | ||||
|  | @ -194,7 +217,6 @@ impl<'db> AllMembers<'db> { | |||
|             | Type::ProtocolInstance(_) | ||||
|             | Type::SpecialForm(_) | ||||
|             | Type::KnownInstance(_) | ||||
|             | Type::TypeVar(_) | ||||
|             | Type::BoundSuper(_) | ||||
|             | Type::TypeIs(_) => match ty.to_meta_type(db) { | ||||
|                 Type::ClassLiteral(class_literal) => { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David Peter
						David Peter