diff options
-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 | } | ||