aboutsummaryrefslogtreecommitdiff
path: root/crates/assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists')
-rw-r--r--crates/assists/src/handlers/auto_import.rs41
-rw-r--r--crates/assists/src/handlers/generate_function.rs19
-rw-r--r--crates/assists/src/handlers/generate_impl.rs11
-rw-r--r--crates/assists/src/handlers/generate_new.rs8
-rw-r--r--crates/assists/src/handlers/introduce_named_lifetime.rs2
-rw-r--r--crates/assists/src/handlers/qualify_path.rs43
-rw-r--r--crates/assists/src/handlers/raw_string.rs2
-rw-r--r--crates/assists/src/handlers/replace_derive_with_manual_impl.rs19
-rw-r--r--crates/assists/src/utils.rs2
9 files changed, 79 insertions, 68 deletions
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs
index 4e2a4fcd9..e93901cb3 100644
--- a/crates/assists/src/handlers/auto_import.rs
+++ b/crates/assists/src/handlers/auto_import.rs
@@ -3,7 +3,7 @@ use ide_db::helpers::{
3 insert_use::{insert_use, ImportScope}, 3 insert_use::{insert_use, ImportScope},
4 mod_path_to_ast, 4 mod_path_to_ast,
5}; 5};
6use syntax::ast; 6use syntax::{ast, AstNode, SyntaxNode};
7 7
8use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; 8use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
9 9
@@ -82,25 +82,16 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
82// # pub mod std { pub mod collections { pub struct HashMap { } } } 82// # pub mod std { pub mod collections { pub struct HashMap { } } }
83// ``` 83// ```
84pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 84pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
85 let import_assets = 85 let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
86 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { 86 let proposed_imports =
87 ImportAssets::for_regular_path(path_under_caret, &ctx.sema) 87 import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind);
88 } else if let Some(method_under_caret) =
89 ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
90 {
91 ImportAssets::for_method_call(method_under_caret, &ctx.sema)
92 } else {
93 None
94 }?;
95 let proposed_imports = import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use);
96 if proposed_imports.is_empty() { 88 if proposed_imports.is_empty() {
97 return None; 89 return None;
98 } 90 }
99 91
100 let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; 92 let range = ctx.sema.original_range(&syntax_under_caret).range;
101 let group = import_group_message(import_assets.import_candidate()); 93 let group = import_group_message(import_assets.import_candidate());
102 let scope = 94 let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?;
103 ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), &ctx.sema)?;
104 for (import, _) in proposed_imports { 95 for (import, _) in proposed_imports {
105 acc.add_group( 96 acc.add_group(
106 &group, 97 &group,
@@ -117,14 +108,28 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
117 Some(()) 108 Some(())
118} 109}
119 110
111pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets, SyntaxNode)> {
112 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
113 ImportAssets::for_exact_path(&path_under_caret, &ctx.sema)
114 .zip(Some(path_under_caret.syntax().clone()))
115 } else if let Some(method_under_caret) =
116 ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
117 {
118 ImportAssets::for_method_call(&method_under_caret, &ctx.sema)
119 .zip(Some(method_under_caret.syntax().clone()))
120 } else {
121 None
122 }
123}
124
120fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel { 125fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel {
121 let name = match import_candidate { 126 let name = match import_candidate {
122 ImportCandidate::Path(candidate) => format!("Import {}", &candidate.name), 127 ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
123 ImportCandidate::TraitAssocItem(candidate) => { 128 ImportCandidate::TraitAssocItem(candidate) => {
124 format!("Import a trait for item {}", &candidate.name) 129 format!("Import a trait for item {}", candidate.name.text())
125 } 130 }
126 ImportCandidate::TraitMethod(candidate) => { 131 ImportCandidate::TraitMethod(candidate) => {
127 format!("Import a trait for method {}", &candidate.name) 132 format!("Import a trait for method {}", candidate.name.text())
128 } 133 }
129 }; 134 };
130 GroupLabel(name) 135 GroupLabel(name)
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs
index 06ac85f67..1805c1dfd 100644
--- a/crates/assists/src/handlers/generate_function.rs
+++ b/crates/assists/src/handlers/generate_function.rs
@@ -158,11 +158,11 @@ impl FunctionBuilder {
158 it.text_range().end() 158 it.text_range().end()
159 } 159 }
160 GeneratedFunctionTarget::InEmptyItemList(it) => { 160 GeneratedFunctionTarget::InEmptyItemList(it) => {
161 let indent = IndentLevel::from_node(it.syntax()); 161 let indent = IndentLevel::from_node(&it);
162 leading_ws = format!("\n{}", indent + 1); 162 leading_ws = format!("\n{}", indent + 1);
163 fn_def = fn_def.indent(indent + 1); 163 fn_def = fn_def.indent(indent + 1);
164 trailing_ws = format!("\n{}", indent); 164 trailing_ws = format!("\n{}", indent);
165 it.syntax().text_range().start() + TextSize::of('{') 165 it.text_range().start() + TextSize::of('{')
166 } 166 }
167 }; 167 };
168 168
@@ -179,14 +179,14 @@ impl FunctionBuilder {
179 179
180enum GeneratedFunctionTarget { 180enum GeneratedFunctionTarget {
181 BehindItem(SyntaxNode), 181 BehindItem(SyntaxNode),
182 InEmptyItemList(ast::ItemList), 182 InEmptyItemList(SyntaxNode),
183} 183}
184 184
185impl GeneratedFunctionTarget { 185impl GeneratedFunctionTarget {
186 fn syntax(&self) -> &SyntaxNode { 186 fn syntax(&self) -> &SyntaxNode {
187 match self { 187 match self {
188 GeneratedFunctionTarget::BehindItem(it) => it, 188 GeneratedFunctionTarget::BehindItem(it) => it,
189 GeneratedFunctionTarget::InEmptyItemList(it) => it.syntax(), 189 GeneratedFunctionTarget::InEmptyItemList(it) => it,
190 } 190 }
191 } 191 }
192} 192}
@@ -323,7 +323,16 @@ fn next_space_for_fn_in_module(
323 if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { 323 if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) {
324 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) 324 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
325 } else { 325 } else {
326 GeneratedFunctionTarget::InEmptyItemList(it.item_list()?) 326 GeneratedFunctionTarget::InEmptyItemList(it.item_list()?.syntax().clone())
327 }
328 }
329 hir::ModuleSource::BlockExpr(it) => {
330 if let Some(last_item) =
331 it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last()
332 {
333 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
334 } else {
335 GeneratedFunctionTarget::InEmptyItemList(it.syntax().clone())
327 } 336 }
328 } 337 }
329 }; 338 };
diff --git a/crates/assists/src/handlers/generate_impl.rs b/crates/assists/src/handlers/generate_impl.rs
index 9af45192b..827477272 100644
--- a/crates/assists/src/handlers/generate_impl.rs
+++ b/crates/assists/src/handlers/generate_impl.rs
@@ -1,6 +1,9 @@
1use itertools::Itertools; 1use itertools::Itertools;
2use stdx::format_to; 2use stdx::format_to;
3use syntax::ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner}; 3use syntax::{
4 ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner},
5 SmolStr,
6};
4 7
5use crate::{AssistContext, AssistId, AssistKind, Assists}; 8use crate::{AssistContext, AssistId, AssistKind, Assists};
6 9
@@ -49,16 +52,16 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()
49 format_to!(buf, "{}", type_params.syntax()); 52 format_to!(buf, "{}", type_params.syntax());
50 } 53 }
51 buf.push_str(" "); 54 buf.push_str(" ");
52 buf.push_str(name.text().as_str()); 55 buf.push_str(name.text());
53 if let Some(type_params) = type_params { 56 if let Some(type_params) = type_params {
54 let lifetime_params = type_params 57 let lifetime_params = type_params
55 .lifetime_params() 58 .lifetime_params()
56 .filter_map(|it| it.lifetime()) 59 .filter_map(|it| it.lifetime())
57 .map(|it| it.text().clone()); 60 .map(|it| SmolStr::from(it.text()));
58 let type_params = type_params 61 let type_params = type_params
59 .type_params() 62 .type_params()
60 .filter_map(|it| it.name()) 63 .filter_map(|it| it.name())
61 .map(|it| it.text().clone()); 64 .map(|it| SmolStr::from(it.text()));
62 65
63 let generic_params = lifetime_params.chain(type_params).format(", "); 66 let generic_params = lifetime_params.chain(type_params).format(", ");
64 format_to!(buf, "<{}>", generic_params) 67 format_to!(buf, "<{}>", generic_params)
diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs
index 5c52b2bc8..b7390855a 100644
--- a/crates/assists/src/handlers/generate_new.rs
+++ b/crates/assists/src/handlers/generate_new.rs
@@ -3,7 +3,7 @@ use itertools::Itertools;
3use stdx::format_to; 3use stdx::format_to;
4use syntax::{ 4use syntax::{
5 ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, 5 ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner},
6 T, 6 SmolStr, T,
7}; 7};
8 8
9use crate::{AssistContext, AssistId, AssistKind, Assists}; 9use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -95,14 +95,14 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String {
95 format_to!(buf, "{}", type_params.syntax()); 95 format_to!(buf, "{}", type_params.syntax());
96 } 96 }
97 buf.push_str(" "); 97 buf.push_str(" ");
98 buf.push_str(strukt.name().unwrap().text().as_str()); 98 buf.push_str(strukt.name().unwrap().text());
99 if let Some(type_params) = type_params { 99 if let Some(type_params) = type_params {
100 let lifetime_params = type_params 100 let lifetime_params = type_params
101 .lifetime_params() 101 .lifetime_params()
102 .filter_map(|it| it.lifetime()) 102 .filter_map(|it| it.lifetime())
103 .map(|it| it.text().clone()); 103 .map(|it| SmolStr::from(it.text()));
104 let type_params = 104 let type_params =
105 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); 105 type_params.type_params().filter_map(|it| it.name()).map(|it| SmolStr::from(it.text()));
106 format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", ")) 106 format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", "))
107 } 107 }
108 108
diff --git a/crates/assists/src/handlers/introduce_named_lifetime.rs b/crates/assists/src/handlers/introduce_named_lifetime.rs
index 3f5f44d69..02782eb6d 100644
--- a/crates/assists/src/handlers/introduce_named_lifetime.rs
+++ b/crates/assists/src/handlers/introduce_named_lifetime.rs
@@ -61,7 +61,7 @@ fn generate_fn_def_assist(
61 // compute the location which implicitly has the same lifetime as the anonymous lifetime 61 // compute the location which implicitly has the same lifetime as the anonymous lifetime
62 let loc_needing_lifetime = if let Some(self_param) = self_param { 62 let loc_needing_lifetime = if let Some(self_param) = self_param {
63 // if we have a self reference, use that 63 // if we have a self reference, use that
64 Some(self_param.self_token()?.text_range().start()) 64 Some(self_param.name()?.syntax().text_range().start())
65 } else { 65 } else {
66 // otherwise, if there's a single reference parameter without a named liftime, use that 66 // otherwise, if there's a single reference parameter without a named liftime, use that
67 let fn_params_without_lifetime: Vec<_> = param_list 67 let fn_params_without_lifetime: Vec<_> = param_list
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs
index a7d9fd4dc..b0b0d31b4 100644
--- a/crates/assists/src/handlers/qualify_path.rs
+++ b/crates/assists/src/handlers/qualify_path.rs
@@ -1,10 +1,7 @@
1use std::iter; 1use std::iter;
2 2
3use hir::AsName; 3use hir::{AsAssocItem, AsName};
4use ide_db::helpers::{ 4use ide_db::helpers::{import_assets::ImportCandidate, mod_path_to_ast};
5 import_assets::{ImportAssets, ImportCandidate},
6 mod_path_to_ast,
7};
8use ide_db::RootDatabase; 5use ide_db::RootDatabase;
9use syntax::{ 6use syntax::{
10 ast, 7 ast,
@@ -18,6 +15,8 @@ use crate::{
18 AssistId, AssistKind, GroupLabel, 15 AssistId, AssistKind, GroupLabel,
19}; 16};
20 17
18use super::auto_import::find_importable_node;
19
21// Assist: qualify_path 20// Assist: qualify_path
22// 21//
23// If the name is unresolved, provides all possible qualified paths for it. 22// If the name is unresolved, provides all possible qualified paths for it.
@@ -36,47 +35,38 @@ use crate::{
36// # pub mod std { pub mod collections { pub struct HashMap { } } } 35// # pub mod std { pub mod collections { pub struct HashMap { } } }
37// ``` 36// ```
38pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 37pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39 let import_assets = 38 let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
40 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
41 ImportAssets::for_regular_path(path_under_caret, &ctx.sema)
42 } else if let Some(method_under_caret) =
43 ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
44 {
45 ImportAssets::for_method_call(method_under_caret, &ctx.sema)
46 } else {
47 None
48 }?;
49 let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema); 39 let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema);
50 if proposed_imports.is_empty() { 40 if proposed_imports.is_empty() {
51 return None; 41 return None;
52 } 42 }
53 43
54 let candidate = import_assets.import_candidate(); 44 let candidate = import_assets.import_candidate();
55 let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; 45 let range = ctx.sema.original_range(&syntax_under_caret).range;
56 46
57 let qualify_candidate = match candidate { 47 let qualify_candidate = match candidate {
58 ImportCandidate::Path(candidate) => { 48 ImportCandidate::Path(candidate) => {
59 if candidate.qualifier.is_some() { 49 if candidate.qualifier.is_some() {
60 mark::hit!(qualify_path_qualifier_start); 50 mark::hit!(qualify_path_qualifier_start);
61 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; 51 let path = ast::Path::cast(syntax_under_caret)?;
62 let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); 52 let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?);
63 QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) 53 QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list())
64 } else { 54 } else {
65 mark::hit!(qualify_path_unqualified_name); 55 mark::hit!(qualify_path_unqualified_name);
66 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; 56 let path = ast::Path::cast(syntax_under_caret)?;
67 let generics = path.segment()?.generic_arg_list(); 57 let generics = path.segment()?.generic_arg_list();
68 QualifyCandidate::UnqualifiedName(generics) 58 QualifyCandidate::UnqualifiedName(generics)
69 } 59 }
70 } 60 }
71 ImportCandidate::TraitAssocItem(_) => { 61 ImportCandidate::TraitAssocItem(_) => {
72 mark::hit!(qualify_path_trait_assoc_item); 62 mark::hit!(qualify_path_trait_assoc_item);
73 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; 63 let path = ast::Path::cast(syntax_under_caret)?;
74 let (qualifier, segment) = (path.qualifier()?, path.segment()?); 64 let (qualifier, segment) = (path.qualifier()?, path.segment()?);
75 QualifyCandidate::TraitAssocItem(qualifier, segment) 65 QualifyCandidate::TraitAssocItem(qualifier, segment)
76 } 66 }
77 ImportCandidate::TraitMethod(_) => { 67 ImportCandidate::TraitMethod(_) => {
78 mark::hit!(qualify_path_trait_method); 68 mark::hit!(qualify_path_trait_method);
79 let mcall_expr = ast::MethodCallExpr::cast(import_assets.syntax_under_caret().clone())?; 69 let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret)?;
80 QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr) 70 QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr)
81 } 71 }
82 }; 72 };
@@ -140,7 +130,7 @@ impl QualifyCandidate<'_> {
140 let generics = 130 let generics =
141 mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string); 131 mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string);
142 let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args()); 132 let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args());
143 let trait_ = item_as_trait(item)?; 133 let trait_ = item_as_trait(db, item)?;
144 let method = find_trait_method(db, trait_, &trait_method_name)?; 134 let method = find_trait_method(db, trait_, &trait_method_name)?;
145 if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) { 135 if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) {
146 let receiver = match self_access { 136 let receiver = match self_access {
@@ -179,11 +169,13 @@ fn find_trait_method(
179 } 169 }
180} 170}
181 171
182fn item_as_trait(item: hir::ItemInNs) -> Option<hir::Trait> { 172fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option<hir::Trait> {
183 if let hir::ModuleDef::Trait(trait_) = hir::ModuleDef::from(item.as_module_def_id()?) { 173 let item_module_def = hir::ModuleDef::from(item.as_module_def_id()?);
174
175 if let hir::ModuleDef::Trait(trait_) = item_module_def {
184 Some(trait_) 176 Some(trait_)
185 } else { 177 } else {
186 None 178 item_module_def.as_assoc_item(db)?.containing_trait(db)
187 } 179 }
188} 180}
189 181
@@ -191,7 +183,8 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel {
191 let name = match candidate { 183 let name = match candidate {
192 ImportCandidate::Path(it) => &it.name, 184 ImportCandidate::Path(it) => &it.name,
193 ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name, 185 ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name,
194 }; 186 }
187 .text();
195 GroupLabel(format!("Qualify {}", name)) 188 GroupLabel(format!("Qualify {}", name))
196} 189}
197 190
diff --git a/crates/assists/src/handlers/raw_string.rs b/crates/assists/src/handlers/raw_string.rs
index be963f162..d95267607 100644
--- a/crates/assists/src/handlers/raw_string.rs
+++ b/crates/assists/src/handlers/raw_string.rs
@@ -138,7 +138,7 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
138 return None; 138 return None;
139 } 139 }
140 140
141 let text = token.text().as_str(); 141 let text = token.text();
142 if !text.starts_with("r#") && text.ends_with('#') { 142 if !text.starts_with("r#") && text.ends_with('#') {
143 return None; 143 return None;
144 } 144 }
diff --git a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
index bd4c1c806..6aa9d2f2c 100644
--- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -3,7 +3,7 @@ use ide_db::imports_locator;
3use itertools::Itertools; 3use itertools::Itertools;
4use syntax::{ 4use syntax::{
5 ast::{self, make, AstNode}, 5 ast::{self, make, AstNode},
6 Direction, SmolStr, 6 Direction,
7 SyntaxKind::{IDENT, WHITESPACE}, 7 SyntaxKind::{IDENT, WHITESPACE},
8 TextSize, 8 TextSize,
9}; 9};
@@ -43,17 +43,18 @@ pub(crate) fn replace_derive_with_manual_impl(
43) -> Option<()> { 43) -> Option<()> {
44 let attr = ctx.find_node_at_offset::<ast::Attr>()?; 44 let attr = ctx.find_node_at_offset::<ast::Attr>()?;
45 45
46 let attr_name = attr 46 let has_derive = attr
47 .syntax() 47 .syntax()
48 .descendants_with_tokens() 48 .descendants_with_tokens()
49 .filter(|t| t.kind() == IDENT) 49 .filter(|t| t.kind() == IDENT)
50 .find_map(syntax::NodeOrToken::into_token) 50 .find_map(syntax::NodeOrToken::into_token)
51 .filter(|t| t.text() == "derive")? 51 .filter(|t| t.text() == "derive")
52 .text() 52 .is_some();
53 .clone(); 53 if !has_derive {
54 return None;
55 }
54 56
55 let trait_token = 57 let trait_token = ctx.token_at_offset().find(|t| t.kind() == IDENT && t.text() != "derive")?;
56 ctx.token_at_offset().find(|t| t.kind() == IDENT && *t.text() != attr_name)?;
57 let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text()))); 58 let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text())));
58 59
59 let annotated_name = attr.syntax().siblings(Direction::Next).find_map(ast::Name::cast)?; 60 let annotated_name = attr.syntax().siblings(Direction::Next).find_map(ast::Name::cast)?;
@@ -176,9 +177,9 @@ fn update_attribute(
176 .syntax() 177 .syntax()
177 .descendants_with_tokens() 178 .descendants_with_tokens()
178 .filter(|t| t.kind() == IDENT) 179 .filter(|t| t.kind() == IDENT)
179 .filter_map(|t| t.into_token().map(|t| t.text().clone())) 180 .filter_map(|t| t.into_token().map(|t| t.text().to_string()))
180 .filter(|t| t != trait_name.text()) 181 .filter(|t| t != trait_name.text())
181 .collect::<Vec<SmolStr>>(); 182 .collect::<Vec<_>>();
182 let has_more_derives = !new_attr_input.is_empty(); 183 let has_more_derives = !new_attr_input.is_empty();
183 184
184 if has_more_derives { 185 if has_more_derives {
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index fc9f83bab..44c35bafa 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -223,7 +223,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
223 let method = mce.name_ref()?; 223 let method = mce.name_ref()?;
224 let arg_list = mce.arg_list()?; 224 let arg_list = mce.arg_list()?;
225 225
226 let method = match method.text().as_str() { 226 let method = match method.text() {
227 "is_some" => "is_none", 227 "is_some" => "is_none",
228 "is_none" => "is_some", 228 "is_none" => "is_some",
229 "is_ok" => "is_err", 229 "is_ok" => "is_err",