diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 35 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics_sink.rs (renamed from crates/hir_ty/src/diagnostics_sink.rs) | 0 | ||||
| -rw-r--r-- | crates/hir/src/lib.rs | 32 | ||||
| -rw-r--r-- | crates/hir_ty/src/diagnostics.rs | 156 | ||||
| -rw-r--r-- | crates/hir_ty/src/diagnostics/decl_check.rs | 359 | ||||
| -rw-r--r-- | crates/hir_ty/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/ide/src/diagnostics.rs | 354 |
7 files changed, 417 insertions, 520 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 26dbcd86a..8a7c3a4fd 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
| @@ -11,9 +11,8 @@ use hir_expand::{name::Name, HirFileId, InFile}; | |||
| 11 | use stdx::format_to; | 11 | use stdx::format_to; |
| 12 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; | 12 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; |
| 13 | 13 | ||
| 14 | pub use hir_ty::{ | 14 | pub use crate::diagnostics_sink::{ |
| 15 | diagnostics::IncorrectCase, | 15 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, |
| 16 | diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, | ||
| 17 | }; | 16 | }; |
| 18 | 17 | ||
| 19 | // Diagnostic: unresolved-module | 18 | // Diagnostic: unresolved-module |
| @@ -578,3 +577,33 @@ impl Diagnostic for InternalBailedOut { | |||
| 578 | self | 577 | self |
| 579 | } | 578 | } |
| 580 | } | 579 | } |
| 580 | |||
| 581 | pub use hir_ty::diagnostics::IncorrectCase; | ||
| 582 | |||
| 583 | impl Diagnostic for IncorrectCase { | ||
| 584 | fn code(&self) -> DiagnosticCode { | ||
| 585 | DiagnosticCode("incorrect-ident-case") | ||
| 586 | } | ||
| 587 | |||
| 588 | fn message(&self) -> String { | ||
| 589 | format!( | ||
| 590 | "{} `{}` should have {} name, e.g. `{}`", | ||
| 591 | self.ident_type, | ||
| 592 | self.ident_text, | ||
| 593 | self.expected_case.to_string(), | ||
| 594 | self.suggested_text | ||
| 595 | ) | ||
| 596 | } | ||
| 597 | |||
| 598 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
| 599 | InFile::new(self.file, self.ident.clone().into()) | ||
| 600 | } | ||
| 601 | |||
| 602 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
| 603 | self | ||
| 604 | } | ||
| 605 | |||
| 606 | fn is_experimental(&self) -> bool { | ||
| 607 | true | ||
| 608 | } | ||
| 609 | } | ||
diff --git a/crates/hir_ty/src/diagnostics_sink.rs b/crates/hir/src/diagnostics_sink.rs index 084fa8b06..084fa8b06 100644 --- a/crates/hir_ty/src/diagnostics_sink.rs +++ b/crates/hir/src/diagnostics_sink.rs | |||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index dd5515c2b..2468c0dc6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
| @@ -27,6 +27,7 @@ mod attrs; | |||
| 27 | mod has_source; | 27 | mod has_source; |
| 28 | 28 | ||
| 29 | pub mod diagnostics; | 29 | pub mod diagnostics; |
| 30 | pub mod diagnostics_sink; | ||
| 30 | pub mod db; | 31 | pub mod db; |
| 31 | 32 | ||
| 32 | mod display; | 33 | mod display; |
| @@ -35,13 +36,6 @@ use std::{iter, sync::Arc}; | |||
| 35 | 36 | ||
| 36 | use arrayvec::ArrayVec; | 37 | use arrayvec::ArrayVec; |
| 37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | 38 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; |
| 38 | use diagnostics::{ | ||
| 39 | BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError, MismatchedArgCount, | ||
| 40 | MissingFields, MissingOkOrSomeInTailExpr, MissingPatFields, MissingUnsafe, NoSuchField, | ||
| 41 | RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnimplementedBuiltinMacro, | ||
| 42 | UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule, | ||
| 43 | UnresolvedProcMacro, | ||
| 44 | }; | ||
| 45 | use either::Either; | 39 | use either::Either; |
| 46 | use hir_def::{ | 40 | use hir_def::{ |
| 47 | adt::{ReprKind, VariantData}, | 41 | adt::{ReprKind, VariantData}, |
| @@ -64,8 +58,7 @@ use hir_ty::{ | |||
| 64 | consteval::ConstExt, | 58 | consteval::ConstExt, |
| 65 | could_unify, | 59 | could_unify, |
| 66 | diagnostics::BodyValidationDiagnostic, | 60 | diagnostics::BodyValidationDiagnostic, |
| 67 | diagnostics_sink::DiagnosticSink, | 61 | method_resolution::{self, TyFingerprint}, |
| 68 | method_resolution::{self, def_crates, TyFingerprint}, | ||
| 69 | primitive::UintTy, | 62 | primitive::UintTy, |
| 70 | subst_prefix, | 63 | subst_prefix, |
| 71 | traits::FnTrait, | 64 | traits::FnTrait, |
| @@ -87,7 +80,14 @@ use tt::{Ident, Leaf, Literal, TokenTree}; | |||
| 87 | 80 | ||
| 88 | use crate::{ | 81 | use crate::{ |
| 89 | db::{DefDatabase, HirDatabase}, | 82 | db::{DefDatabase, HirDatabase}, |
| 90 | diagnostics::MissingMatchArms, | 83 | diagnostics::{ |
| 84 | BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError, MismatchedArgCount, | ||
| 85 | MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, MissingPatFields, | ||
| 86 | MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, | ||
| 87 | UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, | ||
| 88 | UnresolvedModule, UnresolvedProcMacro, | ||
| 89 | }, | ||
| 90 | diagnostics_sink::DiagnosticSink, | ||
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | pub use crate::{ | 93 | pub use crate::{ |
| @@ -361,7 +361,9 @@ impl ModuleDef { | |||
| 361 | None => return, | 361 | None => return, |
| 362 | }; | 362 | }; |
| 363 | 363 | ||
| 364 | hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink) | 364 | for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) { |
| 365 | sink.push(diag) | ||
| 366 | } | ||
| 365 | } | 367 | } |
| 366 | } | 368 | } |
| 367 | 369 | ||
| @@ -1225,7 +1227,9 @@ impl Function { | |||
| 1225 | } | 1227 | } |
| 1226 | } | 1228 | } |
| 1227 | 1229 | ||
| 1228 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | 1230 | for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) { |
| 1231 | sink.push(diag) | ||
| 1232 | } | ||
| 1229 | } | 1233 | } |
| 1230 | 1234 | ||
| 1231 | /// Whether this function declaration has a definition. | 1235 | /// Whether this function declaration has a definition. |
| @@ -1944,7 +1948,7 @@ impl Impl { | |||
| 1944 | } | 1948 | } |
| 1945 | 1949 | ||
| 1946 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { | 1950 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { |
| 1947 | let def_crates = match def_crates(db, &ty, krate) { | 1951 | let def_crates = match method_resolution::def_crates(db, &ty, krate) { |
| 1948 | Some(def_crates) => def_crates, | 1952 | Some(def_crates) => def_crates, |
| 1949 | None => return Vec::new(), | 1953 | None => return Vec::new(), |
| 1950 | }; | 1954 | }; |
| @@ -2350,7 +2354,7 @@ impl Type { | |||
| 2350 | krate: Crate, | 2354 | krate: Crate, |
| 2351 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 2355 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
| 2352 | ) -> Option<T> { | 2356 | ) -> Option<T> { |
| 2353 | for krate in def_crates(db, &self.ty, krate.id)? { | 2357 | for krate in method_resolution::def_crates(db, &self.ty, krate.id)? { |
| 2354 | let impls = db.inherent_impls_in_crate(krate); | 2358 | let impls = db.inherent_impls_in_crate(krate); |
| 2355 | 2359 | ||
| 2356 | for impl_def in impls.for_self_ty(&self.ty) { | 2360 | for impl_def in impls.for_self_ty(&self.ty) { |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index f3236bc06..407273943 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
| @@ -4,17 +4,14 @@ mod match_check; | |||
| 4 | mod unsafe_check; | 4 | mod unsafe_check; |
| 5 | mod decl_check; | 5 | mod decl_check; |
| 6 | 6 | ||
| 7 | use std::{any::Any, fmt}; | 7 | use std::fmt; |
| 8 | 8 | ||
| 9 | use base_db::CrateId; | 9 | use base_db::CrateId; |
| 10 | use hir_def::ModuleDefId; | 10 | use hir_def::ModuleDefId; |
| 11 | use hir_expand::{HirFileId, InFile}; | 11 | use hir_expand::HirFileId; |
| 12 | use syntax::{ast, AstPtr, SyntaxNodePtr}; | 12 | use syntax::{ast, AstPtr}; |
| 13 | 13 | ||
| 14 | use crate::{ | 14 | use crate::db::HirDatabase; |
| 15 | db::HirDatabase, | ||
| 16 | diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink}, | ||
| 17 | }; | ||
| 18 | 15 | ||
| 19 | pub use crate::diagnostics::{ | 16 | pub use crate::diagnostics::{ |
| 20 | expr::{ | 17 | expr::{ |
| @@ -27,11 +24,11 @@ pub fn validate_module_item( | |||
| 27 | db: &dyn HirDatabase, | 24 | db: &dyn HirDatabase, |
| 28 | krate: CrateId, | 25 | krate: CrateId, |
| 29 | owner: ModuleDefId, | 26 | owner: ModuleDefId, |
| 30 | sink: &mut DiagnosticSink<'_>, | 27 | ) -> Vec<IncorrectCase> { |
| 31 | ) { | ||
| 32 | let _p = profile::span("validate_module_item"); | 28 | let _p = profile::span("validate_module_item"); |
| 33 | let mut validator = decl_check::DeclValidator::new(db, krate, sink); | 29 | let mut validator = decl_check::DeclValidator::new(db, krate); |
| 34 | validator.validate_item(owner); | 30 | validator.validate_item(owner); |
| 31 | validator.sink | ||
| 35 | } | 32 | } |
| 36 | 33 | ||
| 37 | #[derive(Debug)] | 34 | #[derive(Debug)] |
| @@ -99,142 +96,3 @@ pub struct IncorrectCase { | |||
| 99 | pub ident_text: String, | 96 | pub ident_text: String, |
| 100 | pub suggested_text: String, | 97 | pub suggested_text: String, |
| 101 | } | 98 | } |
| 102 | |||
| 103 | impl Diagnostic for IncorrectCase { | ||
| 104 | fn code(&self) -> DiagnosticCode { | ||
| 105 | DiagnosticCode("incorrect-ident-case") | ||
| 106 | } | ||
| 107 | |||
| 108 | fn message(&self) -> String { | ||
| 109 | format!( | ||
| 110 | "{} `{}` should have {} name, e.g. `{}`", | ||
| 111 | self.ident_type, | ||
| 112 | self.ident_text, | ||
| 113 | self.expected_case.to_string(), | ||
| 114 | self.suggested_text | ||
| 115 | ) | ||
| 116 | } | ||
| 117 | |||
| 118 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
| 119 | InFile::new(self.file, self.ident.clone().into()) | ||
| 120 | } | ||
| 121 | |||
| 122 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
| 123 | self | ||
| 124 | } | ||
| 125 | |||
| 126 | fn is_experimental(&self) -> bool { | ||
| 127 | true | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | #[cfg(test)] | ||
| 132 | mod tests { | ||
| 133 | use base_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; | ||
| 134 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; | ||
| 135 | use hir_expand::db::AstDatabase; | ||
| 136 | use rustc_hash::FxHashMap; | ||
| 137 | use syntax::{TextRange, TextSize}; | ||
| 138 | |||
| 139 | use crate::{ | ||
| 140 | diagnostics::validate_module_item, | ||
| 141 | diagnostics_sink::{Diagnostic, DiagnosticSinkBuilder}, | ||
| 142 | test_db::TestDB, | ||
| 143 | }; | ||
| 144 | |||
| 145 | impl TestDB { | ||
| 146 | fn diagnostics<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) { | ||
| 147 | let crate_graph = self.crate_graph(); | ||
| 148 | for krate in crate_graph.iter() { | ||
| 149 | let crate_def_map = self.crate_def_map(krate); | ||
| 150 | |||
| 151 | let mut fns = Vec::new(); | ||
| 152 | for (module_id, _) in crate_def_map.modules() { | ||
| 153 | for decl in crate_def_map[module_id].scope.declarations() { | ||
| 154 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | ||
| 155 | validate_module_item(self, krate, decl, &mut sink); | ||
| 156 | |||
| 157 | if let ModuleDefId::FunctionId(f) = decl { | ||
| 158 | fns.push(f) | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | for impl_id in crate_def_map[module_id].scope.impls() { | ||
| 163 | let impl_data = self.impl_data(impl_id); | ||
| 164 | for item in impl_data.items.iter() { | ||
| 165 | if let AssocItemId::FunctionId(f) = item { | ||
| 166 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | ||
| 167 | validate_module_item( | ||
| 168 | self, | ||
| 169 | krate, | ||
| 170 | ModuleDefId::FunctionId(*f), | ||
| 171 | &mut sink, | ||
| 172 | ); | ||
| 173 | fns.push(*f) | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | pub(crate) fn check_diagnostics(ra_fixture: &str) { | ||
| 183 | let db = TestDB::with_files(ra_fixture); | ||
| 184 | let annotations = db.extract_annotations(); | ||
| 185 | |||
| 186 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); | ||
| 187 | db.diagnostics(|d| { | ||
| 188 | let src = d.display_source(); | ||
| 189 | let root = db.parse_or_expand(src.file_id).unwrap(); | ||
| 190 | // FIXME: macros... | ||
| 191 | let file_id = src.file_id.original_file(&db); | ||
| 192 | let range = src.value.to_node(&root).text_range(); | ||
| 193 | let message = d.message(); | ||
| 194 | actual.entry(file_id).or_default().push((range, message)); | ||
| 195 | }); | ||
| 196 | |||
| 197 | for (file_id, diags) in actual.iter_mut() { | ||
| 198 | diags.sort_by_key(|it| it.0.start()); | ||
| 199 | let text = db.file_text(*file_id); | ||
| 200 | // For multiline spans, place them on line start | ||
| 201 | for (range, content) in diags { | ||
| 202 | if text[*range].contains('\n') { | ||
| 203 | *range = TextRange::new(range.start(), range.start() + TextSize::from(1)); | ||
| 204 | *content = format!("... {}", content); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | assert_eq!(annotations, actual); | ||
| 210 | } | ||
| 211 | |||
| 212 | #[test] | ||
| 213 | fn import_extern_crate_clash_with_inner_item() { | ||
| 214 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. | ||
| 215 | |||
| 216 | check_diagnostics( | ||
| 217 | r#" | ||
| 218 | //- /lib.rs crate:lib deps:jwt | ||
| 219 | mod permissions; | ||
| 220 | |||
| 221 | use permissions::jwt; | ||
| 222 | |||
| 223 | fn f() { | ||
| 224 | fn inner() {} | ||
| 225 | jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic | ||
| 226 | } | ||
| 227 | |||
| 228 | //- /permissions.rs | ||
| 229 | pub mod jwt { | ||
| 230 | pub struct Claims {} | ||
| 231 | } | ||
| 232 | |||
| 233 | //- /jwt/lib.rs crate:jwt | ||
| 234 | pub struct Claims { | ||
| 235 | field: u8, | ||
| 236 | } | ||
| 237 | "#, | ||
| 238 | ); | ||
| 239 | } | ||
| 240 | } | ||
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index cfb5d7320..ca452e879 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
| @@ -29,7 +29,6 @@ use syntax::{ | |||
| 29 | use crate::{ | 29 | use crate::{ |
| 30 | db::HirDatabase, | 30 | db::HirDatabase, |
| 31 | diagnostics::{decl_check::case_conv::*, CaseType, IdentType, IncorrectCase}, | 31 | diagnostics::{decl_check::case_conv::*, CaseType, IdentType, IncorrectCase}, |
| 32 | diagnostics_sink::DiagnosticSink, | ||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | mod allow { | 34 | mod allow { |
| @@ -40,10 +39,10 @@ mod allow { | |||
| 40 | pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; | 39 | pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; |
| 41 | } | 40 | } |
| 42 | 41 | ||
| 43 | pub(super) struct DeclValidator<'a, 'b> { | 42 | pub(super) struct DeclValidator<'a> { |
| 44 | db: &'a dyn HirDatabase, | 43 | db: &'a dyn HirDatabase, |
| 45 | krate: CrateId, | 44 | krate: CrateId, |
| 46 | sink: &'a mut DiagnosticSink<'b>, | 45 | pub(super) sink: Vec<IncorrectCase>, |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | #[derive(Debug)] | 48 | #[derive(Debug)] |
| @@ -53,13 +52,9 @@ struct Replacement { | |||
| 53 | expected_case: CaseType, | 52 | expected_case: CaseType, |
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | impl<'a, 'b> DeclValidator<'a, 'b> { | 55 | impl<'a> DeclValidator<'a> { |
| 57 | pub(super) fn new( | 56 | pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> { |
| 58 | db: &'a dyn HirDatabase, | 57 | DeclValidator { db, krate, sink: Vec::new() } |
| 59 | krate: CrateId, | ||
| 60 | sink: &'a mut DiagnosticSink<'b>, | ||
| 61 | ) -> DeclValidator<'a, 'b> { | ||
| 62 | DeclValidator { db, krate, sink } | ||
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | pub(super) fn validate_item(&mut self, item: ModuleDefId) { | 60 | pub(super) fn validate_item(&mut self, item: ModuleDefId) { |
| @@ -121,7 +116,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
| 121 | fn validate_func(&mut self, func: FunctionId) { | 116 | fn validate_func(&mut self, func: FunctionId) { |
| 122 | let data = self.db.function_data(func); | 117 | let data = self.db.function_data(func); |
| 123 | if data.is_in_extern_block() { | 118 | if data.is_in_extern_block() { |
| 124 | cov_mark::hit!(extern_func_incorrect_case_ignored); | ||
| 125 | return; | 119 | return; |
| 126 | } | 120 | } |
| 127 | 121 | ||
| @@ -131,7 +125,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
| 131 | for (_, block_def_map) in body.blocks(self.db.upcast()) { | 125 | for (_, block_def_map) in body.blocks(self.db.upcast()) { |
| 132 | for (_, module) in block_def_map.modules() { | 126 | for (_, module) in block_def_map.modules() { |
| 133 | for def_id in module.scope.declarations() { | 127 | for def_id in module.scope.declarations() { |
| 134 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 128 | let mut validator = DeclValidator::new(self.db, self.krate); |
| 135 | validator.validate_item(def_id); | 129 | validator.validate_item(def_id); |
| 136 | } | 130 | } |
| 137 | } | 131 | } |
| @@ -578,7 +572,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
| 578 | fn validate_static(&mut self, static_id: StaticId) { | 572 | fn validate_static(&mut self, static_id: StaticId) { |
| 579 | let data = self.db.static_data(static_id); | 573 | let data = self.db.static_data(static_id); |
| 580 | if data.is_extern { | 574 | if data.is_extern { |
| 581 | cov_mark::hit!(extern_static_incorrect_case_ignored); | ||
| 582 | return; | 575 | return; |
| 583 | } | 576 | } |
| 584 | 577 | ||
| @@ -623,343 +616,3 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
| 623 | self.sink.push(diagnostic); | 616 | self.sink.push(diagnostic); |
| 624 | } | 617 | } |
| 625 | } | 618 | } |
| 626 | |||
| 627 | #[cfg(test)] | ||
| 628 | mod tests { | ||
| 629 | use crate::diagnostics::tests::check_diagnostics; | ||
| 630 | |||
| 631 | #[test] | ||
| 632 | fn incorrect_function_name() { | ||
| 633 | check_diagnostics( | ||
| 634 | r#" | ||
| 635 | fn NonSnakeCaseName() {} | ||
| 636 | // ^^^^^^^^^^^^^^^^ Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name` | ||
| 637 | "#, | ||
| 638 | ); | ||
| 639 | } | ||
| 640 | |||
| 641 | #[test] | ||
| 642 | fn incorrect_function_params() { | ||
| 643 | check_diagnostics( | ||
| 644 | r#" | ||
| 645 | fn foo(SomeParam: u8) {} | ||
| 646 | // ^^^^^^^^^ Parameter `SomeParam` should have snake_case name, e.g. `some_param` | ||
| 647 | |||
| 648 | fn foo2(ok_param: &str, CAPS_PARAM: u8) {} | ||
| 649 | // ^^^^^^^^^^ Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param` | ||
| 650 | "#, | ||
| 651 | ); | ||
| 652 | } | ||
| 653 | |||
| 654 | #[test] | ||
| 655 | fn incorrect_variable_names() { | ||
| 656 | check_diagnostics( | ||
| 657 | r#" | ||
| 658 | fn foo() { | ||
| 659 | let SOME_VALUE = 10; | ||
| 660 | // ^^^^^^^^^^ Variable `SOME_VALUE` should have snake_case name, e.g. `some_value` | ||
| 661 | let AnotherValue = 20; | ||
| 662 | // ^^^^^^^^^^^^ Variable `AnotherValue` should have snake_case name, e.g. `another_value` | ||
| 663 | } | ||
| 664 | "#, | ||
| 665 | ); | ||
| 666 | } | ||
| 667 | |||
| 668 | #[test] | ||
| 669 | fn incorrect_struct_names() { | ||
| 670 | check_diagnostics( | ||
| 671 | r#" | ||
| 672 | struct non_camel_case_name {} | ||
| 673 | // ^^^^^^^^^^^^^^^^^^^ Structure `non_camel_case_name` should have CamelCase name, e.g. `NonCamelCaseName` | ||
| 674 | |||
| 675 | struct SCREAMING_CASE {} | ||
| 676 | // ^^^^^^^^^^^^^^ Structure `SCREAMING_CASE` should have CamelCase name, e.g. `ScreamingCase` | ||
| 677 | "#, | ||
| 678 | ); | ||
| 679 | } | ||
| 680 | |||
| 681 | #[test] | ||
| 682 | fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() { | ||
| 683 | check_diagnostics( | ||
| 684 | r#" | ||
| 685 | struct AABB {} | ||
| 686 | "#, | ||
| 687 | ); | ||
| 688 | } | ||
| 689 | |||
| 690 | #[test] | ||
| 691 | fn incorrect_struct_field() { | ||
| 692 | check_diagnostics( | ||
| 693 | r#" | ||
| 694 | struct SomeStruct { SomeField: u8 } | ||
| 695 | // ^^^^^^^^^ Field `SomeField` should have snake_case name, e.g. `some_field` | ||
| 696 | "#, | ||
| 697 | ); | ||
| 698 | } | ||
| 699 | |||
| 700 | #[test] | ||
| 701 | fn incorrect_enum_names() { | ||
| 702 | check_diagnostics( | ||
| 703 | r#" | ||
| 704 | enum some_enum { Val(u8) } | ||
| 705 | // ^^^^^^^^^ Enum `some_enum` should have CamelCase name, e.g. `SomeEnum` | ||
| 706 | |||
| 707 | enum SOME_ENUM | ||
| 708 | // ^^^^^^^^^ Enum `SOME_ENUM` should have CamelCase name, e.g. `SomeEnum` | ||
| 709 | "#, | ||
| 710 | ); | ||
| 711 | } | ||
| 712 | |||
| 713 | #[test] | ||
| 714 | fn no_diagnostic_for_camel_cased_acronyms_in_enum_name() { | ||
| 715 | check_diagnostics( | ||
| 716 | r#" | ||
| 717 | enum AABB {} | ||
| 718 | "#, | ||
| 719 | ); | ||
| 720 | } | ||
| 721 | |||
| 722 | #[test] | ||
| 723 | fn incorrect_enum_variant_name() { | ||
| 724 | check_diagnostics( | ||
| 725 | r#" | ||
| 726 | enum SomeEnum { SOME_VARIANT(u8) } | ||
| 727 | // ^^^^^^^^^^^^ Variant `SOME_VARIANT` should have CamelCase name, e.g. `SomeVariant` | ||
| 728 | "#, | ||
| 729 | ); | ||
| 730 | } | ||
| 731 | |||
| 732 | #[test] | ||
| 733 | fn incorrect_const_name() { | ||
| 734 | check_diagnostics( | ||
| 735 | r#" | ||
| 736 | const some_weird_const: u8 = 10; | ||
| 737 | // ^^^^^^^^^^^^^^^^ Constant `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST` | ||
| 738 | |||
| 739 | fn func() { | ||
| 740 | const someConstInFunc: &str = "hi there"; | ||
| 741 | // ^^^^^^^^^^^^^^^ Constant `someConstInFunc` should have UPPER_SNAKE_CASE name, e.g. `SOME_CONST_IN_FUNC` | ||
| 742 | |||
| 743 | } | ||
| 744 | "#, | ||
| 745 | ); | ||
| 746 | } | ||
| 747 | |||
| 748 | #[test] | ||
| 749 | fn incorrect_static_name() { | ||
| 750 | check_diagnostics( | ||
| 751 | r#" | ||
| 752 | static some_weird_const: u8 = 10; | ||
| 753 | // ^^^^^^^^^^^^^^^^ Static variable `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST` | ||
| 754 | |||
| 755 | fn func() { | ||
| 756 | static someConstInFunc: &str = "hi there"; | ||
| 757 | // ^^^^^^^^^^^^^^^ Static variable `someConstInFunc` should have UPPER_SNAKE_CASE name, e.g. `SOME_CONST_IN_FUNC` | ||
| 758 | } | ||
| 759 | "#, | ||
| 760 | ); | ||
| 761 | } | ||
| 762 | |||
| 763 | #[test] | ||
| 764 | fn fn_inside_impl_struct() { | ||
| 765 | check_diagnostics( | ||
| 766 | r#" | ||
| 767 | struct someStruct; | ||
| 768 | // ^^^^^^^^^^ Structure `someStruct` should have CamelCase name, e.g. `SomeStruct` | ||
| 769 | |||
| 770 | impl someStruct { | ||
| 771 | fn SomeFunc(&self) { | ||
| 772 | // ^^^^^^^^ Function `SomeFunc` should have snake_case name, e.g. `some_func` | ||
| 773 | static someConstInFunc: &str = "hi there"; | ||
| 774 | // ^^^^^^^^^^^^^^^ Static variable `someConstInFunc` should have UPPER_SNAKE_CASE name, e.g. `SOME_CONST_IN_FUNC` | ||
| 775 | let WHY_VAR_IS_CAPS = 10; | ||
| 776 | // ^^^^^^^^^^^^^^^ Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps` | ||
| 777 | } | ||
| 778 | } | ||
| 779 | "#, | ||
| 780 | ); | ||
| 781 | } | ||
| 782 | |||
| 783 | #[test] | ||
| 784 | fn no_diagnostic_for_enum_varinats() { | ||
| 785 | check_diagnostics( | ||
| 786 | r#" | ||
| 787 | enum Option { Some, None } | ||
| 788 | |||
| 789 | fn main() { | ||
| 790 | match Option::None { | ||
| 791 | None => (), | ||
| 792 | Some => (), | ||
| 793 | } | ||
| 794 | } | ||
| 795 | "#, | ||
| 796 | ); | ||
| 797 | } | ||
| 798 | |||
| 799 | #[test] | ||
| 800 | fn non_let_bind() { | ||
| 801 | check_diagnostics( | ||
| 802 | r#" | ||
| 803 | enum Option { Some, None } | ||
| 804 | |||
| 805 | fn main() { | ||
| 806 | match Option::None { | ||
| 807 | SOME_VAR @ None => (), | ||
| 808 | // ^^^^^^^^ Variable `SOME_VAR` should have snake_case name, e.g. `some_var` | ||
| 809 | Some => (), | ||
| 810 | } | ||
| 811 | } | ||
| 812 | "#, | ||
| 813 | ); | ||
| 814 | } | ||
| 815 | |||
| 816 | #[test] | ||
| 817 | fn allow_attributes() { | ||
| 818 | check_diagnostics( | ||
| 819 | r#" | ||
| 820 | #[allow(non_snake_case)] | ||
| 821 | fn NonSnakeCaseName(SOME_VAR: u8) -> u8{ | ||
| 822 | // cov_flags generated output from elsewhere in this file | ||
| 823 | extern "C" { | ||
| 824 | #[no_mangle] | ||
| 825 | static lower_case: u8; | ||
| 826 | } | ||
| 827 | |||
| 828 | let OtherVar = SOME_VAR + 1; | ||
| 829 | OtherVar | ||
| 830 | } | ||
| 831 | |||
| 832 | #[allow(nonstandard_style)] | ||
| 833 | mod CheckNonstandardStyle { | ||
| 834 | fn HiImABadFnName() {} | ||
| 835 | } | ||
| 836 | |||
| 837 | #[allow(bad_style)] | ||
| 838 | mod CheckBadStyle { | ||
| 839 | fn HiImABadFnName() {} | ||
| 840 | } | ||
| 841 | |||
| 842 | mod F { | ||
| 843 | #![allow(non_snake_case)] | ||
| 844 | fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {} | ||
| 845 | } | ||
| 846 | |||
| 847 | #[allow(non_snake_case, non_camel_case_types)] | ||
| 848 | pub struct some_type { | ||
| 849 | SOME_FIELD: u8, | ||
| 850 | SomeField: u16, | ||
| 851 | } | ||
| 852 | |||
| 853 | #[allow(non_upper_case_globals)] | ||
| 854 | pub const some_const: u8 = 10; | ||
| 855 | |||
| 856 | #[allow(non_upper_case_globals)] | ||
| 857 | pub static SomeStatic: u8 = 10; | ||
| 858 | "#, | ||
| 859 | ); | ||
| 860 | } | ||
| 861 | |||
| 862 | #[test] | ||
| 863 | fn allow_attributes_crate_attr() { | ||
| 864 | check_diagnostics( | ||
| 865 | r#" | ||
| 866 | #![allow(non_snake_case)] | ||
| 867 | |||
| 868 | mod F { | ||
| 869 | fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {} | ||
| 870 | } | ||
| 871 | "#, | ||
| 872 | ); | ||
| 873 | } | ||
| 874 | |||
| 875 | #[test] | ||
| 876 | #[ignore] | ||
| 877 | fn bug_trait_inside_fn() { | ||
| 878 | // FIXME: | ||
| 879 | // This is broken, and in fact, should not even be looked at by this | ||
| 880 | // lint in the first place. There's weird stuff going on in the | ||
| 881 | // collection phase. | ||
| 882 | // It's currently being brought in by: | ||
| 883 | // * validate_func on `a` recursing into modules | ||
| 884 | // * then it finds the trait and then the function while iterating | ||
| 885 | // through modules | ||
| 886 | // * then validate_func is called on Dirty | ||
| 887 | // * ... which then proceeds to look at some unknown module taking no | ||
| 888 | // attrs from either the impl or the fn a, and then finally to the root | ||
| 889 | // module | ||
| 890 | // | ||
| 891 | // It should find the attribute on the trait, but it *doesn't even see | ||
| 892 | // the trait* as far as I can tell. | ||
| 893 | |||
| 894 | check_diagnostics( | ||
| 895 | r#" | ||
| 896 | trait T { fn a(); } | ||
| 897 | struct U {} | ||
| 898 | impl T for U { | ||
| 899 | fn a() { | ||
| 900 | // this comes out of bitflags, mostly | ||
| 901 | #[allow(non_snake_case)] | ||
| 902 | trait __BitFlags { | ||
| 903 | const HiImAlsoBad: u8 = 2; | ||
| 904 | #[inline] | ||
| 905 | fn Dirty(&self) -> bool { | ||
| 906 | false | ||
| 907 | } | ||
| 908 | } | ||
| 909 | |||
| 910 | } | ||
| 911 | } | ||
| 912 | "#, | ||
| 913 | ); | ||
| 914 | } | ||
| 915 | |||
| 916 | #[test] | ||
| 917 | #[ignore] | ||
| 918 | fn bug_traits_arent_checked() { | ||
| 919 | // FIXME: Traits and functions in traits aren't currently checked by | ||
| 920 | // r-a, even though rustc will complain about them. | ||
| 921 | check_diagnostics( | ||
| 922 | r#" | ||
| 923 | trait BAD_TRAIT { | ||
| 924 | // ^^^^^^^^^ Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait` | ||
| 925 | fn BAD_FUNCTION(); | ||
| 926 | // ^^^^^^^^^^^^ Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function` | ||
| 927 | fn BadFunction(); | ||
| 928 | // ^^^^^^^^^^^^ Function `BadFunction` should have snake_case name, e.g. `bad_function` | ||
| 929 | } | ||
| 930 | "#, | ||
| 931 | ); | ||
| 932 | } | ||
| 933 | |||
| 934 | #[test] | ||
| 935 | fn ignores_extern_items() { | ||
| 936 | cov_mark::check!(extern_func_incorrect_case_ignored); | ||
| 937 | cov_mark::check!(extern_static_incorrect_case_ignored); | ||
| 938 | check_diagnostics( | ||
| 939 | r#" | ||
| 940 | extern { | ||
| 941 | fn NonSnakeCaseName(SOME_VAR: u8) -> u8; | ||
| 942 | pub static SomeStatic: u8 = 10; | ||
| 943 | } | ||
| 944 | "#, | ||
| 945 | ); | ||
| 946 | } | ||
| 947 | |||
| 948 | #[test] | ||
| 949 | fn infinite_loop_inner_items() { | ||
| 950 | check_diagnostics( | ||
| 951 | r#" | ||
| 952 | fn qualify() { | ||
| 953 | mod foo { | ||
| 954 | use super::*; | ||
| 955 | } | ||
| 956 | } | ||
| 957 | "#, | ||
| 958 | ) | ||
| 959 | } | ||
| 960 | |||
| 961 | #[test] // Issue #8809. | ||
| 962 | fn parenthesized_parameter() { | ||
| 963 | check_diagnostics(r#"fn f((O): _) {}"#) | ||
| 964 | } | ||
| 965 | } | ||
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 0c6b19653..128cae830 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
| @@ -21,7 +21,6 @@ mod utils; | |||
| 21 | mod walk; | 21 | mod walk; |
| 22 | pub mod db; | 22 | pub mod db; |
| 23 | pub mod diagnostics; | 23 | pub mod diagnostics; |
| 24 | pub mod diagnostics_sink; | ||
| 25 | pub mod display; | 24 | pub mod display; |
| 26 | pub mod method_resolution; | 25 | pub mod method_resolution; |
| 27 | pub mod primitive; | 26 | pub mod primitive; |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index dffb6fdc8..e34341631 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
| @@ -1338,6 +1338,35 @@ fn main() { | |||
| 1338 | "#, | 1338 | "#, |
| 1339 | ); | 1339 | ); |
| 1340 | } | 1340 | } |
| 1341 | |||
| 1342 | #[test] | ||
| 1343 | fn import_extern_crate_clash_with_inner_item() { | ||
| 1344 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. | ||
| 1345 | |||
| 1346 | check_diagnostics( | ||
| 1347 | r#" | ||
| 1348 | //- /lib.rs crate:lib deps:jwt | ||
| 1349 | mod permissions; | ||
| 1350 | |||
| 1351 | use permissions::jwt; | ||
| 1352 | |||
| 1353 | fn f() { | ||
| 1354 | fn inner() {} | ||
| 1355 | jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | //- /permissions.rs | ||
| 1359 | pub mod jwt { | ||
| 1360 | pub struct Claims {} | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | //- /jwt/lib.rs crate:jwt | ||
| 1364 | pub struct Claims { | ||
| 1365 | field: u8, | ||
| 1366 | } | ||
| 1367 | "#, | ||
| 1368 | ); | ||
| 1369 | } | ||
| 1341 | } | 1370 | } |
| 1342 | 1371 | ||
| 1343 | #[cfg(test)] | 1372 | #[cfg(test)] |
| @@ -2245,3 +2274,328 @@ fn main() { | |||
| 2245 | } | 2274 | } |
| 2246 | } | 2275 | } |
| 2247 | } | 2276 | } |
| 2277 | |||
| 2278 | #[cfg(test)] | ||
| 2279 | mod decl_check_tests { | ||
| 2280 | use crate::diagnostics::tests::check_diagnostics; | ||
| 2281 | |||
| 2282 | #[test] | ||
| 2283 | fn incorrect_function_name() { | ||
| 2284 | check_diagnostics( | ||
| 2285 | r#" | ||
| 2286 | fn NonSnakeCaseName() {} | ||
| 2287 | // ^^^^^^^^^^^^^^^^ Function `NonSnakeCaseName` should have snake_case name, e.g. `non_snake_case_name` | ||
| 2288 | "#, | ||
| 2289 | ); | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | #[test] | ||
| 2293 | fn incorrect_function_params() { | ||
| 2294 | check_diagnostics( | ||
| 2295 | r#" | ||
| 2296 | fn foo(SomeParam: u8) {} | ||
| 2297 | // ^^^^^^^^^ Parameter `SomeParam` should have snake_case name, e.g. `some_param` | ||
| 2298 | |||
| 2299 | fn foo2(ok_param: &str, CAPS_PARAM: u8) {} | ||
| 2300 | // ^^^^^^^^^^ Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param` | ||
| 2301 | "#, | ||
| 2302 | ); | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | #[test] | ||
| 2306 | fn incorrect_variable_names() { | ||
| 2307 | check_diagnostics( | ||
| 2308 | r#" | ||
| 2309 | fn foo() { | ||
| 2310 | let SOME_VALUE = 10; | ||
| 2311 | // ^^^^^^^^^^ Variable `SOME_VALUE` should have snake_case name, e.g. `some_value` | ||
| 2312 | let AnotherValue = 20; | ||
| 2313 | // ^^^^^^^^^^^^ Variable `AnotherValue` should have snake_case name, e.g. `another_value` | ||
| 2314 | } | ||
| 2315 | "#, | ||
| 2316 | ); | ||
| 2317 | } | ||
| 2318 | |||
| 2319 | #[test] | ||
| 2320 | fn incorrect_struct_names() { | ||
| 2321 | check_diagnostics( | ||
| 2322 | r#" | ||
| 2323 | struct non_camel_case_name {} | ||
| 2324 | // ^^^^^^^^^^^^^^^^^^^ Structure `non_camel_case_name` should have CamelCase name, e.g. `NonCamelCaseName` | ||
| 2325 | |||
| 2326 | struct SCREAMING_CASE {} | ||
| 2327 | // ^^^^^^^^^^^^^^ Structure `SCREAMING_CASE` should have CamelCase name, e.g. `ScreamingCase` | ||
| 2328 | "#, | ||
| 2329 | ); | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | #[test] | ||
| 2333 | fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() { | ||
| 2334 | check_diagnostics( | ||
| 2335 | r#" | ||
| 2336 | struct AABB {} | ||
| 2337 | "#, | ||
| 2338 | ); | ||
| 2339 | } | ||
| 2340 | |||
| 2341 | #[test] | ||
| 2342 | fn incorrect_struct_field() { | ||
| 2343 | check_diagnostics( | ||
| 2344 | r#" | ||
| 2345 | struct SomeStruct { SomeField: u8 } | ||
| 2346 | // ^^^^^^^^^ Field `SomeField` should have snake_case name, e.g. `some_field` | ||
| 2347 | "#, | ||
| 2348 | ); | ||
| 2349 | } | ||
| 2350 | |||
| 2351 | #[test] | ||
| 2352 | fn incorrect_enum_names() { | ||
| 2353 | check_diagnostics( | ||
| 2354 | r#" | ||
| 2355 | enum some_enum { Val(u8) } | ||
| 2356 | // ^^^^^^^^^ Enum `some_enum` should have CamelCase name, e.g. `SomeEnum` | ||
| 2357 | |||
| 2358 | enum SOME_ENUM {} | ||
| 2359 | // ^^^^^^^^^ Enum `SOME_ENUM` should have CamelCase name, e.g. `SomeEnum` | ||
| 2360 | "#, | ||
| 2361 | ); | ||
| 2362 | } | ||
| 2363 | |||
| 2364 | #[test] | ||
| 2365 | fn no_diagnostic_for_camel_cased_acronyms_in_enum_name() { | ||
| 2366 | check_diagnostics( | ||
| 2367 | r#" | ||
| 2368 | enum AABB {} | ||
| 2369 | "#, | ||
| 2370 | ); | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | #[test] | ||
| 2374 | fn incorrect_enum_variant_name() { | ||
| 2375 | check_diagnostics( | ||
| 2376 | r#" | ||
| 2377 | enum SomeEnum { SOME_VARIANT(u8) } | ||
| 2378 | // ^^^^^^^^^^^^ Variant `SOME_VARIANT` should have CamelCase name, e.g. `SomeVariant` | ||
| 2379 | "#, | ||
| 2380 | ); | ||
| 2381 | } | ||
| 2382 | |||
| 2383 | #[test] | ||
| 2384 | fn incorrect_const_name() { | ||
| 2385 | check_diagnostics( | ||
| 2386 | r#" | ||
| 2387 | const some_weird_const: u8 = 10; | ||
| 2388 | // ^^^^^^^^^^^^^^^^ Constant `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST` | ||
| 2389 | "#, | ||
| 2390 | ); | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | #[test] | ||
| 2394 | fn incorrect_static_name() { | ||
| 2395 | check_diagnostics( | ||
| 2396 | r#" | ||
| 2397 | static some_weird_const: u8 = 10; | ||
| 2398 | // ^^^^^^^^^^^^^^^^ Static variable `some_weird_const` should have UPPER_SNAKE_CASE name, e.g. `SOME_WEIRD_CONST` | ||
| 2399 | "#, | ||
| 2400 | ); | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | #[test] | ||
| 2404 | fn fn_inside_impl_struct() { | ||
| 2405 | check_diagnostics( | ||
| 2406 | r#" | ||
| 2407 | struct someStruct; | ||
| 2408 | // ^^^^^^^^^^ Structure `someStruct` should have CamelCase name, e.g. `SomeStruct` | ||
| 2409 | |||
| 2410 | impl someStruct { | ||
| 2411 | fn SomeFunc(&self) { | ||
| 2412 | // ^^^^^^^^ Function `SomeFunc` should have snake_case name, e.g. `some_func` | ||
| 2413 | let WHY_VAR_IS_CAPS = 10; | ||
| 2414 | // ^^^^^^^^^^^^^^^ Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps` | ||
| 2415 | } | ||
| 2416 | } | ||
| 2417 | "#, | ||
| 2418 | ); | ||
| 2419 | } | ||
| 2420 | |||
| 2421 | #[test] | ||
| 2422 | fn no_diagnostic_for_enum_varinats() { | ||
| 2423 | check_diagnostics( | ||
| 2424 | r#" | ||
| 2425 | enum Option { Some, None } | ||
| 2426 | |||
| 2427 | fn main() { | ||
| 2428 | match Option::None { | ||
| 2429 | None => (), | ||
| 2430 | Some => (), | ||
| 2431 | } | ||
| 2432 | } | ||
| 2433 | "#, | ||
| 2434 | ); | ||
| 2435 | } | ||
| 2436 | |||
| 2437 | #[test] | ||
| 2438 | fn non_let_bind() { | ||
| 2439 | check_diagnostics( | ||
| 2440 | r#" | ||
| 2441 | enum Option { Some, None } | ||
| 2442 | |||
| 2443 | fn main() { | ||
| 2444 | match Option::None { | ||
| 2445 | SOME_VAR @ None => (), | ||
| 2446 | // ^^^^^^^^ Variable `SOME_VAR` should have snake_case name, e.g. `some_var` | ||
| 2447 | Some => (), | ||
| 2448 | } | ||
| 2449 | } | ||
| 2450 | "#, | ||
| 2451 | ); | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | #[test] | ||
| 2455 | fn allow_attributes() { | ||
| 2456 | check_diagnostics( | ||
| 2457 | r#" | ||
| 2458 | #[allow(non_snake_case)] | ||
| 2459 | fn NonSnakeCaseName(SOME_VAR: u8) -> u8{ | ||
| 2460 | // cov_flags generated output from elsewhere in this file | ||
| 2461 | extern "C" { | ||
| 2462 | #[no_mangle] | ||
| 2463 | static lower_case: u8; | ||
| 2464 | } | ||
| 2465 | |||
| 2466 | let OtherVar = SOME_VAR + 1; | ||
| 2467 | OtherVar | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | #[allow(nonstandard_style)] | ||
| 2471 | mod CheckNonstandardStyle { | ||
| 2472 | fn HiImABadFnName() {} | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | #[allow(bad_style)] | ||
| 2476 | mod CheckBadStyle { | ||
| 2477 | fn HiImABadFnName() {} | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | mod F { | ||
| 2481 | #![allow(non_snake_case)] | ||
| 2482 | fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {} | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | #[allow(non_snake_case, non_camel_case_types)] | ||
| 2486 | pub struct some_type { | ||
| 2487 | SOME_FIELD: u8, | ||
| 2488 | SomeField: u16, | ||
| 2489 | } | ||
| 2490 | |||
| 2491 | #[allow(non_upper_case_globals)] | ||
| 2492 | pub const some_const: u8 = 10; | ||
| 2493 | |||
| 2494 | #[allow(non_upper_case_globals)] | ||
| 2495 | pub static SomeStatic: u8 = 10; | ||
| 2496 | "#, | ||
| 2497 | ); | ||
| 2498 | } | ||
| 2499 | |||
| 2500 | #[test] | ||
| 2501 | fn allow_attributes_crate_attr() { | ||
| 2502 | check_diagnostics( | ||
| 2503 | r#" | ||
| 2504 | #![allow(non_snake_case)] | ||
| 2505 | |||
| 2506 | mod F { | ||
| 2507 | fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {} | ||
| 2508 | } | ||
| 2509 | "#, | ||
| 2510 | ); | ||
| 2511 | } | ||
| 2512 | |||
| 2513 | #[test] | ||
| 2514 | #[ignore] | ||
| 2515 | fn bug_trait_inside_fn() { | ||
| 2516 | // FIXME: | ||
| 2517 | // This is broken, and in fact, should not even be looked at by this | ||
| 2518 | // lint in the first place. There's weird stuff going on in the | ||
| 2519 | // collection phase. | ||
| 2520 | // It's currently being brought in by: | ||
| 2521 | // * validate_func on `a` recursing into modules | ||
| 2522 | // * then it finds the trait and then the function while iterating | ||
| 2523 | // through modules | ||
| 2524 | // * then validate_func is called on Dirty | ||
| 2525 | // * ... which then proceeds to look at some unknown module taking no | ||
| 2526 | // attrs from either the impl or the fn a, and then finally to the root | ||
| 2527 | // module | ||
| 2528 | // | ||
| 2529 | // It should find the attribute on the trait, but it *doesn't even see | ||
| 2530 | // the trait* as far as I can tell. | ||
| 2531 | |||
| 2532 | check_diagnostics( | ||
| 2533 | r#" | ||
| 2534 | trait T { fn a(); } | ||
| 2535 | struct U {} | ||
| 2536 | impl T for U { | ||
| 2537 | fn a() { | ||
| 2538 | // this comes out of bitflags, mostly | ||
| 2539 | #[allow(non_snake_case)] | ||
| 2540 | trait __BitFlags { | ||
| 2541 | const HiImAlsoBad: u8 = 2; | ||
| 2542 | #[inline] | ||
| 2543 | fn Dirty(&self) -> bool { | ||
| 2544 | false | ||
| 2545 | } | ||
| 2546 | } | ||
| 2547 | |||
| 2548 | } | ||
| 2549 | } | ||
| 2550 | "#, | ||
| 2551 | ); | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | #[test] | ||
| 2555 | #[ignore] | ||
| 2556 | fn bug_traits_arent_checked() { | ||
| 2557 | // FIXME: Traits and functions in traits aren't currently checked by | ||
| 2558 | // r-a, even though rustc will complain about them. | ||
| 2559 | check_diagnostics( | ||
| 2560 | r#" | ||
| 2561 | trait BAD_TRAIT { | ||
| 2562 | // ^^^^^^^^^ Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait` | ||
| 2563 | fn BAD_FUNCTION(); | ||
| 2564 | // ^^^^^^^^^^^^ Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function` | ||
| 2565 | fn BadFunction(); | ||
| 2566 | // ^^^^^^^^^^^^ Function `BadFunction` should have snake_case name, e.g. `bad_function` | ||
| 2567 | } | ||
| 2568 | "#, | ||
| 2569 | ); | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | #[test] | ||
| 2573 | fn ignores_extern_items() { | ||
| 2574 | check_diagnostics( | ||
| 2575 | r#" | ||
| 2576 | extern { | ||
| 2577 | fn NonSnakeCaseName(SOME_VAR: u8) -> u8; | ||
| 2578 | pub static SomeStatic: u8 = 10; | ||
| 2579 | } | ||
| 2580 | "#, | ||
| 2581 | ); | ||
| 2582 | } | ||
| 2583 | |||
| 2584 | #[test] | ||
| 2585 | fn infinite_loop_inner_items() { | ||
| 2586 | check_diagnostics( | ||
| 2587 | r#" | ||
| 2588 | fn qualify() { | ||
| 2589 | mod foo { | ||
| 2590 | use super::*; | ||
| 2591 | } | ||
| 2592 | } | ||
| 2593 | "#, | ||
| 2594 | ) | ||
| 2595 | } | ||
| 2596 | |||
| 2597 | #[test] // Issue #8809. | ||
| 2598 | fn parenthesized_parameter() { | ||
| 2599 | check_diagnostics(r#"fn f((O): _) {}"#) | ||
| 2600 | } | ||
| 2601 | } | ||
