aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorIgor Aleksanov <[email protected]>2020-10-03 12:47:46 +0100
committerIgor Aleksanov <[email protected]>2020-10-12 08:59:54 +0100
commit329626124f360feadb47e83be5690861c62a4b70 (patch)
tree56a1f8e3b351ae739b4c3c373ebd93ba81c18dc4 /crates/hir_ty
parent1773c6d154abe5da00b31bb16139addcaa443bbb (diff)
Add check for structure names to be CamelCase
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs138
2 files changed, 139 insertions, 1 deletions
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 24fff690a..bd370e3b2 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -257,7 +257,7 @@ impl fmt::Display for CaseType {
257 let repr = match self { 257 let repr = match self {
258 CaseType::LowerSnakeCase => "snake_case", 258 CaseType::LowerSnakeCase => "snake_case",
259 CaseType::UpperSnakeCase => "UPPER_SNAKE_CASE", 259 CaseType::UpperSnakeCase => "UPPER_SNAKE_CASE",
260 CaseType::UpperCamelCase => "UpperCamelCase", 260 CaseType::UpperCamelCase => "CamelCase",
261 }; 261 };
262 262
263 write!(f, "{}", repr) 263 write!(f, "{}", repr)
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 1a0906492..b7f511fd8 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -14,6 +14,7 @@ mod str_helpers;
14use std::sync::Arc; 14use std::sync::Arc;
15 15
16use hir_def::{ 16use hir_def::{
17 adt::VariantData,
17 body::Body, 18 body::Body,
18 db::DefDatabase, 19 db::DefDatabase,
19 expr::{Expr, ExprId, UnaryOp}, 20 expr::{Expr, ExprId, UnaryOp},
@@ -205,6 +206,133 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
205 206
206 fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) { 207 fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) {
207 let data = db.struct_data(struct_id); 208 let data = db.struct_data(struct_id);
209
210 // 1. Check the structure name.
211 let struct_name = data.name.to_string();
212 let struct_name_replacement = if let Some(new_name) = to_camel_case(&struct_name) {
213 let replacement = Replacement {
214 current_name: data.name.clone(),
215 suggested_text: new_name,
216 expected_case: CaseType::UpperCamelCase,
217 };
218 Some(replacement)
219 } else {
220 None
221 };
222
223 // 2. Check the field names.
224 let mut struct_fields_replacements = Vec::new();
225
226 if let VariantData::Record(fields) = data.variant_data.as_ref() {
227 for (_, field) in fields.iter() {
228 let field_name = field.name.to_string();
229 if let Some(new_name) = to_lower_snake_case(&field_name) {
230 let replacement = Replacement {
231 current_name: field.name.clone(),
232 suggested_text: new_name,
233 expected_case: CaseType::LowerSnakeCase,
234 };
235 struct_fields_replacements.push(replacement);
236 }
237 }
238 }
239
240 // 3. If there is at least one element to spawn a warning on, go to the source map and generate a warning.
241 self.create_incorrect_case_diagnostic_for_struct(
242 struct_id,
243 db,
244 struct_name_replacement,
245 struct_fields_replacements,
246 )
247 }
248
249 /// Given the information about incorrect names in the struct declaration, looks up into the source code
250 /// for exact locations and adds diagnostics into the sink.
251 fn create_incorrect_case_diagnostic_for_struct(
252 &mut self,
253 struct_id: StructId,
254 db: &dyn HirDatabase,
255 struct_name_replacement: Option<Replacement>,
256 struct_fields_replacements: Vec<Replacement>,
257 ) {
258 // XXX: only look at sources if we do have incorrect names
259 if struct_name_replacement.is_none() && struct_fields_replacements.is_empty() {
260 return;
261 }
262
263 let struct_loc = struct_id.lookup(db.upcast());
264 let struct_src = struct_loc.source(db.upcast());
265
266 if let Some(replacement) = struct_name_replacement {
267 let ast_ptr = if let Some(name) = struct_src.value.name() {
268 name
269 } else {
270 // We don't want rust-analyzer to panic over this, but it is definitely some kind of error in the logic.
271 log::error!(
272 "Replacement ({:?}) was generated for a structure without a name: {:?}",
273 replacement,
274 struct_src
275 );
276 return;
277 };
278
279 let diagnostic = IncorrectCase {
280 file: struct_src.file_id,
281 ident_type: "Structure".to_string(),
282 ident: AstPtr::new(&ast_ptr).into(),
283 expected_case: replacement.expected_case,
284 ident_text: replacement.current_name.to_string(),
285 suggested_text: replacement.suggested_text,
286 };
287
288 self.sink.push(diagnostic);
289 }
290
291 // let fn_params_list = match fn_src.value.param_list() {
292 // Some(params) => params,
293 // None => {
294 // if !fn_param_replacements.is_empty() {
295 // log::error!(
296 // "Replacements ({:?}) were generated for a function parameters which had no parameters list: {:?}",
297 // fn_param_replacements, fn_src
298 // );
299 // }
300 // return;
301 // }
302 // };
303 // let mut fn_params_iter = fn_params_list.params();
304 // for param_to_rename in fn_param_replacements {
305 // // We assume that parameters in replacement are in the same order as in the
306 // // actual params list, but just some of them (ones that named correctly) are skipped.
307 // let ast_ptr = loop {
308 // match fn_params_iter.next() {
309 // Some(element)
310 // if pat_equals_to_name(element.pat(), &param_to_rename.current_name) =>
311 // {
312 // break element.pat().unwrap()
313 // }
314 // Some(_) => {}
315 // None => {
316 // log::error!(
317 // "Replacement ({:?}) was generated for a function parameter which was not found: {:?}",
318 // param_to_rename, fn_src
319 // );
320 // return;
321 // }
322 // }
323 // };
324
325 // let diagnostic = IncorrectCase {
326 // file: fn_src.file_id,
327 // ident_type: "Argument".to_string(),
328 // ident: AstPtr::new(&ast_ptr).into(),
329 // expected_case: param_to_rename.expected_case,
330 // ident_text: param_to_rename.current_name.to_string(),
331 // suggested_text: param_to_rename.suggested_text,
332 // };
333
334 // self.sink.push(diagnostic);
335 // }
208 } 336 }
209 337
210 fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) { 338 fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) {
@@ -246,4 +374,14 @@ fn foo2(ok_param: &str, CAPS_PARAM: u8) {}
246"#, 374"#,
247 ); 375 );
248 } 376 }
377
378 #[test]
379 fn incorrect_struct_name() {
380 check_diagnostics(
381 r#"
382struct non_camel_case_name {}
383 // ^^^^^^^^^^^^^^^^^^^ Structure `non_camel_case_name` should have a CamelCase name, e.g. `NonCamelCaseName`
384"#,
385 );
386 }
249} 387}