diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-04 18:45:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-04 18:45:37 +0100 |
commit | 98395f29a417b37a5969594f0cac5ae23585da85 (patch) | |
tree | 3a13913003723f3da843dae8580287b9d33c68eb /xtask | |
parent | 92d91050c4aa48732e7af3bf979aa7ed5aed924d (diff) | |
parent | ae1c63fcdd0caf34f41fba62b04e3d868a589f1d (diff) |
Merge #9138
9138: feat: Implement hover for lints r=Veykril a=Veykril
fixes https://github.com/rust-analyzer/rust-analyzer/issues/8857, fixes https://github.com/rust-analyzer/rust-analyzer/issues/3941
![URXBanNxYe](https://user-images.githubusercontent.com/3757771/120830905-4bd8da80-c55f-11eb-9f55-ff5a321726fa.gif)
We also generate the default lints(and lint groups 🎉) instead now by invoking `rustc -W help` and parsing the output from that.
Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/codegen/gen_lint_completions.rs | 82 | ||||
-rw-r--r-- | xtask/src/tidy.rs | 8 |
2 files changed, 73 insertions, 17 deletions
diff --git a/xtask/src/codegen/gen_lint_completions.rs b/xtask/src/codegen/gen_lint_completions.rs index 24dbc6a39..a28b6cb59 100644 --- a/xtask/src/codegen/gen_lint_completions.rs +++ b/xtask/src/codegen/gen_lint_completions.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | //! Generates descriptors structure for unstable feature from Unstable Book | 1 | //! Generates descriptors structure for unstable feature from Unstable Book |
2 | use std::borrow::Cow; | ||
2 | use std::fmt::Write; | 3 | use std::fmt::Write; |
3 | use std::path::{Path, PathBuf}; | 4 | use std::path::{Path, PathBuf}; |
4 | 5 | ||
@@ -12,25 +13,75 @@ pub(crate) fn generate_lint_completions() -> Result<()> { | |||
12 | cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?; | 13 | cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?; |
13 | } | 14 | } |
14 | 15 | ||
15 | let mut contents = String::from("use crate::completions::attribute::LintCompletion;\n\n"); | 16 | let mut contents = String::from( |
16 | generate_descriptor(&mut contents, "./target/rust/src/doc/unstable-book/src".into())?; | 17 | r#"pub struct Lint { |
18 | pub label: &'static str, | ||
19 | pub description: &'static str, | ||
20 | } | ||
21 | |||
22 | "#, | ||
23 | ); | ||
24 | generate_lint_descriptor(&mut contents)?; | ||
25 | contents.push('\n'); | ||
26 | |||
27 | generate_feature_descriptor(&mut contents, "./target/rust/src/doc/unstable-book/src".into())?; | ||
17 | contents.push('\n'); | 28 | contents.push('\n'); |
18 | 29 | ||
19 | cmd!("curl http://rust-lang.github.io/rust-clippy/master/lints.json --output ./target/clippy_lints.json").run()?; | 30 | cmd!("curl http://rust-lang.github.io/rust-clippy/master/lints.json --output ./target/clippy_lints.json").run()?; |
20 | generate_descriptor_clippy(&mut contents, &Path::new("./target/clippy_lints.json"))?; | 31 | generate_descriptor_clippy(&mut contents, &Path::new("./target/clippy_lints.json"))?; |
21 | let contents = reformat(&contents)?; | 32 | let contents = reformat(&contents)?; |
22 | 33 | ||
23 | let destination = | 34 | let destination = project_root().join("crates/ide_db/src/helpers/generated_lints.rs"); |
24 | project_root().join("crates/ide_completion/src/generated_lint_completions.rs"); | ||
25 | ensure_file_contents(destination.as_path(), &contents)?; | 35 | ensure_file_contents(destination.as_path(), &contents)?; |
26 | 36 | ||
27 | Ok(()) | 37 | Ok(()) |
28 | } | 38 | } |
29 | 39 | ||
30 | fn generate_descriptor(buf: &mut String, src_dir: PathBuf) -> Result<()> { | 40 | fn generate_lint_descriptor(buf: &mut String) -> Result<()> { |
31 | buf.push_str(r#"pub(super) const FEATURES: &[LintCompletion] = &["#); | 41 | let stdout = cmd!("rustc -W help").read()?; |
42 | let start_lints = | ||
43 | stdout.find("---- ------- -------").ok_or_else(|| anyhow::format_err!(""))?; | ||
44 | let start_lint_groups = | ||
45 | stdout.find("---- ---------").ok_or_else(|| anyhow::format_err!(""))?; | ||
46 | let end_lints = | ||
47 | stdout.find("Lint groups provided by rustc:").ok_or_else(|| anyhow::format_err!(""))?; | ||
48 | let end_lint_groups = stdout | ||
49 | .find("Lint tools like Clippy can provide additional lints and lint groups.") | ||
50 | .ok_or_else(|| anyhow::format_err!(""))?; | ||
51 | buf.push_str(r#"pub const DEFAULT_LINTS: &[Lint] = &["#); | ||
52 | buf.push('\n'); | ||
53 | let mut lints = stdout[start_lints..end_lints] | ||
54 | .lines() | ||
55 | .skip(1) | ||
56 | .filter(|l| !l.is_empty()) | ||
57 | .map(|line| { | ||
58 | let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); | ||
59 | let (_default_level, description) = | ||
60 | rest.trim().split_once(char::is_whitespace).unwrap(); | ||
61 | (name.trim(), Cow::Borrowed(description.trim())) | ||
62 | }) | ||
63 | .collect::<Vec<_>>(); | ||
64 | lints.extend( | ||
65 | stdout[start_lint_groups..end_lint_groups].lines().skip(1).filter(|l| !l.is_empty()).map( | ||
66 | |line| { | ||
67 | let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); | ||
68 | (name.trim(), format!("lint group for: {}", lints.trim()).into()) | ||
69 | }, | ||
70 | ), | ||
71 | ); | ||
72 | |||
73 | lints.sort_by(|(ident, _), (ident2, _)| ident.cmp(ident2)); | ||
74 | lints.into_iter().for_each(|(name, description)| { | ||
75 | push_lint_completion(buf, &name.replace("-", "_"), &description) | ||
76 | }); | ||
77 | buf.push_str("];\n"); | ||
78 | Ok(()) | ||
79 | } | ||
80 | |||
81 | fn generate_feature_descriptor(buf: &mut String, src_dir: PathBuf) -> Result<()> { | ||
82 | buf.push_str(r#"pub const FEATURES: &[Lint] = &["#); | ||
32 | buf.push('\n'); | 83 | buf.push('\n'); |
33 | ["language-features", "library-features"] | 84 | let mut vec = ["language-features", "library-features"] |
34 | .iter() | 85 | .iter() |
35 | .flat_map(|it| WalkDir::new(src_dir.join(it))) | 86 | .flat_map(|it| WalkDir::new(src_dir.join(it))) |
36 | .filter_map(|e| e.ok()) | 87 | .filter_map(|e| e.ok()) |
@@ -38,13 +89,16 @@ fn generate_descriptor(buf: &mut String, src_dir: PathBuf) -> Result<()> { | |||
38 | // Get all `.md ` files | 89 | // Get all `.md ` files |
39 | entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md" | 90 | entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md" |
40 | }) | 91 | }) |
41 | .for_each(|entry| { | 92 | .map(|entry| { |
42 | let path = entry.path(); | 93 | let path = entry.path(); |
43 | let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_"); | 94 | let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_"); |
44 | let doc = read_file(path).unwrap(); | 95 | let doc = read_file(path).unwrap(); |
45 | 96 | (feature_ident, doc) | |
46 | push_lint_completion(buf, &feature_ident, &doc); | 97 | }) |
47 | }); | 98 | .collect::<Vec<_>>(); |
99 | vec.sort_by(|(feature_ident, _), (feature_ident2, _)| feature_ident.cmp(feature_ident2)); | ||
100 | vec.into_iter() | ||
101 | .for_each(|(feature_ident, doc)| push_lint_completion(buf, &feature_ident, &doc)); | ||
48 | buf.push_str("];\n"); | 102 | buf.push_str("];\n"); |
49 | Ok(()) | 103 | Ok(()) |
50 | } | 104 | } |
@@ -85,8 +139,8 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) -> Result<()> { | |||
85 | .into(); | 139 | .into(); |
86 | } | 140 | } |
87 | } | 141 | } |
88 | 142 | clippy_lints.sort_by(|lint, lint2| lint.id.cmp(&lint2.id)); | |
89 | buf.push_str(r#"pub(super) const CLIPPY_LINTS: &[LintCompletion] = &["#); | 143 | buf.push_str(r#"pub const CLIPPY_LINTS: &[Lint] = &["#); |
90 | buf.push('\n'); | 144 | buf.push('\n'); |
91 | clippy_lints.into_iter().for_each(|clippy_lint| { | 145 | clippy_lints.into_iter().for_each(|clippy_lint| { |
92 | let lint_ident = format!("clippy::{}", clippy_lint.id); | 146 | let lint_ident = format!("clippy::{}", clippy_lint.id); |
@@ -102,7 +156,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) -> Result<()> { | |||
102 | fn push_lint_completion(buf: &mut String, label: &str, description: &str) { | 156 | fn push_lint_completion(buf: &mut String, label: &str, description: &str) { |
103 | writeln!( | 157 | writeln!( |
104 | buf, | 158 | buf, |
105 | r###" LintCompletion {{ | 159 | r###" Lint {{ |
106 | label: "{}", | 160 | label: "{}", |
107 | description: r##"{}"## | 161 | description: r##"{}"## |
108 | }},"###, | 162 | }},"###, |
diff --git a/xtask/src/tidy.rs b/xtask/src/tidy.rs index 618cf12fb..9447d463d 100644 --- a/xtask/src/tidy.rs +++ b/xtask/src/tidy.rs | |||
@@ -193,7 +193,9 @@ https://github.blog/2015-06-08-how-to-undo-almost-anything-with-git/#redo-after- | |||
193 | fn deny_clippy(path: &Path, text: &str) { | 193 | fn deny_clippy(path: &Path, text: &str) { |
194 | let ignore = &[ | 194 | let ignore = &[ |
195 | // The documentation in string literals may contain anything for its own purposes | 195 | // The documentation in string literals may contain anything for its own purposes |
196 | "ide_completion/src/generated_lint_completions.rs", | 196 | "ide_db/src/helpers/generated_lints.rs", |
197 | // The tests test clippy lint hovers | ||
198 | "ide/src/hover.rs", | ||
197 | ]; | 199 | ]; |
198 | if ignore.iter().any(|p| path.ends_with(p)) { | 200 | if ignore.iter().any(|p| path.ends_with(p)) { |
199 | return; | 201 | return; |
@@ -280,7 +282,7 @@ fn check_todo(path: &Path, text: &str) { | |||
280 | // `ast::make`. | 282 | // `ast::make`. |
281 | "ast/make.rs", | 283 | "ast/make.rs", |
282 | // The documentation in string literals may contain anything for its own purposes | 284 | // The documentation in string literals may contain anything for its own purposes |
283 | "ide_completion/src/generated_lint_completions.rs", | 285 | "ide_db/src/helpers/generated_lints.rs", |
284 | ]; | 286 | ]; |
285 | if need_todo.iter().any(|p| path.ends_with(p)) { | 287 | if need_todo.iter().any(|p| path.ends_with(p)) { |
286 | return; | 288 | return; |
@@ -310,7 +312,7 @@ fn check_dbg(path: &Path, text: &str) { | |||
310 | "ide_completion/src/completions/postfix.rs", | 312 | "ide_completion/src/completions/postfix.rs", |
311 | // The documentation in string literals may contain anything for its own purposes | 313 | // The documentation in string literals may contain anything for its own purposes |
312 | "ide_completion/src/lib.rs", | 314 | "ide_completion/src/lib.rs", |
313 | "ide_completion/src/generated_lint_completions.rs", | 315 | "ide_db/src/helpers/generated_lints.rs", |
314 | // test for doc test for remove_dbg | 316 | // test for doc test for remove_dbg |
315 | "src/tests/generated.rs", | 317 | "src/tests/generated.rs", |
316 | ]; | 318 | ]; |