diff options
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | crates/assists/src/assist_context.rs | 4 | ||||
-rw-r--r-- | crates/assists/src/handlers/generate_enum_match_method.rs | 10 | ||||
-rw-r--r-- | crates/assists/src/tests/generated.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics.rs | 35 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/decl_check.rs | 279 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 2 | ||||
-rw-r--r-- | crates/proc_macro_api/src/rpc.rs | 2 | ||||
-rw-r--r-- | crates/stdx/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/test_utils/src/fixture.rs | 11 | ||||
-rw-r--r-- | docs/dev/debugging.md | 2 | ||||
-rw-r--r-- | xtask/src/install.rs | 4 |
15 files changed, 176 insertions, 186 deletions
diff --git a/Cargo.lock b/Cargo.lock index 8f1a8401f..1ceae965f 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -17,9 +17,9 @@ checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" | |||
17 | 17 | ||
18 | [[package]] | 18 | [[package]] |
19 | name = "always-assert" | 19 | name = "always-assert" |
20 | version = "0.1.1" | 20 | version = "0.1.2" |
21 | source = "registry+https://github.com/rust-lang/crates.io-index" | 21 | source = "registry+https://github.com/rust-lang/crates.io-index" |
22 | checksum = "727786f78c5bc0cda8011831616589f72084cb16b7df4213a997b78749b55a60" | 22 | checksum = "fbf688625d06217d5b1bb0ea9d9c44a1635fd0ee3534466388d18203174f4d11" |
23 | dependencies = [ | 23 | dependencies = [ |
24 | "log", | 24 | "log", |
25 | ] | 25 | ] |
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index 8d93edba2..bba6c08e0 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs | |||
@@ -162,7 +162,7 @@ impl Assists { | |||
162 | } else { | 162 | } else { |
163 | None | 163 | None |
164 | }; | 164 | }; |
165 | assist.source_change = source_change.clone(); | 165 | assist.source_change = source_change; |
166 | 166 | ||
167 | self.buf.push(assist); | 167 | self.buf.push(assist); |
168 | Some(()) | 168 | Some(()) |
@@ -242,7 +242,7 @@ impl AssistBuilder { | |||
242 | } | 242 | } |
243 | pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) { | 243 | pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) { |
244 | let file_system_edit = | 244 | let file_system_edit = |
245 | FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() }; | 245 | FileSystemEdit::CreateFile { dst: dst, initial_contents: content.into() }; |
246 | self.source_change.push_file_system_edit(file_system_edit); | 246 | self.source_change.push_file_system_edit(file_system_edit); |
247 | } | 247 | } |
248 | 248 | ||
diff --git a/crates/assists/src/handlers/generate_enum_match_method.rs b/crates/assists/src/handlers/generate_enum_match_method.rs index 2345a61c1..4cf66b5d5 100644 --- a/crates/assists/src/handlers/generate_enum_match_method.rs +++ b/crates/assists/src/handlers/generate_enum_match_method.rs | |||
@@ -28,6 +28,7 @@ use crate::{ | |||
28 | // } | 28 | // } |
29 | // | 29 | // |
30 | // impl Version { | 30 | // impl Version { |
31 | // /// Returns `true` if the version is [`Minor`]. | ||
31 | // fn is_minor(&self) -> bool { | 32 | // fn is_minor(&self) -> bool { |
32 | // matches!(self, Self::Minor) | 33 | // matches!(self, Self::Minor) |
33 | // } | 34 | // } |
@@ -42,6 +43,7 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext) | |||
42 | return None; | 43 | return None; |
43 | } | 44 | } |
44 | 45 | ||
46 | let enum_lowercase_name = to_lower_snake_case(&parent_enum.name()?.to_string()); | ||
45 | let fn_name = to_lower_snake_case(&variant_name.to_string()); | 47 | let fn_name = to_lower_snake_case(&variant_name.to_string()); |
46 | 48 | ||
47 | // Return early if we've found an existing new fn | 49 | // Return early if we've found an existing new fn |
@@ -66,9 +68,12 @@ pub(crate) fn generate_enum_match_method(acc: &mut Assists, ctx: &AssistContext) | |||
66 | let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); | 68 | let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v)); |
67 | format_to!( | 69 | format_to!( |
68 | buf, | 70 | buf, |
69 | " {}fn is_{}(&self) -> bool {{ | 71 | " /// Returns `true` if the {} is [`{}`]. |
72 | {}fn is_{}(&self) -> bool {{ | ||
70 | matches!(self, Self::{}) | 73 | matches!(self, Self::{}) |
71 | }}", | 74 | }}", |
75 | enum_lowercase_name, | ||
76 | variant_name, | ||
72 | vis, | 77 | vis, |
73 | fn_name, | 78 | fn_name, |
74 | variant_name | 79 | variant_name |
@@ -125,6 +130,7 @@ enum Variant { | |||
125 | } | 130 | } |
126 | 131 | ||
127 | impl Variant { | 132 | impl Variant { |
133 | /// Returns `true` if the variant is [`Minor`]. | ||
128 | fn is_minor(&self) -> bool { | 134 | fn is_minor(&self) -> bool { |
129 | matches!(self, Self::Minor) | 135 | matches!(self, Self::Minor) |
130 | } | 136 | } |
@@ -172,6 +178,7 @@ enum Variant { | |||
172 | enum Variant { Undefined } | 178 | enum Variant { Undefined } |
173 | 179 | ||
174 | impl Variant { | 180 | impl Variant { |
181 | /// Returns `true` if the variant is [`Undefined`]. | ||
175 | fn is_undefined(&self) -> bool { | 182 | fn is_undefined(&self) -> bool { |
176 | matches!(self, Self::Undefined) | 183 | matches!(self, Self::Undefined) |
177 | } | 184 | } |
@@ -196,6 +203,7 @@ pub(crate) enum Variant { | |||
196 | } | 203 | } |
197 | 204 | ||
198 | impl Variant { | 205 | impl Variant { |
206 | /// Returns `true` if the variant is [`Minor`]. | ||
199 | pub(crate) fn is_minor(&self) -> bool { | 207 | pub(crate) fn is_minor(&self) -> bool { |
200 | matches!(self, Self::Minor) | 208 | matches!(self, Self::Minor) |
201 | } | 209 | } |
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index 960815bd9..0dbb05f2a 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs | |||
@@ -478,6 +478,7 @@ enum Version { | |||
478 | } | 478 | } |
479 | 479 | ||
480 | impl Version { | 480 | impl Version { |
481 | /// Returns `true` if the version is [`Minor`]. | ||
481 | fn is_minor(&self) -> bool { | 482 | fn is_minor(&self) -> bool { |
482 | matches!(self, Self::Minor) | 483 | matches!(self, Self::Minor) |
483 | } | 484 | } |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 28b11cdde..c18001e15 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -712,7 +712,7 @@ impl ExprCollector<'_> { | |||
712 | let statements = | 712 | let statements = |
713 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | 713 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); |
714 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 714 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
715 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); | 715 | let syntax_node_ptr = AstPtr::new(&block.into()); |
716 | let expr_id = self.alloc_expr( | 716 | let expr_id = self.alloc_expr( |
717 | Expr::Block { id: block_id, statements, tail, label: None }, | 717 | Expr::Block { id: block_id, statements, tail, label: None }, |
718 | syntax_node_ptr, | 718 | syntax_node_ptr, |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 42fcca386..d3380e0f4 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -43,7 +43,7 @@ impl FunctionData { | |||
43 | name: func.name.clone(), | 43 | name: func.name.clone(), |
44 | params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), | 44 | params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), |
45 | ret_type: item_tree[func.ret_type].clone(), | 45 | ret_type: item_tree[func.ret_type].clone(), |
46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(), | 46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
47 | has_self_param: func.has_self_param, | 47 | has_self_param: func.has_self_param, |
48 | has_body: func.has_body, | 48 | has_body: func.has_body, |
49 | is_unsafe: func.is_unsafe, | 49 | is_unsafe: func.is_unsafe, |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index c4e36eda5..6665d902d 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -161,7 +161,7 @@ impl TestDB { | |||
161 | let node = src.map(|ptr| ptr.to_node(&root)); | 161 | let node = src.map(|ptr| ptr.to_node(&root)); |
162 | let frange = node.as_ref().original_file_range(db); | 162 | let frange = node.as_ref().original_file_range(db); |
163 | 163 | ||
164 | let message = d.message().to_owned(); | 164 | let message = d.message(); |
165 | actual.entry(frange.file_id).or_default().push((frange.range, message)); | 165 | actual.entry(frange.file_id).or_default().push((frange.range, message)); |
166 | }); | 166 | }); |
167 | 167 | ||
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 323c5f963..19da51acd 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -345,6 +345,37 @@ impl fmt::Display for CaseType { | |||
345 | } | 345 | } |
346 | } | 346 | } |
347 | 347 | ||
348 | #[derive(Debug)] | ||
349 | pub enum IdentType { | ||
350 | Argument, | ||
351 | Constant, | ||
352 | Enum, | ||
353 | Field, | ||
354 | Function, | ||
355 | StaticVariable, | ||
356 | Structure, | ||
357 | Variable, | ||
358 | Variant, | ||
359 | } | ||
360 | |||
361 | impl fmt::Display for IdentType { | ||
362 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
363 | let repr = match self { | ||
364 | IdentType::Argument => "Argument", | ||
365 | IdentType::Constant => "Constant", | ||
366 | IdentType::Enum => "Enum", | ||
367 | IdentType::Field => "Field", | ||
368 | IdentType::Function => "Function", | ||
369 | IdentType::StaticVariable => "Static variable", | ||
370 | IdentType::Structure => "Structure", | ||
371 | IdentType::Variable => "Variable", | ||
372 | IdentType::Variant => "Variant", | ||
373 | }; | ||
374 | |||
375 | write!(f, "{}", repr) | ||
376 | } | ||
377 | } | ||
378 | |||
348 | // Diagnostic: incorrect-ident-case | 379 | // Diagnostic: incorrect-ident-case |
349 | // | 380 | // |
350 | // This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention]. | 381 | // This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention]. |
@@ -353,7 +384,7 @@ pub struct IncorrectCase { | |||
353 | pub file: HirFileId, | 384 | pub file: HirFileId, |
354 | pub ident: AstPtr<ast::Name>, | 385 | pub ident: AstPtr<ast::Name>, |
355 | pub expected_case: CaseType, | 386 | pub expected_case: CaseType, |
356 | pub ident_type: String, | 387 | pub ident_type: IdentType, |
357 | pub ident_text: String, | 388 | pub ident_text: String, |
358 | pub suggested_text: String, | 389 | pub suggested_text: String, |
359 | } | 390 | } |
@@ -480,7 +511,7 @@ mod tests { | |||
480 | // FIXME: macros... | 511 | // FIXME: macros... |
481 | let file_id = src.file_id.original_file(&db); | 512 | let file_id = src.file_id.original_file(&db); |
482 | let range = src.value.to_node(&root).text_range(); | 513 | let range = src.value.to_node(&root).text_range(); |
483 | let message = d.message().to_owned(); | 514 | let message = d.message(); |
484 | actual.entry(file_id).or_default().push((range, message)); | 515 | actual.entry(file_id).or_default().push((range, message)); |
485 | }); | 516 | }); |
486 | 517 | ||
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index eaeb6899f..6773ddea3 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -23,6 +23,7 @@ use hir_expand::{ | |||
23 | diagnostics::DiagnosticSink, | 23 | diagnostics::DiagnosticSink, |
24 | name::{AsName, Name}, | 24 | name::{AsName, Name}, |
25 | }; | 25 | }; |
26 | use stdx::{always, never}; | ||
26 | use syntax::{ | 27 | use syntax::{ |
27 | ast::{self, NameOwner}, | 28 | ast::{self, NameOwner}, |
28 | AstNode, AstPtr, | 29 | AstNode, AstPtr, |
@@ -31,7 +32,7 @@ use test_utils::mark; | |||
31 | 32 | ||
32 | use crate::{ | 33 | use crate::{ |
33 | db::HirDatabase, | 34 | db::HirDatabase, |
34 | diagnostics::{decl_check::case_conv::*, CaseType, IncorrectCase}, | 35 | diagnostics::{decl_check::case_conv::*, CaseType, IdentType, IncorrectCase}, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | mod allow { | 38 | mod allow { |
@@ -40,7 +41,7 @@ mod allow { | |||
40 | pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; | 41 | pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; |
41 | } | 42 | } |
42 | 43 | ||
43 | pub(super) struct DeclValidator<'a, 'b: 'a> { | 44 | pub(super) struct DeclValidator<'a, 'b> { |
44 | db: &'a dyn HirDatabase, | 45 | db: &'a dyn HirDatabase, |
45 | krate: CrateId, | 46 | krate: CrateId, |
46 | sink: &'a mut DiagnosticSink<'b>, | 47 | sink: &'a mut DiagnosticSink<'b>, |
@@ -77,7 +78,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
77 | AdtId::StructId(struct_id) => self.validate_struct(struct_id), | 78 | AdtId::StructId(struct_id) => self.validate_struct(struct_id), |
78 | AdtId::EnumId(enum_id) => self.validate_enum(enum_id), | 79 | AdtId::EnumId(enum_id) => self.validate_enum(enum_id), |
79 | AdtId::UnionId(_) => { | 80 | AdtId::UnionId(_) => { |
80 | // Unions aren't yet supported by this validator. | 81 | // FIXME: Unions aren't yet supported by this validator. |
81 | } | 82 | } |
82 | } | 83 | } |
83 | } | 84 | } |
@@ -111,63 +112,50 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
111 | 112 | ||
112 | // Check the function name. | 113 | // Check the function name. |
113 | let function_name = data.name.to_string(); | 114 | let function_name = data.name.to_string(); |
114 | let fn_name_replacement = if let Some(new_name) = to_lower_snake_case(&function_name) { | 115 | let fn_name_replacement = to_lower_snake_case(&function_name).map(|new_name| Replacement { |
115 | let replacement = Replacement { | 116 | current_name: data.name.clone(), |
116 | current_name: data.name.clone(), | 117 | suggested_text: new_name, |
117 | suggested_text: new_name, | 118 | expected_case: CaseType::LowerSnakeCase, |
118 | expected_case: CaseType::LowerSnakeCase, | 119 | }); |
119 | }; | ||
120 | Some(replacement) | ||
121 | } else { | ||
122 | None | ||
123 | }; | ||
124 | 120 | ||
125 | // Check the param names. | 121 | // Check the param names. |
126 | let mut fn_param_replacements = Vec::new(); | 122 | let fn_param_replacements = body |
127 | 123 | .params | |
128 | for pat_id in body.params.iter().cloned() { | 124 | .iter() |
129 | let pat = &body[pat_id]; | 125 | .filter_map(|&id| match &body[id] { |
130 | 126 | Pat::Bind { name, .. } => Some(name), | |
131 | let param_name = match pat { | 127 | _ => None, |
132 | Pat::Bind { name, .. } => name, | 128 | }) |
133 | _ => continue, | 129 | .filter_map(|param_name| { |
134 | }; | 130 | Some(Replacement { |
135 | |||
136 | let name = param_name.to_string(); | ||
137 | if let Some(new_name) = to_lower_snake_case(&name) { | ||
138 | let replacement = Replacement { | ||
139 | current_name: param_name.clone(), | 131 | current_name: param_name.clone(), |
140 | suggested_text: new_name, | 132 | suggested_text: to_lower_snake_case(¶m_name.to_string())?, |
141 | expected_case: CaseType::LowerSnakeCase, | 133 | expected_case: CaseType::LowerSnakeCase, |
142 | }; | 134 | }) |
143 | fn_param_replacements.push(replacement); | 135 | }) |
144 | } | 136 | .collect(); |
145 | } | ||
146 | 137 | ||
147 | // Check the patterns inside the function body. | 138 | // Check the patterns inside the function body. |
148 | let mut pats_replacements = Vec::new(); | 139 | let pats_replacements = body |
149 | 140 | .pats | |
150 | for (pat_idx, pat) in body.pats.iter() { | 141 | .iter() |
151 | if body.params.contains(&pat_idx) { | 142 | // We aren't interested in function parameters, we've processed them above. |
152 | // We aren't interested in function parameters, we've processed them above. | 143 | .filter(|(pat_idx, _)| !body.params.contains(&pat_idx)) |
153 | continue; | 144 | .filter_map(|(id, pat)| match pat { |
154 | } | 145 | Pat::Bind { name, .. } => Some((id, name)), |
155 | 146 | _ => None, | |
156 | let bind_name = match pat { | 147 | }) |
157 | Pat::Bind { name, .. } => name, | 148 | .filter_map(|(id, bind_name)| { |
158 | _ => continue, | 149 | Some(( |
159 | }; | 150 | id, |
160 | 151 | Replacement { | |
161 | let name = bind_name.to_string(); | 152 | current_name: bind_name.clone(), |
162 | if let Some(new_name) = to_lower_snake_case(&name) { | 153 | suggested_text: to_lower_snake_case(&bind_name.to_string())?, |
163 | let replacement = Replacement { | 154 | expected_case: CaseType::LowerSnakeCase, |
164 | current_name: bind_name.clone(), | 155 | }, |
165 | suggested_text: new_name, | 156 | )) |
166 | expected_case: CaseType::LowerSnakeCase, | 157 | }) |
167 | }; | 158 | .collect(); |
168 | pats_replacements.push((pat_idx, replacement)); | ||
169 | } | ||
170 | } | ||
171 | 159 | ||
172 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. | 160 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. |
173 | self.create_incorrect_case_diagnostic_for_func( | 161 | self.create_incorrect_case_diagnostic_for_func( |
@@ -199,8 +187,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
199 | let ast_ptr = match fn_src.value.name() { | 187 | let ast_ptr = match fn_src.value.name() { |
200 | Some(name) => name, | 188 | Some(name) => name, |
201 | None => { | 189 | None => { |
202 | // We don't want rust-analyzer to panic over this, but it is definitely some kind of error in the logic. | 190 | never!( |
203 | log::error!( | ||
204 | "Replacement ({:?}) was generated for a function without a name: {:?}", | 191 | "Replacement ({:?}) was generated for a function without a name: {:?}", |
205 | replacement, | 192 | replacement, |
206 | fn_src | 193 | fn_src |
@@ -211,7 +198,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
211 | 198 | ||
212 | let diagnostic = IncorrectCase { | 199 | let diagnostic = IncorrectCase { |
213 | file: fn_src.file_id, | 200 | file: fn_src.file_id, |
214 | ident_type: "Function".to_string(), | 201 | ident_type: IdentType::Function, |
215 | ident: AstPtr::new(&ast_ptr).into(), | 202 | ident: AstPtr::new(&ast_ptr).into(), |
216 | expected_case: replacement.expected_case, | 203 | expected_case: replacement.expected_case, |
217 | ident_text: replacement.current_name.to_string(), | 204 | ident_text: replacement.current_name.to_string(), |
@@ -225,12 +212,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
225 | let fn_params_list = match fn_src.value.param_list() { | 212 | let fn_params_list = match fn_src.value.param_list() { |
226 | Some(params) => params, | 213 | Some(params) => params, |
227 | None => { | 214 | None => { |
228 | if !fn_param_replacements.is_empty() { | 215 | always!( |
229 | log::error!( | 216 | fn_param_replacements.is_empty(), |
230 | "Replacements ({:?}) were generated for a function parameters which had no parameters list: {:?}", | 217 | "Replacements ({:?}) were generated for a function parameters which had no parameters list: {:?}", |
231 | fn_param_replacements, fn_src | 218 | fn_param_replacements, |
232 | ); | 219 | fn_src |
233 | } | 220 | ); |
234 | return; | 221 | return; |
235 | } | 222 | } |
236 | }; | 223 | }; |
@@ -240,23 +227,25 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
240 | // actual params list, but just some of them (ones that named correctly) are skipped. | 227 | // actual params list, but just some of them (ones that named correctly) are skipped. |
241 | let ast_ptr: ast::Name = loop { | 228 | let ast_ptr: ast::Name = loop { |
242 | match fn_params_iter.next() { | 229 | match fn_params_iter.next() { |
243 | Some(element) | 230 | Some(element) => { |
244 | if pat_equals_to_name(element.pat(), ¶m_to_rename.current_name) => | 231 | if let Some(ast::Pat::IdentPat(pat)) = element.pat() { |
245 | { | 232 | if pat.to_string() == param_to_rename.current_name.to_string() { |
246 | if let ast::Pat::IdentPat(pat) = element.pat().unwrap() { | 233 | if let Some(name) = pat.name() { |
247 | break pat.name().unwrap(); | 234 | break name; |
248 | } else { | 235 | } |
249 | // This is critical. If we consider this parameter the expected one, | 236 | // This is critical. If we consider this parameter the expected one, |
250 | // it **must** have a name. | 237 | // it **must** have a name. |
251 | panic!( | 238 | never!( |
252 | "Pattern {:?} equals to expected replacement {:?}, but has no name", | 239 | "Pattern {:?} equals to expected replacement {:?}, but has no name", |
253 | element, param_to_rename | 240 | element, |
254 | ); | 241 | param_to_rename |
242 | ); | ||
243 | return; | ||
244 | } | ||
255 | } | 245 | } |
256 | } | 246 | } |
257 | Some(_) => {} | ||
258 | None => { | 247 | None => { |
259 | log::error!( | 248 | never!( |
260 | "Replacement ({:?}) was generated for a function parameter which was not found: {:?}", | 249 | "Replacement ({:?}) was generated for a function parameter which was not found: {:?}", |
261 | param_to_rename, fn_src | 250 | param_to_rename, fn_src |
262 | ); | 251 | ); |
@@ -267,7 +256,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
267 | 256 | ||
268 | let diagnostic = IncorrectCase { | 257 | let diagnostic = IncorrectCase { |
269 | file: fn_src.file_id, | 258 | file: fn_src.file_id, |
270 | ident_type: "Argument".to_string(), | 259 | ident_type: IdentType::Argument, |
271 | ident: AstPtr::new(&ast_ptr).into(), | 260 | ident: AstPtr::new(&ast_ptr).into(), |
272 | expected_case: param_to_rename.expected_case, | 261 | expected_case: param_to_rename.expected_case, |
273 | ident_text: param_to_rename.current_name.to_string(), | 262 | ident_text: param_to_rename.current_name.to_string(), |
@@ -309,8 +298,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
309 | // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, | 298 | // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, |
310 | // because e.g. match arms are patterns as well. | 299 | // because e.g. match arms are patterns as well. |
311 | // In other words, we check that it's a named variable binding. | 300 | // In other words, we check that it's a named variable binding. |
312 | let is_binding = ast::LetStmt::cast(parent.clone()).is_some() | 301 | let is_binding = ast::LetStmt::can_cast(parent.kind()) |
313 | || (ast::MatchArm::cast(parent).is_some() | 302 | || (ast::MatchArm::can_cast(parent.kind()) |
314 | && ident_pat.at_token().is_some()); | 303 | && ident_pat.at_token().is_some()); |
315 | if !is_binding { | 304 | if !is_binding { |
316 | // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. | 305 | // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. |
@@ -319,7 +308,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
319 | 308 | ||
320 | let diagnostic = IncorrectCase { | 309 | let diagnostic = IncorrectCase { |
321 | file: source_ptr.file_id, | 310 | file: source_ptr.file_id, |
322 | ident_type: "Variable".to_string(), | 311 | ident_type: IdentType::Variable, |
323 | ident: AstPtr::new(&name_ast).into(), | 312 | ident: AstPtr::new(&name_ast).into(), |
324 | expected_case: replacement.expected_case, | 313 | expected_case: replacement.expected_case, |
325 | ident_text: replacement.current_name.to_string(), | 314 | ident_text: replacement.current_name.to_string(), |
@@ -341,17 +330,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
341 | 330 | ||
342 | // Check the structure name. | 331 | // Check the structure name. |
343 | let struct_name = data.name.to_string(); | 332 | let struct_name = data.name.to_string(); |
344 | let struct_name_replacement = if let Some(new_name) = to_camel_case(&struct_name) { | 333 | let struct_name_replacement = if !non_camel_case_allowed { |
345 | let replacement = Replacement { | 334 | to_camel_case(&struct_name).map(|new_name| Replacement { |
346 | current_name: data.name.clone(), | 335 | current_name: data.name.clone(), |
347 | suggested_text: new_name, | 336 | suggested_text: new_name, |
348 | expected_case: CaseType::UpperCamelCase, | 337 | expected_case: CaseType::UpperCamelCase, |
349 | }; | 338 | }) |
350 | if non_camel_case_allowed { | ||
351 | None | ||
352 | } else { | ||
353 | Some(replacement) | ||
354 | } | ||
355 | } else { | 339 | } else { |
356 | None | 340 | None |
357 | }; | 341 | }; |
@@ -403,8 +387,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
403 | let ast_ptr = match struct_src.value.name() { | 387 | let ast_ptr = match struct_src.value.name() { |
404 | Some(name) => name, | 388 | Some(name) => name, |
405 | None => { | 389 | None => { |
406 | // We don't want rust-analyzer to panic over this, but it is definitely some kind of error in the logic. | 390 | never!( |
407 | log::error!( | ||
408 | "Replacement ({:?}) was generated for a structure without a name: {:?}", | 391 | "Replacement ({:?}) was generated for a structure without a name: {:?}", |
409 | replacement, | 392 | replacement, |
410 | struct_src | 393 | struct_src |
@@ -415,7 +398,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
415 | 398 | ||
416 | let diagnostic = IncorrectCase { | 399 | let diagnostic = IncorrectCase { |
417 | file: struct_src.file_id, | 400 | file: struct_src.file_id, |
418 | ident_type: "Structure".to_string(), | 401 | ident_type: IdentType::Structure, |
419 | ident: AstPtr::new(&ast_ptr).into(), | 402 | ident: AstPtr::new(&ast_ptr).into(), |
420 | expected_case: replacement.expected_case, | 403 | expected_case: replacement.expected_case, |
421 | ident_text: replacement.current_name.to_string(), | 404 | ident_text: replacement.current_name.to_string(), |
@@ -428,12 +411,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
428 | let struct_fields_list = match struct_src.value.field_list() { | 411 | let struct_fields_list = match struct_src.value.field_list() { |
429 | Some(ast::FieldList::RecordFieldList(fields)) => fields, | 412 | Some(ast::FieldList::RecordFieldList(fields)) => fields, |
430 | _ => { | 413 | _ => { |
431 | if !struct_fields_replacements.is_empty() { | 414 | always!( |
432 | log::error!( | 415 | struct_fields_replacements.is_empty(), |
433 | "Replacements ({:?}) were generated for a structure fields which had no fields list: {:?}", | 416 | "Replacements ({:?}) were generated for a structure fields which had no fields list: {:?}", |
434 | struct_fields_replacements, struct_src | 417 | struct_fields_replacements, |
435 | ); | 418 | struct_src |
436 | } | 419 | ); |
437 | return; | 420 | return; |
438 | } | 421 | } |
439 | }; | 422 | }; |
@@ -442,13 +425,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
442 | // We assume that parameters in replacement are in the same order as in the | 425 | // We assume that parameters in replacement are in the same order as in the |
443 | // actual params list, but just some of them (ones that named correctly) are skipped. | 426 | // actual params list, but just some of them (ones that named correctly) are skipped. |
444 | let ast_ptr = loop { | 427 | let ast_ptr = loop { |
445 | match struct_fields_iter.next() { | 428 | match struct_fields_iter.next().and_then(|field| field.name()) { |
446 | Some(element) if names_equal(element.name(), &field_to_rename.current_name) => { | 429 | Some(field_name) => { |
447 | break element.name().unwrap() | 430 | if field_name.as_name() == field_to_rename.current_name { |
431 | break field_name; | ||
432 | } | ||
448 | } | 433 | } |
449 | Some(_) => {} | ||
450 | None => { | 434 | None => { |
451 | log::error!( | 435 | never!( |
452 | "Replacement ({:?}) was generated for a structure field which was not found: {:?}", | 436 | "Replacement ({:?}) was generated for a structure field which was not found: {:?}", |
453 | field_to_rename, struct_src | 437 | field_to_rename, struct_src |
454 | ); | 438 | ); |
@@ -459,7 +443,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
459 | 443 | ||
460 | let diagnostic = IncorrectCase { | 444 | let diagnostic = IncorrectCase { |
461 | file: struct_src.file_id, | 445 | file: struct_src.file_id, |
462 | ident_type: "Field".to_string(), | 446 | ident_type: IdentType::Field, |
463 | ident: AstPtr::new(&ast_ptr).into(), | 447 | ident: AstPtr::new(&ast_ptr).into(), |
464 | expected_case: field_to_rename.expected_case, | 448 | expected_case: field_to_rename.expected_case, |
465 | ident_text: field_to_rename.current_name.to_string(), | 449 | ident_text: field_to_rename.current_name.to_string(), |
@@ -480,31 +464,24 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
480 | 464 | ||
481 | // Check the enum name. | 465 | // Check the enum name. |
482 | let enum_name = data.name.to_string(); | 466 | let enum_name = data.name.to_string(); |
483 | let enum_name_replacement = if let Some(new_name) = to_camel_case(&enum_name) { | 467 | let enum_name_replacement = to_camel_case(&enum_name).map(|new_name| Replacement { |
484 | let replacement = Replacement { | 468 | current_name: data.name.clone(), |
485 | current_name: data.name.clone(), | 469 | suggested_text: new_name, |
486 | suggested_text: new_name, | 470 | expected_case: CaseType::UpperCamelCase, |
487 | expected_case: CaseType::UpperCamelCase, | 471 | }); |
488 | }; | ||
489 | Some(replacement) | ||
490 | } else { | ||
491 | None | ||
492 | }; | ||
493 | 472 | ||
494 | // Check the field names. | 473 | // Check the field names. |
495 | let mut enum_fields_replacements = Vec::new(); | 474 | let enum_fields_replacements = data |
496 | 475 | .variants | |
497 | for (_, variant) in data.variants.iter() { | 476 | .iter() |
498 | let variant_name = variant.name.to_string(); | 477 | .filter_map(|(_, variant)| { |
499 | if let Some(new_name) = to_camel_case(&variant_name) { | 478 | Some(Replacement { |
500 | let replacement = Replacement { | ||
501 | current_name: variant.name.clone(), | 479 | current_name: variant.name.clone(), |
502 | suggested_text: new_name, | 480 | suggested_text: to_camel_case(&variant.name.to_string())?, |
503 | expected_case: CaseType::UpperCamelCase, | 481 | expected_case: CaseType::UpperCamelCase, |
504 | }; | 482 | }) |
505 | enum_fields_replacements.push(replacement); | 483 | }) |
506 | } | 484 | .collect(); |
507 | } | ||
508 | 485 | ||
509 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. | 486 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. |
510 | self.create_incorrect_case_diagnostic_for_enum( | 487 | self.create_incorrect_case_diagnostic_for_enum( |
@@ -534,8 +511,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
534 | let ast_ptr = match enum_src.value.name() { | 511 | let ast_ptr = match enum_src.value.name() { |
535 | Some(name) => name, | 512 | Some(name) => name, |
536 | None => { | 513 | None => { |
537 | // We don't want rust-analyzer to panic over this, but it is definitely some kind of error in the logic. | 514 | never!( |
538 | log::error!( | ||
539 | "Replacement ({:?}) was generated for a enum without a name: {:?}", | 515 | "Replacement ({:?}) was generated for a enum without a name: {:?}", |
540 | replacement, | 516 | replacement, |
541 | enum_src | 517 | enum_src |
@@ -546,7 +522,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
546 | 522 | ||
547 | let diagnostic = IncorrectCase { | 523 | let diagnostic = IncorrectCase { |
548 | file: enum_src.file_id, | 524 | file: enum_src.file_id, |
549 | ident_type: "Enum".to_string(), | 525 | ident_type: IdentType::Enum, |
550 | ident: AstPtr::new(&ast_ptr).into(), | 526 | ident: AstPtr::new(&ast_ptr).into(), |
551 | expected_case: replacement.expected_case, | 527 | expected_case: replacement.expected_case, |
552 | ident_text: replacement.current_name.to_string(), | 528 | ident_text: replacement.current_name.to_string(), |
@@ -559,12 +535,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
559 | let enum_variants_list = match enum_src.value.variant_list() { | 535 | let enum_variants_list = match enum_src.value.variant_list() { |
560 | Some(variants) => variants, | 536 | Some(variants) => variants, |
561 | _ => { | 537 | _ => { |
562 | if !enum_variants_replacements.is_empty() { | 538 | always!( |
563 | log::error!( | 539 | enum_variants_replacements.is_empty(), |
564 | "Replacements ({:?}) were generated for a enum variants which had no fields list: {:?}", | 540 | "Replacements ({:?}) were generated for a enum variants which had no fields list: {:?}", |
565 | enum_variants_replacements, enum_src | 541 | enum_variants_replacements, |
566 | ); | 542 | enum_src |
567 | } | 543 | ); |
568 | return; | 544 | return; |
569 | } | 545 | } |
570 | }; | 546 | }; |
@@ -573,15 +549,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
573 | // We assume that parameters in replacement are in the same order as in the | 549 | // We assume that parameters in replacement are in the same order as in the |
574 | // actual params list, but just some of them (ones that named correctly) are skipped. | 550 | // actual params list, but just some of them (ones that named correctly) are skipped. |
575 | let ast_ptr = loop { | 551 | let ast_ptr = loop { |
576 | match enum_variants_iter.next() { | 552 | match enum_variants_iter.next().and_then(|v| v.name()) { |
577 | Some(variant) | 553 | Some(variant_name) => { |
578 | if names_equal(variant.name(), &variant_to_rename.current_name) => | 554 | if variant_name.as_name() == variant_to_rename.current_name { |
579 | { | 555 | break variant_name; |
580 | break variant.name().unwrap() | 556 | } |
581 | } | 557 | } |
582 | Some(_) => {} | ||
583 | None => { | 558 | None => { |
584 | log::error!( | 559 | never!( |
585 | "Replacement ({:?}) was generated for a enum variant which was not found: {:?}", | 560 | "Replacement ({:?}) was generated for a enum variant which was not found: {:?}", |
586 | variant_to_rename, enum_src | 561 | variant_to_rename, enum_src |
587 | ); | 562 | ); |
@@ -592,7 +567,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
592 | 567 | ||
593 | let diagnostic = IncorrectCase { | 568 | let diagnostic = IncorrectCase { |
594 | file: enum_src.file_id, | 569 | file: enum_src.file_id, |
595 | ident_type: "Variant".to_string(), | 570 | ident_type: IdentType::Variant, |
596 | ident: AstPtr::new(&ast_ptr).into(), | 571 | ident: AstPtr::new(&ast_ptr).into(), |
597 | expected_case: variant_to_rename.expected_case, | 572 | expected_case: variant_to_rename.expected_case, |
598 | ident_text: variant_to_rename.current_name.to_string(), | 573 | ident_text: variant_to_rename.current_name.to_string(), |
@@ -637,7 +612,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
637 | 612 | ||
638 | let diagnostic = IncorrectCase { | 613 | let diagnostic = IncorrectCase { |
639 | file: const_src.file_id, | 614 | file: const_src.file_id, |
640 | ident_type: "Constant".to_string(), | 615 | ident_type: IdentType::Constant, |
641 | ident: AstPtr::new(&ast_ptr).into(), | 616 | ident: AstPtr::new(&ast_ptr).into(), |
642 | expected_case: replacement.expected_case, | 617 | expected_case: replacement.expected_case, |
643 | ident_text: replacement.current_name.to_string(), | 618 | ident_text: replacement.current_name.to_string(), |
@@ -685,7 +660,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
685 | 660 | ||
686 | let diagnostic = IncorrectCase { | 661 | let diagnostic = IncorrectCase { |
687 | file: static_src.file_id, | 662 | file: static_src.file_id, |
688 | ident_type: "Static variable".to_string(), | 663 | ident_type: IdentType::StaticVariable, |
689 | ident: AstPtr::new(&ast_ptr).into(), | 664 | ident: AstPtr::new(&ast_ptr).into(), |
690 | expected_case: replacement.expected_case, | 665 | expected_case: replacement.expected_case, |
691 | ident_text: replacement.current_name.to_string(), | 666 | ident_text: replacement.current_name.to_string(), |
@@ -696,22 +671,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
696 | } | 671 | } |
697 | } | 672 | } |
698 | 673 | ||
699 | fn names_equal(left: Option<ast::Name>, right: &Name) -> bool { | ||
700 | if let Some(left) = left { | ||
701 | &left.as_name() == right | ||
702 | } else { | ||
703 | false | ||
704 | } | ||
705 | } | ||
706 | |||
707 | fn pat_equals_to_name(pat: Option<ast::Pat>, name: &Name) -> bool { | ||
708 | if let Some(ast::Pat::IdentPat(ident)) = pat { | ||
709 | ident.to_string() == name.to_string() | ||
710 | } else { | ||
711 | false | ||
712 | } | ||
713 | } | ||
714 | |||
715 | #[cfg(test)] | 674 | #[cfg(test)] |
716 | mod tests { | 675 | mod tests { |
717 | use test_utils::mark; | 676 | use test_utils::mark; |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index a3d4e4f77..9bed329d8 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -72,7 +72,7 @@ pub(crate) fn highlight( | |||
72 | } | 72 | } |
73 | }; | 73 | }; |
74 | 74 | ||
75 | let mut hl = highlights::Highlights::new(range_to_highlight); | 75 | let mut hl = highlights::Highlights::new(root.text_range()); |
76 | traverse(&mut hl, &sema, &root, range_to_highlight, syntactic_name_ref_highlighting); | 76 | traverse(&mut hl, &sema, &root, range_to_highlight, syntactic_name_ref_highlighting); |
77 | hl.to_vec() | 77 | hl.to_vec() |
78 | } | 78 | } |
diff --git a/crates/proc_macro_api/src/rpc.rs b/crates/proc_macro_api/src/rpc.rs index cf830b59f..64cfdafc5 100644 --- a/crates/proc_macro_api/src/rpc.rs +++ b/crates/proc_macro_api/src/rpc.rs | |||
@@ -262,7 +262,7 @@ mod tests { | |||
262 | 262 | ||
263 | assert_eq!(task.macro_body, back.macro_body); | 263 | assert_eq!(task.macro_body, back.macro_body); |
264 | 264 | ||
265 | let result = ExpansionResult { expansion: tt.clone() }; | 265 | let result = ExpansionResult { expansion: tt }; |
266 | let json = serde_json::to_string(&result).unwrap(); | 266 | let json = serde_json::to_string(&result).unwrap(); |
267 | let back: ExpansionResult = serde_json::from_str(&json).unwrap(); | 267 | let back: ExpansionResult = serde_json::from_str(&json).unwrap(); |
268 | 268 | ||
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index 5866c0a28..d28b5e658 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml | |||
@@ -11,7 +11,7 @@ doctest = false | |||
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | backtrace = { version = "0.3.44", optional = true } | 13 | backtrace = { version = "0.3.44", optional = true } |
14 | always-assert = { version = "0.1.1", features = ["log"] } | 14 | always-assert = { version = "0.1.2", features = ["log"] } |
15 | # Think twice before adding anything here | 15 | # Think twice before adding anything here |
16 | 16 | ||
17 | [features] | 17 | [features] |
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index e40b61a94..e3f57f3b2 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs | |||
@@ -95,16 +95,7 @@ impl Fixture { | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | Fixture { | 98 | Fixture { path, text: String::new(), krate, deps, cfg_atoms, cfg_key_values, edition, env } |
99 | path, | ||
100 | text: String::new(), | ||
101 | krate: krate, | ||
102 | deps, | ||
103 | cfg_atoms, | ||
104 | cfg_key_values, | ||
105 | edition, | ||
106 | env, | ||
107 | } | ||
108 | } | 99 | } |
109 | } | 100 | } |
110 | 101 | ||
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md index cc7a790ff..5876e71bc 100644 --- a/docs/dev/debugging.md +++ b/docs/dev/debugging.md | |||
@@ -10,7 +10,7 @@ | |||
10 | - Install all TypeScript dependencies | 10 | - Install all TypeScript dependencies |
11 | ```bash | 11 | ```bash |
12 | cd editors/code | 12 | cd editors/code |
13 | npm install | 13 | npm ci |
14 | ``` | 14 | ``` |
15 | 15 | ||
16 | ## Common knowledge | 16 | ## Common knowledge |
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 81b9956b8..3b79cca0d 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -129,7 +129,7 @@ fn install_client(client_opt: ClientOpt) -> Result<()> { | |||
129 | 129 | ||
130 | let installed_extensions = if cfg!(unix) { | 130 | let installed_extensions = if cfg!(unix) { |
131 | cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?; | 131 | cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?; |
132 | cmd!("npm install").run()?; | 132 | cmd!("npm ci").run()?; |
133 | 133 | ||
134 | cmd!("npm run package --scripts-prepend-node-path").run()?; | 134 | cmd!("npm run package --scripts-prepend-node-path").run()?; |
135 | 135 | ||
@@ -140,7 +140,7 @@ fn install_client(client_opt: ClientOpt) -> Result<()> { | |||
140 | cmd!("cmd.exe /c npm --version") | 140 | cmd!("cmd.exe /c npm --version") |
141 | .run() | 141 | .run() |
142 | .context("`npm` is required to build the VS Code plugin")?; | 142 | .context("`npm` is required to build the VS Code plugin")?; |
143 | cmd!("cmd.exe /c npm install").run()?; | 143 | cmd!("cmd.exe /c npm ci").run()?; |
144 | 144 | ||
145 | cmd!("cmd.exe /c npm run package").run()?; | 145 | cmd!("cmd.exe /c npm run package").run()?; |
146 | 146 | ||