|
| 1 | +use ra_ide_db::RootDatabase; |
1 | 2 | use ra_syntax::{
|
2 | 3 | ast::{self, AstNode, NameOwner},
|
3 | 4 | TextSize,
|
4 | 5 | };
|
5 | 6 | use stdx::format_to;
|
6 | 7 |
|
7 |
| -use crate::{Assist, AssistCtx, AssistId}; |
8 |
| -use ra_ide_db::RootDatabase; |
| 8 | +use crate::{utils::FamousDefs, Assist, AssistCtx, AssistId}; |
| 9 | +use test_utils::tested_by; |
9 | 10 |
|
10 | 11 | // Assist add_from_impl_for_enum
|
11 | 12 | //
|
@@ -41,7 +42,8 @@ pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> {
|
41 | 42 | _ => return None,
|
42 | 43 | };
|
43 | 44 |
|
44 |
| - if already_has_from_impl(ctx.sema, &variant) { |
| 45 | + if existing_from_impl(ctx.sema, &variant).is_some() { |
| 46 | + tested_by!(test_add_from_impl_already_exists); |
45 | 47 | return None;
|
46 | 48 | }
|
47 | 49 |
|
@@ -70,41 +72,33 @@ impl From<{0}> for {1} {{
|
70 | 72 | )
|
71 | 73 | }
|
72 | 74 |
|
73 |
| -fn already_has_from_impl( |
| 75 | +fn existing_from_impl( |
74 | 76 | sema: &'_ hir::Semantics<'_, RootDatabase>,
|
75 | 77 | variant: &ast::EnumVariant,
|
76 |
| -) -> bool { |
77 |
| - let scope = sema.scope(&variant.syntax()); |
| 78 | +) -> Option<()> { |
| 79 | + let variant = sema.to_def(variant)?; |
| 80 | + let enum_ = variant.parent_enum(sema.db); |
| 81 | + let krate = enum_.module(sema.db).krate(); |
78 | 82 |
|
79 |
| - let from_path = ast::make::path_from_text("From"); |
80 |
| - let from_hir_path = match hir::Path::from_ast(from_path) { |
81 |
| - Some(p) => p, |
82 |
| - None => return false, |
83 |
| - }; |
84 |
| - let from_trait = match scope.resolve_hir_path(&from_hir_path) { |
85 |
| - Some(hir::PathResolution::Def(hir::ModuleDef::Trait(t))) => t, |
86 |
| - _ => return false, |
87 |
| - }; |
| 83 | + let from_trait = FamousDefs(sema, krate).core_convert_From()?; |
88 | 84 |
|
89 |
| - let e: hir::Enum = match sema.to_def(&variant.parent_enum()) { |
90 |
| - Some(e) => e, |
91 |
| - None => return false, |
92 |
| - }; |
93 |
| - let e_ty = e.ty(sema.db); |
| 85 | + let enum_type = enum_.ty(sema.db); |
94 | 86 |
|
95 |
| - let hir_enum_var: hir::EnumVariant = match sema.to_def(variant) { |
96 |
| - Some(ev) => ev, |
97 |
| - None => return false, |
98 |
| - }; |
99 |
| - let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db); |
| 87 | + let wrapped_type = variant.fields(sema.db).get(0)?.signature_ty(sema.db); |
100 | 88 |
|
101 |
| - e_ty.impls_trait(sema.db, from_trait, &[var_ty]) |
| 89 | + if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) { |
| 90 | + Some(()) |
| 91 | + } else { |
| 92 | + None |
| 93 | + } |
102 | 94 | }
|
103 | 95 |
|
104 | 96 | #[cfg(test)]
|
105 | 97 | mod tests {
|
106 | 98 | use super::*;
|
| 99 | + |
107 | 100 | use crate::helpers::{check_assist, check_assist_not_applicable};
|
| 101 | + use test_utils::covers; |
108 | 102 |
|
109 | 103 | #[test]
|
110 | 104 | fn test_add_from_impl_for_enum() {
|
@@ -136,36 +130,40 @@ mod tests {
|
136 | 130 | );
|
137 | 131 | }
|
138 | 132 |
|
| 133 | + fn check_not_applicable(ra_fixture: &str) { |
| 134 | + let fixture = |
| 135 | + format!("//- main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); |
| 136 | + check_assist_not_applicable(add_from_impl_for_enum, &fixture) |
| 137 | + } |
| 138 | + |
139 | 139 | #[test]
|
140 | 140 | fn test_add_from_impl_no_element() {
|
141 |
| - check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One }"); |
| 141 | + check_not_applicable("enum A { <|>One }"); |
142 | 142 | }
|
143 | 143 |
|
144 | 144 | #[test]
|
145 | 145 | fn test_add_from_impl_more_than_one_element_in_tuple() {
|
146 |
| - check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One(u32, String) }"); |
| 146 | + check_not_applicable("enum A { <|>One(u32, String) }"); |
147 | 147 | }
|
148 | 148 |
|
149 | 149 | #[test]
|
150 | 150 | fn test_add_from_impl_struct_variant() {
|
151 |
| - check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One { x: u32 } }"); |
| 151 | + check_not_applicable("enum A { <|>One { x: u32 } }"); |
152 | 152 | }
|
153 | 153 |
|
154 | 154 | #[test]
|
155 | 155 | fn test_add_from_impl_already_exists() {
|
156 |
| - check_assist_not_applicable( |
157 |
| - add_from_impl_for_enum, |
158 |
| - r#"enum A { <|>One(u32), } |
| 156 | + covers!(test_add_from_impl_already_exists); |
| 157 | + check_not_applicable( |
| 158 | + r#" |
| 159 | +enum A { <|>One(u32), } |
159 | 160 |
|
160 | 161 | impl From<u32> for A {
|
161 | 162 | fn from(v: u32) -> Self {
|
162 | 163 | A::One(v)
|
163 | 164 | }
|
164 | 165 | }
|
165 |
| -
|
166 |
| -pub trait From<T> { |
167 |
| - fn from(T) -> Self; |
168 |
| -}"#, |
| 166 | +"#, |
169 | 167 | );
|
170 | 168 | }
|
171 | 169 |
|
|
0 commit comments