mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	minor: Suggest better names when a type is a sequence
Previously, we'd suggest a type of `vec` for a value of type `Vec<T>`, which is rarely what the user wants. We also had no suggestions for values of type `&[T]`. Instead, try to pluralise the inner type name, and fall back to `items`.
This commit is contained in:
		
							parent
							
								
									6e4c29f7ce
								
							
						
					
					
						commit
						4c34352517
					
				
					 2 changed files with 93 additions and 10 deletions
				
			
		|  | @ -1672,8 +1672,8 @@ macro_rules! vec { | ||||||
|     () => {Vec} |     () => {Vec} | ||||||
| } | } | ||||||
| fn main() { | fn main() { | ||||||
|     let $0vec = vec![]; |     let $0items = vec![]; | ||||||
|     let _ = vec; |     let _ = items; | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|             "Extract into variable", |             "Extract into variable", | ||||||
|  | @ -1696,8 +1696,8 @@ macro_rules! vec { | ||||||
|     () => {Vec} |     () => {Vec} | ||||||
| } | } | ||||||
| fn main() { | fn main() { | ||||||
|     const $0VEC: Vec = vec![]; |     const $0ITEMS: Vec = vec![]; | ||||||
|     let _ = VEC; |     let _ = ITEMS; | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|             "Extract into constant", |             "Extract into constant", | ||||||
|  | @ -1720,8 +1720,8 @@ macro_rules! vec { | ||||||
|     () => {Vec} |     () => {Vec} | ||||||
| } | } | ||||||
| fn main() { | fn main() { | ||||||
|     static $0VEC: Vec = vec![]; |     static $0ITEMS: Vec = vec![]; | ||||||
|     let _ = VEC; |     let _ = ITEMS; | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|             "Extract into static", |             "Extract into static", | ||||||
|  | @ -2019,8 +2019,8 @@ impl<T> Vec<T> { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn foo(s: &mut S) { | fn foo(s: &mut S) { | ||||||
|     let $0vec = &mut s.vec; |     let $0items = &mut s.vec; | ||||||
|     vec.push(0); |     items.push(0); | ||||||
| }"#,
 | }"#,
 | ||||||
|             "Extract into variable", |             "Extract into variable", | ||||||
|         ); |         ); | ||||||
|  | @ -2106,8 +2106,8 @@ impl<T> Vec<T> { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn foo(f: &mut Y) { | fn foo(f: &mut Y) { | ||||||
|     let $0vec = &mut f.field.field.vec; |     let $0items = &mut f.field.field.vec; | ||||||
|     vec.push(0); |     items.push(0); | ||||||
| }"#,
 | }"#,
 | ||||||
|             "Extract into variable", |             "Extract into variable", | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|  | @ -31,6 +31,12 @@ const USELESS_NAME_PREFIXES: &[&str] = &["from_", "with_", "into_"]; | ||||||
| /// `Result<User, Error>` -> `User`
 | /// `Result<User, Error>` -> `User`
 | ||||||
| const WRAPPER_TYPES: &[&str] = &["Box", "Arc", "Rc", "Option", "Result"]; | const WRAPPER_TYPES: &[&str] = &["Box", "Arc", "Rc", "Option", "Result"]; | ||||||
| 
 | 
 | ||||||
|  | /// Generic types replaced by a plural of their first argument.
 | ||||||
|  | ///
 | ||||||
|  | /// # Examples
 | ||||||
|  | /// `Vec<Name>` -> "names"
 | ||||||
|  | const SEQUENCE_TYPES: &[&str] = &["Vec", "VecDeque", "LinkedList"]; | ||||||
|  | 
 | ||||||
| /// Prefixes to strip from methods names
 | /// Prefixes to strip from methods names
 | ||||||
| ///
 | ///
 | ||||||
| /// # Examples
 | /// # Examples
 | ||||||
|  | @ -378,6 +384,11 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S | ||||||
|             return name_of_type(&inner_ty, db, edition); |             return name_of_type(&inner_ty, db, edition); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if SEQUENCE_TYPES.contains(&name.as_str()) { | ||||||
|  |             let inner_ty = ty.type_arguments().next(); | ||||||
|  |             return Some(sequence_name(inner_ty.as_ref(), db, edition)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         name |         name | ||||||
|     } else if let Some(trait_) = ty.as_dyn_trait() { |     } else if let Some(trait_) = ty.as_dyn_trait() { | ||||||
|         trait_name(&trait_, db, edition)? |         trait_name(&trait_, db, edition)? | ||||||
|  | @ -390,12 +401,32 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S | ||||||
|         name |         name | ||||||
|     } else if let Some(inner_ty) = ty.remove_ref() { |     } else if let Some(inner_ty) = ty.remove_ref() { | ||||||
|         return name_of_type(&inner_ty, db, edition); |         return name_of_type(&inner_ty, db, edition); | ||||||
|  |     } else if let Some(inner_ty) = ty.as_slice() { | ||||||
|  |         return Some(sequence_name(Some(&inner_ty), db, edition)); | ||||||
|     } else { |     } else { | ||||||
|         return None; |         return None; | ||||||
|     }; |     }; | ||||||
|     normalize(&name) |     normalize(&name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn sequence_name(inner_ty: Option<&hir::Type>, db: &RootDatabase, edition: Edition) -> SmolStr { | ||||||
|  |     let items_str = SmolStr::new_static("items"); | ||||||
|  |     let Some(inner_ty) = inner_ty else { | ||||||
|  |         return items_str; | ||||||
|  |     }; | ||||||
|  |     let Some(name) = name_of_type(inner_ty, db, edition) else { | ||||||
|  |         return items_str; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     if name.ends_with(['s', 'x', 'y']) { | ||||||
|  |         // Given a type called e.g. "Boss", "Fox" or "Story", don't try to
 | ||||||
|  |         // create a plural.
 | ||||||
|  |         items_str | ||||||
|  |     } else { | ||||||
|  |         SmolStr::new(format!("{name}s")) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Option<String> { | fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Option<String> { | ||||||
|     let name = trait_.name(db).display(db, edition).to_string(); |     let name = trait_.name(db).display(db, edition).to_string(); | ||||||
|     if USELESS_TRAITS.contains(&name.as_str()) { |     if USELESS_TRAITS.contains(&name.as_str()) { | ||||||
|  | @ -897,6 +928,58 @@ fn foo() { $0(bar())$0; } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn vec_value() { | ||||||
|  |         check( | ||||||
|  |             r#" | ||||||
|  | struct Vec<T> {}; | ||||||
|  | struct Seed; | ||||||
|  | fn bar() -> Vec<Seed> {} | ||||||
|  | fn foo() { $0(bar())$0; } | ||||||
|  | "#,
 | ||||||
|  |             "seeds", | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn vec_value_ends_with_s() { | ||||||
|  |         check( | ||||||
|  |             r#" | ||||||
|  | struct Vec<T> {}; | ||||||
|  | struct Boss; | ||||||
|  | fn bar() -> Vec<Boss> {} | ||||||
|  | fn foo() { $0(bar())$0; } | ||||||
|  | "#,
 | ||||||
|  |             "items", | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn vecdeque_value() { | ||||||
|  |         check( | ||||||
|  |             r#" | ||||||
|  | struct VecDeque<T> {}; | ||||||
|  | struct Seed; | ||||||
|  | fn bar() -> VecDeque<Seed> {} | ||||||
|  | fn foo() { $0(bar())$0; } | ||||||
|  | "#,
 | ||||||
|  |             "seeds", | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn slice_value() { | ||||||
|  |         check( | ||||||
|  |             r#" | ||||||
|  | struct Vec<T> {}; | ||||||
|  | struct Seed; | ||||||
|  | fn bar() -> &[Seed] {} | ||||||
|  | fn foo() { $0(bar())$0; } | ||||||
|  | "#,
 | ||||||
|  |             "seeds", | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn ref_call() { |     fn ref_call() { | ||||||
|         check( |         check( | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Wilfred Hughes
						Wilfred Hughes