Repository: rust-analyzer/rust-analyzer
Pull request #2073 (2019-10-26 14:13:05)

warn if npm is not found


Patch:
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs
index d3ba634c40..77ecc33c9d 100644
--- a/crates/ra_assists/src/assists/add_derive.rs
+++ b/crates/ra_assists/src/assists/add_derive.rs
@@ -1,3 +1,5 @@
+//! FIXME: write short doc here
+
 use hir::db::HirDatabase;
 use ra_syntax::{
     ast::{self, AstNode, AttrsOwner},
@@ -7,22 +9,6 @@ use ra_syntax::{
 
 use crate::{Assist, AssistCtx, AssistId};
 
-// Assist: add_derive
-// Adds a new `#[derive()]` clause to a struct or enum.
-// ```
-// struct Point {
-//     x: u32,
-//     y: u32,<|>
-// }
-// ```
-// ->
-// ```
-// #[derive()]
-// struct Point {
-//     x: u32,
-//     y: u32,
-// }
-// ```
 pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
     let node_start = derive_insertion_offset(&nominal)?;
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 33b7bea7f2..8c83dc9878 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -1,3 +1,5 @@
+//! FIXME: write short doc here
+
 use hir::{db::HirDatabase, HirDisplay, Ty};
 use ra_syntax::{
     ast::{self, AstNode, LetStmt, NameOwner},
@@ -6,19 +8,7 @@ use ra_syntax::{
 
 use crate::{Assist, AssistCtx, AssistId};
 
-// Assist: add_explicit_type
-// Specify type for a let binding
-// ```
-// fn main() {
-//     let x<|> = 92;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//     let x: i32 = 92;
-// }
-// ```
+/// Add explicit type assist.
 pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let stmt = ctx.node_at_offset::<LetStmt>()?;
     let expr = stmt.initializer()?;
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs
index 40bc5c4641..94801fbc9a 100644
--- a/crates/ra_assists/src/assists/add_impl.rs
+++ b/crates/ra_assists/src/assists/add_impl.rs
@@ -1,3 +1,5 @@
+//! FIXME: write short doc here
+
 use format_buf::format;
 use hir::db::HirDatabase;
 use join_to_string::join;
@@ -8,23 +10,6 @@ use ra_syntax::{
 
 use crate::{Assist, AssistCtx, AssistId};
 
-// Assist: add_impl
-// Adds a new inherent impl for a type
-// ```
-// struct Ctx<T: Clone> {
-//      data: T,<|>
-// }
-// ```
-// ->
-// ```
-// struct Ctx<T: Clone> {
-//      data: T,
-// }
-//
-// impl<T: Clone> Ctx<T> {
-//
-// }
-// ```
 pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
     let name = nominal.name()?;
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index 36fa6f9ea7..565b96fb50 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -1,3 +1,5 @@
+//! FIXME: write short doc here
+
 use hir::{db::HirDatabase, HasSource};
 use ra_syntax::{
     ast::{self, edit, make, AstNode, NameOwner},
@@ -12,32 +14,6 @@ enum AddMissingImplMembersMode {
     NoDefaultMethods,
 }
 
-// Assist: add_impl_missing_members
-// Adds scaffold for required impl members
-// ```
-// trait T {
-//     Type X;
-//     fn foo(&self);
-//     fn bar(&self) {}
-// }
-//
-// impl T for () {<|>
-//
-// }
-// ```
-// ->
-// ```
-// trait T {
-//     Type X;
-//     fn foo(&self);
-//     fn bar(&self) {}
-// }
-//
-// impl T for () {
-//     fn foo(&self) { unimplemented!() }
-//
-// }
-// ```
 pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     add_missing_impl_members_inner(
         ctx,
@@ -47,36 +23,6 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
     )
 }
 
-// Assist: add_impl_default_members
-// Adds scaffold for overriding default impl members
-// ```
-// trait T {
-//     Type X;
-//     fn foo(&self);
-//     fn bar(&self) {}
-// }
-//
-// impl T for () {
-//     Type X = ();
-//     fn foo(&self) {}<|>
-//
-// }
-// ```
-// ->
-// ```
-// trait T {
-//     Type X;
-//     fn foo(&self);
-//     fn bar(&self) {}
-// }
-//
-// impl T for () {
-//     Type X = ();
-//     fn foo(&self) {}
-//     fn bar(&self) {}
-//
-// }
-// ```
 pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     add_missing_impl_members_inner(
         ctx,
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
index a072f63e7a..5f2b0dd189 100644
--- a/crates/ra_assists/src/assists/apply_demorgan.rs
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -1,26 +1,18 @@
+//! This contains the functions associated with the demorgan assist.
+//! This assist transforms boolean expressions of the form `!a || !b` into
+//! `!(a && b)`.
 use hir::db::HirDatabase;
 use ra_syntax::ast::{self, AstNode};
 use ra_syntax::SyntaxNode;
 
 use crate::{Assist, AssistCtx, AssistId};
 
-// Assist: apply_demorgan
-// Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
-// This transforms expressions of the form `!l || !r` into `!(l && r)`.
-// This also works with `&&`. This assist can only be applied with the cursor
-// on either `||` or `&&`, with both operands being a negation of some kind.
-// This means something of the form `!x` or `x != y`.
-// ```
-// fn main() {
-//     if x != 4 ||<|> !y {}
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//     if !(x == 4 && y) {}
-// }
-// ```
+/// Assist for applying demorgan's law
+///
+/// This transforms expressions of the form `!l || !r` into `!(l && r)`.
+/// This also works with `&&`. This assist can only be applied with the cursor
+/// on either `||` or `&&`, with both operands being a negation of some kind.
+/// This means something of the form `!x` or `x != y`.
 pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let expr = ctx.node_at_offset::<ast::BinExpr>()?;
     let op = expr.op_kind()?;
diff --git a/docs/user/assists.md b/docs/user/assists.md
index eeb4868321..cb4b0b9fb8 100644
--- a/docs/user/assists.md
+++ b/docs/user/assists.md
@@ -1,142 +1,5 @@
 # Assists
 
-## `add_derive`
-
-Adds a new `#[derive()]` clause to a struct or enum.
-
-```rust
-// BEFORE
-struct Point {
-    x: u32,
-    y: u32,<|>
-}
-
-// AFTER
-#[derive()]
-struct Point {
-    x: u32,
-    y: u32,
-}
-```
-
-## `add_explicit_type`
-
-Specify type for a let binding
-
-```rust
-// BEFORE
-fn main() {
-    let x<|> = 92;
-}
-
-// AFTER
-fn main() {
-    let x: i32 = 92;
-}
-```
-
-## `add_impl`
-
-Adds a new inherent impl for a type
-
-```rust
-// BEFORE
-struct Ctx<T: Clone> {
-     data: T,<|>
-}
-
-// AFTER
-struct Ctx<T: Clone> {
-     data: T,
-}
-
-impl<T: Clone> Ctx<T> {
-
-}
-```
-
-## `add_impl_default_members`
-
-Adds scaffold for overriding default impl members
-
-```rust
-// BEFORE
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    Type X = ();
-    fn foo(&self) {}<|>
-
-}
-
-// AFTER
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    Type X = ();
-    fn foo(&self) {}
-    fn bar(&self) {}
-
-}
-```
-
-## `add_impl_missing_members`
-
-Adds scaffold for required impl members
-
-```rust
-// BEFORE
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {<|>
-
-}
-
-// AFTER
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    fn foo(&self) { unimplemented!() }
-
-}
-```
-
-## `apply_demorgan`
-
-Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
-This transforms expressions of the form `!l || !r` into `!(l && r)`.
-This also works with `&&`. This assist can only be applied with the cursor
-on either `||` or `&&`, with both operands being a negation of some kind.
-This means something of the form `!x` or `x != y`.
-
-```rust
-// BEFORE
-fn main() {
-    if x != 4 ||<|> !y {}
-}
-
-// AFTER
-fn main() {
-    if !(x == 4 && y) {}
-}
-```
-
 ## `convert_to_guarded_return`
 
 Replace a large conditional with a guarded return.
diff --git a/docs/user/features.md b/docs/user/features.md
index acf092cec1..a94b65ad4d 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -104,6 +104,84 @@ the VS Code side to be able to position cursor. `<|>` signifies cursor
 
 See [assists.md](./assists.md)
 
+- Add `#[derive]`
+
+```rust
+// before:
+struct Foo {
+    <|>x: i32
+}
+// after:
+#[derive(<|>)]
+struct Foo {
+    x: i32
+}
+```
+
+- Add `impl`
+
+```rust
+// before:
+struct Foo<'a, T: Debug> {
+    <|>t: T
+}
+// after:
+struct Foo<'a, T: Debug> {
+    t: T
+}
+
+impl<'a, T: Debug> Foo<'a, T> {
+    <|>
+}
+```
+
+- Add missing `impl` members
+
+```rust
+// before:
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+    fn baz(&self);
+}
+
+struct S;
+
+impl Foo for S {
+    fn bar(&self) {}
+    <|>
+}
+
+// after:
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+    fn baz(&self);
+}
+
+struct S;
+
+impl Foo for S {
+    fn bar(&self) {}
+    fn foo(&self) { unimplemented!() }
+    fn baz(&self) { unimplemented!() }<|>
+}
+```
+
+- Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws)
+
+```rust
+// before:
+fn example(x: bool) -> bool {
+    !x || !x
+}
+
+// after:
+fn example(x: bool) -> bool {
+    !(x && x)
+}
+```
+
 - Import path
 
 ```rust
@@ -313,6 +391,19 @@ fn foo() {
 }
 ```
 
+- Add explicit type
+
+```rust
+// before:
+fn foo() {
+    let t<|> = (&2, Some(1));
+}
+// after:
+fn foo() {
+    let t<|>: (&i32, Option<i32>) = (&2, Some(1));
+}
+```
+
 - Move guard expression to match arm body
 ```rust
 // before:
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 4ec8ab75af..44729cd57a 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -74,14 +74,6 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
 }
 
 fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> {
-    do_extract_comment_blocks(text, false)
-}
-
-fn extract_comment_blocks_with_empty_lines(text: &str) -> Vec<Vec<String>> {
-    do_extract_comment_blocks(text, true)
-}
-
-fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) -> Vec<Vec<String>> {
     let mut res = Vec::new();
 
     let prefix = "// ";
@@ -89,11 +81,6 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) ->
 
     let mut block = vec![];
     for line in lines {
-        if line == "//" && allow_blocks_with_empty_lins {
-            block.push(String::new());
-            continue;
-        }
-
         let is_comment = line.starts_with(prefix);
         if is_comment {
             block.push(line[prefix.len()..].to_string());
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs
index e313820d18..654ae09d66 100644
--- a/xtask/src/codegen/gen_assists_docs.rs
+++ b/xtask/src/codegen/gen_assists_docs.rs
@@ -1,7 +1,7 @@
 use std::{fs, path::Path};
 
 use crate::{
-    codegen::{self, extract_comment_blocks_with_empty_lines, Mode},
+    codegen::{self, extract_comment_blocks, Mode},
     project_root, Result,
 };
 
@@ -34,7 +34,7 @@ fn collect_assists() -> Result<Vec<Assist>> {
 
     fn collect_file(acc: &mut Vec<Assist>, path: &Path) -> Result<()> {
         let text = fs::read_to_string(path)?;
-        let comment_blocks = extract_comment_blocks_with_empty_lines(&text);
+        let comment_blocks = extract_comment_blocks(&text);
 
         for block in comment_blocks {
             // FIXME: doesn't support blank lines yet, need to tweak
@@ -45,11 +45,7 @@ fn collect_assists() -> Result<Vec<Assist>> {
                 continue;
             }
             let id = first_line["Assist: ".len()..].to_string();
-            assert!(
-                id.chars().all(|it| it.is_ascii_lowercase() || it == '_'),
-                "invalid assist id: {:?}",
-                id
-            );
+            assert!(id.chars().all(|it| it.is_ascii_lowercase() || it == '_'));
 
             let doc = take_until(lines.by_ref(), "```");
             let before = take_until(lines.by_ref(), "```");
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 06aa3c8eca..eb39bf7159 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -159,6 +159,17 @@ fn fix_path_for_mac() -> Result<()> {
 }
 
 fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
+    let npm_version = Cmd {
+        unix: r"npm --version",
+        windows: r"cmd.exe /c npm.cmd --version",
+        work_dir: "./editors/code",
+    }
+    .run();
+
+    if npm_version.is_err() {
+        eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin")
+    }
+
     Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?;
     Cmd {
         unix: r"npm run package",


Test patch:
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs
index 872bbdf17a..88e901517c 100644
--- a/crates/ra_assists/src/doc_tests.rs
+++ b/crates/ra_assists/src/doc_tests.rs
@@ -15,10 +15,8 @@ fn check(assist_id: &str, before: &str, after: &str) {
     let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
     let frange = FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
 
-    let (_assist_id, action) = crate::assists(&db, frange)
-        .into_iter()
-        .find(|(id, _)| id.id.0 == assist_id)
-        .unwrap_or_else(|| panic!("Assist {:?} is not applicable", assist_id));
+    let (_assist_id, action) =
+        crate::assists(&db, frange).into_iter().find(|(id, _)| id.id.0 == assist_id).unwrap();
 
     let actual = action.edit.apply(&before);
     assert_eq_text!(after, &actual);
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
index 76d86b93da..e5f6910f11 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -2,145 +2,6 @@
 
 use super::check;
 
-#[test]
-fn doctest_add_derive() {
-    check(
-        "add_derive",
-        r#####"
-struct Point {
-    x: u32,
-    y: u32,<|>
-}
-"#####,
-        r#####"
-#[derive()]
-struct Point {
-    x: u32,
-    y: u32,
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_add_explicit_type() {
-    check(
-        "add_explicit_type",
-        r#####"
-fn main() {
-    let x<|> = 92;
-}
-"#####,
-        r#####"
-fn main() {
-    let x: i32 = 92;
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_add_impl() {
-    check(
-        "add_impl",
-        r#####"
-struct Ctx<T: Clone> {
-     data: T,<|>
-}
-"#####,
-        r#####"
-struct Ctx<T: Clone> {
-     data: T,
-}
-
-impl<T: Clone> Ctx<T> {
-
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_add_impl_default_members() {
-    check(
-        "add_impl_default_members",
-        r#####"
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    Type X = ();
-    fn foo(&self) {}<|>
-
-}
-"#####,
-        r#####"
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    Type X = ();
-    fn foo(&self) {}
-    fn bar(&self) {}
-
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_add_impl_missing_members() {
-    check(
-        "add_impl_missing_members",
-        r#####"
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {<|>
-
-}
-"#####,
-        r#####"
-trait T {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl T for () {
-    fn foo(&self) { unimplemented!() }
-
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_apply_demorgan() {
-    check(
-        "apply_demorgan",
-        r#####"
-fn main() {
-    if x != 4 ||<|> !y {}
-}
-"#####,
-        r#####"
-fn main() {
-    if !(x == 4 && y) {}
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_convert_to_guarded_return() {
     check(