aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-06-13 10:33:08 +0100
committerAleksey Kladov <[email protected]>2021-06-13 11:13:26 +0100
commit546be18e3a91e4844b0dacc76c9f055397b6d89e (patch)
tree020b9667f0f723b06ee7fb6948efaa9e6b135f68
parent0eafc88079fb5ddb1931e59860a4e064743e113a (diff)
internal: check that coverage marks are always paired
-rw-r--r--crates/hir_def/src/body/tests/block.rs10
-rw-r--r--crates/ide_completion/src/render.rs1
-rw-r--r--xtask/src/tidy.rs49
3 files changed, 54 insertions, 6 deletions
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs
index bc3d0f138..15c10d053 100644
--- a/crates/hir_def/src/body/tests/block.rs
+++ b/crates/hir_def/src/body/tests/block.rs
@@ -163,14 +163,14 @@ fn legacy_macro_items() {
163 // correctly. 163 // correctly.
164 check_at( 164 check_at(
165 r#" 165 r#"
166macro_rules! hit { 166macro_rules! mark {
167 () => { 167 () => {
168 struct Hit {} 168 struct Hit {}
169 } 169 }
170} 170}
171 171
172fn f() { 172fn f() {
173 hit!(); 173 mark!();
174 $0 174 $0
175} 175}
176"#, 176"#,
@@ -193,20 +193,20 @@ use core::cov_mark;
193 193
194fn f() { 194fn f() {
195 fn nested() { 195 fn nested() {
196 cov_mark::hit!(Hit); 196 cov_mark::mark!(Hit);
197 $0 197 $0
198 } 198 }
199} 199}
200//- /core.rs crate:core 200//- /core.rs crate:core
201pub mod cov_mark { 201pub mod cov_mark {
202 #[macro_export] 202 #[macro_export]
203 macro_rules! _hit { 203 macro_rules! _mark {
204 ($name:ident) => { 204 ($name:ident) => {
205 struct $name {} 205 struct $name {}
206 } 206 }
207 } 207 }
208 208
209 pub use crate::_hit as hit; 209 pub use crate::_mark as mark;
210} 210}
211"#, 211"#,
212 expect![[r#" 212 expect![[r#"
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index a55081631..d8ca18c73 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -1007,6 +1007,7 @@ fn go(world: &WorldSnapshot) { go(w$0) }
1007 1007
1008 #[test] 1008 #[test]
1009 fn too_many_arguments() { 1009 fn too_many_arguments() {
1010 cov_mark::check!(too_many_arguments);
1010 check_relevance( 1011 check_relevance(
1011 r#" 1012 r#"
1012struct Foo; 1013struct Foo;
diff --git a/xtask/src/tidy.rs b/xtask/src/tidy.rs
index 9447d463d..e6fa5868d 100644
--- a/xtask/src/tidy.rs
+++ b/xtask/src/tidy.rs
@@ -1,4 +1,7 @@
1use std::path::{Path, PathBuf}; 1use std::{
2 collections::HashSet,
3 path::{Path, PathBuf},
4};
2 5
3use xshell::{cmd, pushd, pushenv, read_file}; 6use xshell::{cmd, pushd, pushenv, read_file};
4 7
@@ -81,6 +84,7 @@ Please adjust docs/dev/lsp-extensions.md.
81#[test] 84#[test]
82fn rust_files_are_tidy() { 85fn rust_files_are_tidy() {
83 let mut tidy_docs = TidyDocs::default(); 86 let mut tidy_docs = TidyDocs::default();
87 let mut tidy_marks = TidyMarks::default();
84 for path in rust_files() { 88 for path in rust_files() {
85 let text = read_file(&path).unwrap(); 89 let text = read_file(&path).unwrap();
86 check_todo(&path, &text); 90 check_todo(&path, &text);
@@ -88,8 +92,10 @@ fn rust_files_are_tidy() {
88 check_trailing_ws(&path, &text); 92 check_trailing_ws(&path, &text);
89 deny_clippy(&path, &text); 93 deny_clippy(&path, &text);
90 tidy_docs.visit(&path, &text); 94 tidy_docs.visit(&path, &text);
95 tidy_marks.visit(&path, &text);
91 } 96 }
92 tidy_docs.finish(); 97 tidy_docs.finish();
98 tidy_marks.finish();
93} 99}
94 100
95#[test] 101#[test]
@@ -408,6 +414,39 @@ fn is_exclude_dir(p: &Path, dirs_to_exclude: &[&str]) -> bool {
408 .any(|it| dirs_to_exclude.contains(&it)) 414 .any(|it| dirs_to_exclude.contains(&it))
409} 415}
410 416
417#[derive(Default)]
418struct TidyMarks {
419 hits: HashSet<String>,
420 checks: HashSet<String>,
421}
422
423impl TidyMarks {
424 fn visit(&mut self, _path: &Path, text: &str) {
425 for line in text.lines() {
426 if let Some(mark) = find_mark(line, "hit") {
427 self.hits.insert(mark.to_string());
428 }
429 if let Some(mark) = find_mark(line, "check") {
430 self.checks.insert(mark.to_string());
431 }
432 if let Some(mark) = find_mark(line, "check_count") {
433 self.checks.insert(mark.to_string());
434 }
435 }
436 }
437
438 fn finish(self) {
439 assert!(!self.hits.is_empty());
440
441 let diff: Vec<_> =
442 self.hits.symmetric_difference(&self.checks).map(|it| it.as_str()).collect();
443
444 if !diff.is_empty() {
445 panic!("unpaired marks: {:?}", diff)
446 }
447 }
448}
449
411#[allow(deprecated)] 450#[allow(deprecated)]
412fn stable_hash(text: &str) -> u64 { 451fn stable_hash(text: &str) -> u64 {
413 use std::hash::{Hash, Hasher, SipHasher}; 452 use std::hash::{Hash, Hasher, SipHasher};
@@ -417,3 +456,11 @@ fn stable_hash(text: &str) -> u64 {
417 text.hash(&mut hasher); 456 text.hash(&mut hasher);
418 hasher.finish() 457 hasher.finish()
419} 458}
459
460fn find_mark<'a>(text: &'a str, mark: &'static str) -> Option<&'a str> {
461 let idx = text.find(mark)?;
462 let text = text[idx + mark.len()..].strip_prefix("!(")?;
463 let idx = text.find(|c: char| !(c.is_alphanumeric() || c == '_'))?;
464 let text = &text[..idx];
465 Some(text)
466}