Repository: rust-analyzer/rust-analyzer
Pull request #10993 (2021-12-12 11:11:32)

minor: Bump deps
Gets `coutme 2.0`.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 880b34a6fd..dca35a212a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -220,12 +220,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "countme"
-version = "2.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58"
-
 [[package]]
 name = "countme"
 version = "3.0.0"
@@ -810,9 +804,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.109"
+version = "0.2.111"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01"
+checksum = "8e167738f1866a7ec625567bae89ca0d44477232a4f7c52b1c7f2adc2c98804f"
 
 [[package]]
 name = "libloading"
@@ -1184,7 +1178,7 @@ name = "profile"
 version = "0.0.0"
 dependencies = [
  "cfg-if",
- "countme 3.0.0",
+ "countme",
  "la-arena",
  "libc",
  "once_cell",
@@ -1303,11 +1297,11 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 [[package]]
 name = "rowan"
-version = "0.14.1"
+version = "0.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f77412a3d1f26af0c0783c23b3555a301b1a49805cba7bf9a7827a9e9e285f0"
+checksum = "104e4d36da6a2a0c9485ebf1b2dfc628036c7cc9b38bd1b14fa785f1f1bdf5f0"
 dependencies = [
- "countme 2.0.4",
+ "countme",
  "hashbrown",
  "memoffset",
  "rustc-hash",
@@ -1389,9 +1383,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "ryu"
-version = "1.0.6"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568"
+checksum = "b30e4c09749c107e83dd61baf9604198efc4542863c88af39dafcaca89c7c9f9"
 
 [[package]]
 name = "salsa"
@@ -1454,18 +1448,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.130"
+version = "1.0.131"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
+checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.130"
+version = "1.0.131"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
+checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 9a0f457905..a1e7198bc2 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -181,12 +181,8 @@ impl<'a> DeclValidator<'a> {
                 AttrDefId::ExternBlockId(id) => Some(id.lookup(self.db.upcast()).container.into()),
                 // These warnings should not explore macro definitions at all
                 AttrDefId::MacroDefId(_) => None,
-                AttrDefId::AdtId(aid) => match aid {
-                    AdtId::StructId(sid) => Some(sid.lookup(self.db.upcast()).container.into()),
-                    AdtId::EnumId(eid) => Some(eid.lookup(self.db.upcast()).container.into()),
-                    // Unions aren't yet supported
-                    AdtId::UnionId(_) => None,
-                },
+                // Will never occur under an enum/struct/union/type alias
+                AttrDefId::AdtId(_) => None,
                 AttrDefId::FieldId(_) => None,
                 AttrDefId::EnumVariantId(_) => None,
                 AttrDefId::TypeAliasId(_) => None,
diff --git a/crates/ide_assists/src/handlers/generate_documentation_template.rs b/crates/ide_assists/src/handlers/generate_documentation_template.rs
deleted file mode 100644
index cfc7e9d043..0000000000
--- a/crates/ide_assists/src/handlers/generate_documentation_template.rs
+++ /dev/null
@@ -1,1091 +0,0 @@
-use hir::{AsAssocItem, HasVisibility, ModuleDef, Visibility};
-use ide_db::assists::{AssistId, AssistKind};
-use itertools::Itertools;
-use stdx::to_lower_snake_case;
-use syntax::{
-    ast::{self, edit::IndentLevel, HasDocComments, HasName},
-    AstNode,
-};
-
-use crate::assist_context::{AssistContext, Assists};
-
-// Assist: generate_documentation_template
-//
-// Adds a documentation template above a function definition / declaration.
-//
-// ```
-// pub fn my_$0func(a: i32, b: i32) -> Result<(), std::io::Error> {
-//     unimplemented!()
-// }
-// ```
-// ->
-// ```
-// /// .
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use test::my_func;
-// ///
-// /// assert_eq!(my_func(a, b), );
-// /// ```
-// ///
-// /// # Errors
-// ///
-// /// This function will return an error if .
-// pub fn my_func(a: i32, b: i32) -> Result<(), std::io::Error> {
-//     unimplemented!()
-// }
-// ```
-pub(crate) fn generate_documentation_template(
-    acc: &mut Assists,
-    ctx: &AssistContext,
-) -> Option<()> {
-    let name = ctx.find_node_at_offset::<ast::Name>()?;
-    let ast_func = name.syntax().parent().and_then(ast::Fn::cast)?;
-    if is_in_trait_impl(&ast_func, ctx)
-        || !is_public(&ast_func, ctx)?
-        || ast_func.doc_comments().next().is_some()
-    {
-        return None;
-    }
-
-    let parent_syntax = ast_func.syntax();
-    let text_range = parent_syntax.text_range();
-    let indent_level = IndentLevel::from_node(&parent_syntax);
-
-    acc.add(
-        AssistId("generate_documentation_template", AssistKind::Generate),
-        "Generate a documentation template",
-        text_range,
-        |builder| {
-            let mut doc_lines = Vec::new();
-            // Introduction / short function description before the sections
-            doc_lines.push(introduction_builder(&ast_func, ctx));
-            // Then come the sections
-            if let Some(mut lines) = examples_builder(&ast_func, ctx) {
-                doc_lines.push("".into());
-                doc_lines.append(&mut lines);
-            }
-            for section_builder in [panics_builder, errors_builder, safety_builder] {
-                if let Some(mut lines) = section_builder(&ast_func) {
-                    doc_lines.push("".into());
-                    doc_lines.append(&mut lines);
-                }
-            }
-            builder.insert(text_range.start(), documentation_from_lines(doc_lines, indent_level));
-        },
-    )
-}
-
-/// Builds an introduction, trying to be smart if the function is `::new()`
-fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> String {
-    || -> Option<String> {
-        let hir_func = ctx.sema.to_def(ast_func)?;
-        let container = hir_func.as_assoc_item(ctx.db())?.container(ctx.db());
-        if let hir::AssocItemContainer::Impl(implementation) = container {
-            let ret_ty = hir_func.ret_type(ctx.db());
-            let self_ty = implementation.self_ty(ctx.db());
-
-            let is_new = ast_func.name()?.to_string() == "new";
-            match is_new && ret_ty == self_ty {
-                true => Some(format!("Creates a new [`{}`].", self_type(ast_func)?)),
-                false => None,
-            }
-        } else {
-            None
-        }
-    }()
-    .unwrap_or_else(|| ".".into())
-}
-
-/// Builds an `# Examples` section. An option is returned to be able to manage an error in the AST.
-fn examples_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<Vec<String>> {
-    let mut lines = string_vec_from(&["# Examples", "", "```"]);
-    if is_in_trait_def(ast_func, ctx) {
-        lines.push("// Example template not implemented for trait functions".into());
-    } else {
-        lines.append(&mut gen_ex_template(ast_func, ctx)?)
-    };
-
-    lines.push("```".into());
-    Some(lines)
-}
-
-/// Builds an optional `# Panics` section
-fn panics_builder(ast_func: &ast::Fn) -> Option<Vec<String>> {
-    match can_panic(ast_func) {
-        Some(true) => Some(string_vec_from(&["# Panics", "", "Panics if ."])),
-        _ => None,
-    }
-}
-
-/// Builds an optional `# Errors` section
-fn errors_builder(ast_func: &ast::Fn) -> Option<Vec<String>> {
-    match return_type(ast_func)?.to_string().contains("Result") {
-        true => Some(string_vec_from(&["# Errors", "", "This function will return an error if ."])),
-        false => None,
-    }
-}
-
-/// Builds an optional `# Safety` section
-fn safety_builder(ast_func: &ast::Fn) -> Option<Vec<String>> {
-    let is_unsafe = ast_func.unsafe_token().is_some();
-    match is_unsafe {
-        true => Some(string_vec_from(&["# Safety", "", "."])),
-        false => None,
-    }
-}
-
-/// Generates an example template
-fn gen_ex_template(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<Vec<String>> {
-    let mut lines = Vec::new();
-    let is_unsafe = ast_func.unsafe_token().is_some();
-    let param_list = ast_func.param_list()?;
-    let ref_mut_params = ref_mut_params(&param_list);
-    let self_name: Option<String> = self_name(ast_func);
-
-    lines.push(format!("use {};", build_path(ast_func, ctx)?));
-    lines.push("".into());
-    if let Some(self_definition) = self_definition(ast_func, self_name.as_deref()) {
-        lines.push(self_definition);
-    }
-    for param_name in &ref_mut_params {
-        lines.push(format!("let mut {} = ;", param_name))
-    }
-    // Call the function, check result
-    let function_call = function_call(ast_func, &param_list, self_name.as_deref(), is_unsafe)?;
-    if returns_a_value(ast_func, ctx) {
-        if count_parameters(&param_list) < 3 {
-            lines.push(format!("assert_eq!({}, );", function_call));
-        } else {
-            lines.push(format!("let result = {};", function_call));
-            lines.push("assert_eq!(result, );".into());
-        }
-    } else {
-        lines.push(format!("{};", function_call));
-    }
-    // Check the mutated values
-    if is_ref_mut_self(ast_func) == Some(true) {
-        lines.push(format!("assert_eq!({}, );", self_name?));
-    }
-    for param_name in &ref_mut_params {
-        lines.push(format!("assert_eq!({}, );", param_name));
-    }
-    Some(lines)
-}
-
-/// Checks if the function is public / exported
-fn is_public(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<bool> {
-    let hir_func = ctx.sema.to_def(ast_func)?;
-    Some(
-        hir_func.visibility(ctx.db()) == Visibility::Public
-            && all_parent_mods_public(&hir_func, ctx),
-    )
-}
-
-/// Checks that all parent modules of the function are public / exported
-fn all_parent_mods_public(hir_func: &hir::Function, ctx: &AssistContext) -> bool {
-    let mut module = hir_func.module(ctx.db());
-    loop {
-        if let Some(parent) = module.parent(ctx.db()) {
-            match ModuleDef::from(module).visibility(ctx.db()) {
-                Visibility::Public => module = parent,
-                _ => break false,
-            }
-        } else {
-            break true;
-        }
-    }
-}
-
-/// Returns the name of the current crate
-fn crate_name(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<String> {
-    let krate = ctx.sema.scope(&ast_func.syntax()).module()?.krate();
-    Some(krate.display_name(ctx.db())?.to_string())
-}
-
-/// `None` if function without a body; some bool to guess if function can panic
-fn can_panic(ast_func: &ast::Fn) -> Option<bool> {
-    let body = ast_func.body()?.to_string();
-    let can_panic = body.contains("panic!(")
-        // FIXME it would be better to not match `debug_assert*!` macro invocations
-        || body.contains("assert!(")
-        || body.contains(".unwrap()")
-        || body.contains(".expect(");
-    Some(can_panic)
-}
-
-/// Helper function to get the name that should be given to `self` arguments
-fn self_name(ast_func: &ast::Fn) -> Option<String> {
-    self_partial_type(ast_func).map(|name| to_lower_snake_case(&name))
-}
-
-/// Heper function to get the name of the type of `self`
-fn self_type(ast_func: &ast::Fn) -> Option<String> {
-    ast_func
-        .syntax()
-        .ancestors()
-        .find_map(ast::Impl::cast)
-        .and_then(|i| i.self_ty())
-        .map(|t| (t.to_string()))
-}
-
-/// Heper function to get the name of the type of `self` without generic arguments
-fn self_partial_type(ast_func: &ast::Fn) -> Option<String> {
-    let mut self_type = self_type(ast_func)?;
-    if let Some(idx) = self_type.find(|c| ['<', ' '].contains(&c)) {
-        self_type.truncate(idx);
-    }
-    Some(self_type)
-}
-
-/// Helper function to determine if the function is in a trait implementation
-fn is_in_trait_impl(ast_func: &ast::Fn, ctx: &AssistContext) -> bool {
-    ctx.sema
-        .to_def(ast_func)
-        .and_then(|hir_func| hir_func.as_assoc_item(ctx.db()))
-        .and_then(|assoc_item| assoc_item.containing_trait_impl(ctx.db()))
-        .is_some()
-}
-
-/// Helper function to determine if the function definition is in a trait definition
-fn is_in_trait_def(ast_func: &ast::Fn, ctx: &AssistContext) -> bool {
-    ctx.sema
-        .to_def(ast_func)
-        .and_then(|hir_func| hir_func.as_assoc_item(ctx.db()))
-        .and_then(|assoc_item| assoc_item.containing_trait(ctx.db()))
-        .is_some()
-}
-
-/// Returns `None` if no `self` at all, `Some(true)` if there is `&mut self` else `Some(false)`
-fn is_ref_mut_self(ast_func: &ast::Fn) -> Option<bool> {
-    let self_param = ast_func.param_list()?.self_param()?;
-    Some(self_param.mut_token().is_some() && self_param.amp_token().is_some())
-}
-
-/// Helper function to define an variable to be the `self` argument
-fn self_definition(ast_func: &ast::Fn, self_name: Option<&str>) -> Option<String> {
-    let definition = match is_ref_mut_self(ast_func)? {
-        true => format!("let mut {} = ;", self_name?),
-        false => format!("let {} = ;", self_name?),
-    };
-    Some(definition)
-}
-
-/// Helper function to determine if a parameter is `&mut`
-fn is_a_ref_mut_param(param: &ast::Param) -> bool {
-    match param.ty() {
-        Some(ast::Type::RefType(param_ref)) => param_ref.mut_token().is_some(),
-        _ => false,
-    }
-}
-
-/// Helper function to build the list of `&mut` parameters
-fn ref_mut_params(param_list: &ast::ParamList) -> Vec<String> {
-    param_list
-        .params()
-        .filter_map(|param| match is_a_ref_mut_param(&param) {
-            // Maybe better filter the param name (to do this maybe extract a function from
-            // `arguments_from_params`?) in case of a `mut a: &mut T`. Anyway managing most (not
-            // all) cases might be enough, the goal is just to produce a template.
-            true => Some(param.pat()?.to_string()),
-            false => None,
-        })
-        .collect()
-}
-
-/// Helper function to build the comma-separated list of arguments of the function
-fn arguments_from_params(param_list: &ast::ParamList) -> String {
-    let args_iter = param_list.params().map(|param| match param.pat() {
-        // To avoid `mut` in the function call (which would be a nonsense), `Pat` should not be
-        // written as is so its variants must be managed independently. Other variants (for
-        // instance `TuplePat`) could be managed later.
-        Some(ast::Pat::IdentPat(ident_pat)) => match ident_pat.name() {
-            Some(name) => match is_a_ref_mut_param(&param) {
-                true => format!("&mut {}", name.to_string()),
-                false => name.to_string(),
-            },
-            None => "_".to_string(),
-        },
-        _ => "_".to_string(),
-    });
-    Itertools::intersperse(args_iter, ", ".to_string()).collect()
-}
-
-/// Helper function to build a function call. `None` if expected `self_name` was not provided
-fn function_call(
-    ast_func: &ast::Fn,
-    param_list: &ast::ParamList,
-    self_name: Option<&str>,
-    is_unsafe: bool,
-) -> Option<String> {
-    let name = ast_func.name()?;
-    let arguments = arguments_from_params(&param_list);
-    let function_call = if param_list.self_param().is_some() {
-        format!("{}.{}({})", self_name?, name, arguments)
-    } else if let Some(implementation) = self_partial_type(ast_func) {
-        format!("{}::{}({})", implementation, name, arguments)
-    } else {
-        format!("{}({})", name, arguments)
-    };
-    match is_unsafe {
-        true => Some(format!("unsafe {{ {} }}", function_call)),
-        false => Some(function_call),
-    }
-}
-
-/// Helper function to count the parameters including `self`
-fn count_parameters(param_list: &ast::ParamList) -> usize {
-    param_list.params().count() + if param_list.self_param().is_some() { 1 } else { 0 }
-}
-
-/// Helper function to transform lines of documentation into a Rust code documentation
-fn documentation_from_lines(doc_lines: Vec<String>, indent_level: IndentLevel) -> String {
-    let mut result = String::new();
-    for doc_line in doc_lines {
-        result.push_str("///");
-        if !doc_line.is_empty() {
-            result.push(' ');
-            result.push_str(&doc_line);
-        }
-        result.push('\n');
-        result.push_str(&indent_level.to_string());
-    }
-    result
-}
-
-/// Helper function to transform an array of borrowed strings to an owned `Vec<String>`
-fn string_vec_from(string_array: &[&str]) -> Vec<String> {
-    string_array.iter().map(|&s| s.to_owned()).collect()
-}
-
-/// Helper function to build the path of the module in the which is the node
-fn build_path(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<String> {
-    let crate_name = crate_name(ast_func, ctx)?;
-    let leaf = self_partial_type(ast_func)
-        .or_else(|| ast_func.name().map(|n| n.to_string()))
-        .unwrap_or_else(|| "*".into());
-    let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into();
-    match module_def.canonical_path(ctx.db()) {
-        Some(path) => Some(format!("{}::{}::{}", crate_name, path, leaf)),
-        None => Some(format!("{}::{}", crate_name, leaf)),
-    }
-}
-
-/// Helper function to get the return type of a function
-fn return_type(ast_func: &ast::Fn) -> Option<ast::Type> {
-    ast_func.ret_type()?.ty()
-}
-
-/// Helper function to determine if the function returns some data
-fn returns_a_value(ast_func: &ast::Fn, ctx: &AssistContext) -> bool {
-    ctx.sema
-        .to_def(ast_func)
-        .map(|hir_func| hir_func.ret_type(ctx.db()))
-        .map(|ret_ty| !ret_ty.is_unit() && !ret_ty.is_never())
-        .unwrap_or(false)
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn not_applicable_on_function_calls() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-fn hello_world() {}
-fn calls_hello_world() {
-    hello_world$0();
-}
-"#,
-        )
-    }
-
-    #[test]
-    fn not_applicable_in_trait_impl() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-trait MyTrait {}
-struct MyStruct;
-impl MyTrait for MyStruct {
-    fn hello_world$0();
-}
-"#,
-        )
-    }
-
-    #[test]
-    fn not_applicable_if_function_is_private() {
-        check_assist_not_applicable(generate_documentation_template, r#"fn priv$0ate() {}"#);
-    }
-
-    #[test]
-    fn not_applicable_if_function_is_pub_crate() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"pub(crate) fn pri$0vate() {}"#,
-        );
-    }
-
-    #[test]
-    fn not_applicable_if_function_is_in_private_mod() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-mod PrivateModule {
-    pub fn pri$0vate() {}
-}"#,
-        );
-    }
-
-    #[test]
-    fn not_applicable_if_function_is_in_pub_crate_mod() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-pub(crate) mod PrivateModule {
-    pub fn pr$0ivate() {}
-}"#,
-        );
-    }
-
-    #[test]
-    fn not_applicable_if_function_is_in_non_public_mod_is_recursive() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-mod ParentPrivateModule {
-    pub mod PrivateModule {
-        pub fn pr$0ivate() {}
-    }
-}"#,
-        );
-    }
-
-    #[test]
-    fn not_applicable_if_function_already_documented() {
-        check_assist_not_applicable(
-            generate_documentation_template,
-            r#"
-/// Some documentation here
-pub fn $0documented_function() {}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_noop_function() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn no$0op() {}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::noop;
-///
-/// noop();
-/// ```
-pub fn noop() {}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_a_parameter() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn no$0op_with_param(_a: i32) {}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::noop_with_param;
-///
-/// noop_with_param(_a);
-/// ```
-pub fn noop_with_param(_a: i32) {}
-"#,
-        );
-    }
-
-    #[test]
-    fn detects_unsafe_function() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub unsafe fn no$0op_unsafe() {}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::noop_unsafe;
-///
-/// unsafe { noop_unsafe() };
-/// ```
-///
-/// # Safety
-///
-/// .
-pub unsafe fn noop_unsafe() {}
-"#,
-        );
-    }
-
-    #[test]
-    fn guesses_panic_macro_can_panic() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn panic$0s_if(a: bool) {
-    if a {
-        panic!();
-    }
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::panics_if;
-///
-/// panics_if(a);
-/// ```
-///
-/// # Panics
-///
-/// Panics if .
-pub fn panics_if(a: bool) {
-    if a {
-        panic!();
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn guesses_assert_macro_can_panic() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn $0panics_if_not(a: bool) {
-    assert!(a == true);
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::panics_if_not;
-///
-/// panics_if_not(a);
-/// ```
-///
-/// # Panics
-///
-/// Panics if .
-pub fn panics_if_not(a: bool) {
-    assert!(a == true);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn guesses_unwrap_can_panic() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn $0panics_if_none(a: Option<()>) {
-    a.unwrap();
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::panics_if_none;
-///
-/// panics_if_none(a);
-/// ```
-///
-/// # Panics
-///
-/// Panics if .
-pub fn panics_if_none(a: Option<()>) {
-    a.unwrap();
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn guesses_expect_can_panic() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn $0panics_if_none2(a: Option<()>) {
-    a.expect("Bouh!");
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::panics_if_none2;
-///
-/// panics_if_none2(a);
-/// ```
-///
-/// # Panics
-///
-/// Panics if .
-pub fn panics_if_none2(a: Option<()>) {
-    a.expect("Bouh!");
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn checks_output_in_example() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn returns_a_value$0() -> i32 {
-    0
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::returns_a_value;
-///
-/// assert_eq!(returns_a_value(), );
-/// ```
-pub fn returns_a_value() -> i32 {
-    0
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn detects_result_output() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn returns_a_result$0() -> Result<i32, std::io::Error> {
-    Ok(0)
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::returns_a_result;
-///
-/// assert_eq!(returns_a_result(), );
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if .
-pub fn returns_a_result() -> Result<i32, std::io::Error> {
-    Ok(0)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn checks_ref_mut_in_example() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn modifies_a_value$0(a: &mut i32) {
-    *a = 0;
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::modifies_a_value;
-///
-/// let mut a = ;
-/// modifies_a_value(&mut a);
-/// assert_eq!(a, );
-/// ```
-pub fn modifies_a_value(a: &mut i32) {
-    *a = 0;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn stores_result_if_at_least_3_params() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub fn sum3$0(a: i32, b: i32, c: i32) -> i32 {
-    a + b + c
-}
-"#,
-            r#"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::sum3;
-///
-/// let result = sum3(a, b, c);
-/// assert_eq!(result, );
-/// ```
-pub fn sum3(a: i32, b: i32, c: i32) -> i32 {
-    a + b + c
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_fn_in_mods() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub mod a {
-    pub mod b {
-        pub fn no$0op() {}
-    }
-}
-"#,
-            r#"
-pub mod a {
-    pub mod b {
-        /// .
-        ///
-        /// # Examples
-        ///
-        /// ```
-        /// use test::a::b::noop;
-        ///
-        /// noop();
-        /// ```
-        pub fn noop() {}
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_fn_in_impl() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub struct MyStruct;
-impl MyStruct {
-    pub fn no$0op() {}
-}
-"#,
-            r#"
-pub struct MyStruct;
-impl MyStruct {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use test::MyStruct;
-    ///
-    /// MyStruct::noop();
-    /// ```
-    pub fn noop() {}
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_fn_in_trait() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub trait MyTrait {
-    fn fun$0ction_trait();
-}
-"#,
-            r#"
-pub trait MyTrait {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // Example template not implemented for trait functions
-    /// ```
-    fn function_trait();
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_unsafe_fn_in_trait() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub trait MyTrait {
-    unsafe fn unsafe_funct$0ion_trait();
-}
-"#,
-            r#"
-pub trait MyTrait {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // Example template not implemented for trait functions
-    /// ```
-    ///
-    /// # Safety
-    ///
-    /// .
-    unsafe fn unsafe_function_trait();
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_fn_in_trait_with_default_panicking() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub trait MyTrait {
-    fn function_trait_with_$0default_panicking() {
-        panic!()
-    }
-}
-"#,
-            r#"
-pub trait MyTrait {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // Example template not implemented for trait functions
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics if .
-    fn function_trait_with_default_panicking() {
-        panic!()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_fn_in_trait_returning_result() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-pub trait MyTrait {
-    fn function_tr$0ait_returning_result() -> Result<(), std::io::Error>;
-}
-"#,
-            r#"
-pub trait MyTrait {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // Example template not implemented for trait functions
-    /// ```
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if .
-    fn function_trait_returning_result() -> Result<(), std::io::Error>;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn detects_new() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-#[derive(Debug, PartialEq)]
-pub struct MyGenericStruct<T> {
-    pub x: T,
-}
-impl<T> MyGenericStruct<T> {
-    pub fn new$0(x: T) -> MyGenericStruct<T> {
-        MyGenericStruct { x }
-    }
-}
-"#,
-            r#"
-#[derive(Debug, PartialEq)]
-pub struct MyGenericStruct<T> {
-    pub x: T,
-}
-impl<T> MyGenericStruct<T> {
-    /// Creates a new [`MyGenericStruct<T>`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use test::MyGenericStruct;
-    ///
-    /// assert_eq!(MyGenericStruct::new(x), );
-    /// ```
-    pub fn new(x: T) -> MyGenericStruct<T> {
-        MyGenericStruct { x }
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn detects_new_with_self() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-#[derive(Debug, PartialEq)]
-pub struct MyGenericStruct2<T> {
-    pub x: T,
-}
-impl<T> MyGenericStruct2<T> {
-    pub fn new$0(x: T) -> Self {
-        MyGenericStruct2 { x }
-    }
-}
-"#,
-            r#"
-#[derive(Debug, PartialEq)]
-pub struct MyGenericStruct2<T> {
-    pub x: T,
-}
-impl<T> MyGenericStruct2<T> {
-    /// Creates a new [`MyGenericStruct2<T>`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use test::MyGenericStruct2;
-    ///
-    /// assert_eq!(MyGenericStruct2::new(x), );
-    /// ```
-    pub fn new(x: T) -> Self {
-        MyGenericStruct2 { x }
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn supports_method_call() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-impl<T> MyGenericStruct<T> {
-    pub fn co$0nsume(self) {}
-}
-"#,
-            r#"
-impl<T> MyGenericStruct<T> {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use test::MyGenericStruct;
-    ///
-    /// let my_generic_struct = ;
-    /// my_generic_struct.consume();
-    /// ```
-    pub fn consume(self) {}
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn checks_modified_self_param() {
-        check_assist(
-            generate_documentation_template,
-            r#"
-impl<T> MyGenericStruct<T> {
-    pub fn modi$0fy(&mut self, new_value: T) {
-        self.x = new_value;
-    }
-}
-"#,
-            r#"
-impl<T> MyGenericStruct<T> {
-    /// .
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use test::MyGenericStruct;
-    ///
-    /// let mut my_generic_struct = ;
-    /// my_generic_struct.modify(new_value);
-    /// assert_eq!(my_generic_struct, );
-    /// ```
-    pub fn modify(&mut self, new_value: T) {
-        self.x = new_value;
-    }
-}
-"#,
-        );
-    }
-}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 61ac45637b..5d4c1532db 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -136,7 +136,6 @@ mod handlers {
     mod generate_default_from_new;
     mod generate_deref;
     mod generate_derive;
-    mod generate_documentation_template;
     mod generate_enum_is_method;
     mod generate_enum_projection_method;
     mod generate_from_impl_for_enum;
@@ -220,7 +219,6 @@ mod handlers {
             generate_delegate_methods::generate_delegate_methods,
             generate_deref::generate_deref,
             generate_derive::generate_derive,
-            generate_documentation_template::generate_documentation_template,
             generate_enum_is_method::generate_enum_is_method,
             generate_enum_projection_method::generate_enum_as_method,
             generate_enum_projection_method::generate_enum_try_into_method,
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index d459e51161..e8566b80b6 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -561,21 +561,11 @@ impl<'a> CompletionContext<'a> {
                         })().unwrap_or((None, None))
                     },
                     ast::RecordExprField(it) => {
-                        if let Some(expr) = it.expr() {
-                            cov_mark::hit!(expected_type_struct_field_with_leading_char);
-                            (
-                                self.sema.type_of_expr(&expr).map(TypeInfo::original),
-                                it.field_name().map(NameOrNameRef::NameRef),
-                            )
-                        } else {
-                            cov_mark::hit!(expected_type_struct_field_followed_by_comma);
-                            let ty = self.sema.resolve_record_field(&it)
-                                .map(|(_, _, ty)| ty);
-                            (
-                                ty,
-                                it.field_name().map(NameOrNameRef::NameRef),
-                            )
-                        }
+                        cov_mark::hit!(expected_type_struct_field_with_leading_char);
+                        (
+                            it.expr().as_ref().and_then(|e| self.sema.type_of_expr(e)).map(TypeInfo::original),
+                            it.field_name().map(NameOrNameRef::NameRef),
+                        )
                     },
                     ast::MatchExpr(it) => {
                         cov_mark::hit!(expected_type_match_arm_without_leading_char);
@@ -1018,20 +1008,6 @@ fn foo() {
         )
     }
 
-    #[test]
-    fn expected_type_struct_field_followed_by_comma() {
-        cov_mark::check!(expected_type_struct_field_followed_by_comma);
-        check_expected_type_and_name(
-            r#"
-struct Foo { a: u32 }
-fn foo() {
-    Foo { a: $0, };
-}
-"#,
-            expect![[r#"ty: u32, name: a"#]],
-        )
-    }
-
     #[test]
     fn expected_type_generic_struct_field() {
         check_expected_type_and_name(
diff --git a/crates/ide_diagnostics/src/handlers/incorrect_case.rs b/crates/ide_diagnostics/src/handlers/incorrect_case.rs
index 6a78c08d44..3206a63a90 100644
--- a/crates/ide_diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide_diagnostics/src/handlers/incorrect_case.rs
@@ -332,15 +332,6 @@ fn main() {
         check_diagnostics(
             r#"
 #![allow(non_snake_case)]
-#![allow(non_camel_case_types)]
-
-struct S {
-    fooBar: bool,
-}
-
-enum E {
-    fooBar,
-}
 
 mod F {
     fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {}
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 8705fb2115..526024a836 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
 [dependencies]
 cov-mark = "2.0.0-pre.1"
 itertools = "0.10.0"
-rowan = "0.14.0"
+rowan = "0.15.0"
 rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" }
 rustc-hash = "1.1.0"
 once_cell = "1.3.1"


Test patch:
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index c67e15b2ce..e30f98bcd1 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -839,36 +839,6 @@ struct Point {
     )
 }
 
-#[test]
-fn doctest_generate_documentation_template() {
-    check_doc_test(
-        "generate_documentation_template",
-        r#####"
-pub fn my_$0func(a: i32, b: i32) -> Result<(), std::io::Error> {
-    unimplemented!()
-}
-"#####,
-        r#####"
-/// .
-///
-/// # Examples
-///
-/// ```
-/// use test::my_func;
-///
-/// assert_eq!(my_func(a, b), );
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if .
-pub fn my_func(a: i32, b: i32) -> Result<(), std::io::Error> {
-    unimplemented!()
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_generate_enum_as_method() {
     check_doc_test(