Repository: rust-analyzer/rust-analyzer
Pull request #11021 (2021-12-15 11:34:52)

internal: Use default XCode version
The GHA image no longer contains XCode 12.2, let's use the default version for now.

bors r+


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index e2a2d98a36..2f009c4322 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -194,11 +194,12 @@ jobs:
     runs-on: macos-latest
     env:
       RA_TARGET: x86_64-apple-darwin
-      SELECT_XCODE: /Applications/Xcode_12.2.app
+#      SELECT_XCODE: /Applications/Xcode_12.2.app
 
     steps:
-    - name: Select XCode version
-      run: sudo xcode-select -s "${SELECT_XCODE}"
+# use the default (12.5.1 as of today)
+#    - name: Select XCode version
+#      run: sudo xcode-select -s "${SELECT_XCODE}"
 
     - name: Checkout repository
       uses: actions/checkout@v2
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 79163ad4d0..880596b37c 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -291,12 +291,15 @@ impl SourceAnalyzer {
             }
         }
 
-        let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
-        let tuple_struct_pat = || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
-        if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
+        if let Some(pat) = parent()
+            .and_then(ast::RecordPat::cast)
+            .map(ast::Pat::from)
+            .or_else(|| parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from))
+        {
             let pat_id = self.pat_id(&pat)?;
-            let variant_res_for_pat = self.infer.as_ref()?.variant_resolution_for_pat(pat_id);
-            if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
+            if let Some(VariantId::EnumVariantId(variant)) =
+                self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
+            {
                 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
             }
         }
@@ -332,9 +335,6 @@ impl SourceAnalyzer {
                 }
             }
         } else if is_path_of_attr {
-            // Case where we are resolving the final path segment of a path in an attribute
-            // in this case we have to check for inert/builtin attributes and tools and prioritize
-            // resolution of attributes over other namesapces
             let name_ref = path.as_single_name_ref();
             let builtin =
                 name_ref.as_ref().map(ast::NameRef::text).as_deref().and_then(BuiltinAttr::by_name);
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 06689e1d29..a84501fa54 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -227,7 +227,7 @@ impl<'a> InferenceContext<'a> {
             self.table.trait_env.clone(),
             krate,
             &traits_in_scope,
-            self.resolver.module(),
+            None,
             Some(name),
             method_resolution::LookupMode::Path,
             move |_ty, item| {
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 4985a71a85..df25d80178 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -1,8 +1,5 @@
 //! Extracts, resolves and rewrites links and intra-doc links in markdown documentation.
 
-#[cfg(test)]
-mod tests;
-
 mod intra_doc_links;
 
 use either::Either;
@@ -531,3 +528,399 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
         AssocItem::TypeAlias(ty) => format!("associatedtype.{}", ty.name(db)),
     })
 }
+
+#[cfg(test)]
+mod tests {
+    use expect_test::{expect, Expect};
+    use ide_db::base_db::FileRange;
+    use itertools::Itertools;
+
+    use crate::{fixture, TryToNav};
+
+    use super::*;
+
+    #[test]
+    fn external_docs_doc_url_crate() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:main deps:foo
+use foo$0::Foo;
+//- /lib.rs crate:foo
+pub struct Foo;
+"#,
+            expect![[r#"https://docs.rs/foo/*/foo/index.html"#]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_std_crate() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:std
+use self$0;
+"#,
+            expect![[r#"https://doc.rust-lang.org/nightly/std/index.html"#]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_struct() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Fo$0o;
+"#,
+            expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_struct_field() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo {
+    field$0: ()
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#structfield.field"##]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_fn() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub fn fo$0o() {}
+"#,
+            expect![[r#"https://docs.rs/foo/*/foo/fn.foo.html"#]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_impl_assoc() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo;
+impl Foo {
+    pub fn method$0() {}
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
+        );
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo;
+impl Foo {
+    const CONST$0: () = ();
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_impl_trait_assoc() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo;
+pub trait Trait {
+    fn method() {}
+}
+impl Trait for Foo {
+    pub fn method$0() {}
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
+        );
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo;
+pub trait Trait {
+    const CONST: () = ();
+}
+impl Trait for Foo {
+    const CONST$0: () = ();
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
+        );
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo;
+pub trait Trait {
+    type Type;
+}
+impl Trait for Foo {
+    type Type$0 = ();
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedtype.Type"##]],
+        );
+    }
+
+    #[test]
+    fn external_docs_doc_url_trait_assoc() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub trait Foo {
+    fn method$0();
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#tymethod.method"##]],
+        );
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub trait Foo {
+    const CONST$0: ();
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedconstant.CONST"##]],
+        );
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub trait Foo {
+    type Type$0;
+}
+"#,
+            expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedtype.Type"##]],
+        );
+    }
+
+    #[test]
+    fn external_docs_trait() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+trait Trait$0 {}
+"#,
+            expect![[r#"https://docs.rs/foo/*/foo/trait.Trait.html"#]],
+        )
+    }
+
+    #[test]
+    fn external_docs_module() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub mod foo {
+    pub mod ba$0r {}
+}
+"#,
+            expect![[r#"https://docs.rs/foo/*/foo/foo/bar/index.html"#]],
+        )
+    }
+
+    #[test]
+    fn external_docs_reexport_order() {
+        check_external_docs(
+            r#"
+//- /main.rs crate:foo
+pub mod wrapper {
+    pub use module::Item;
+
+    pub mod module {
+        pub struct Item;
+    }
+}
+
+fn foo() {
+    let bar: wrapper::It$0em;
+}
+        "#,
+            expect![[r#"https://docs.rs/foo/*/foo/wrapper/module/struct.Item.html"#]],
+        )
+    }
+
+    #[test]
+    fn test_trait_items() {
+        check_doc_links(
+            r#"
+/// [`Trait`]
+/// [`Trait::Type`]
+/// [`Trait::CONST`]
+/// [`Trait::func`]
+trait Trait$0 {
+   // ^^^^^ Trait
+    type Type;
+      // ^^^^ Trait::Type
+    const CONST: usize;
+       // ^^^^^ Trait::CONST
+    fn func();
+    // ^^^^ Trait::func
+}
+        "#,
+        )
+    }
+
+    #[test]
+    fn rewrite_html_root_url() {
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+#![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)]
+
+pub mod foo {
+    pub struct Foo;
+}
+/// [Foo](foo::Foo)
+pub struct B$0ar
+"#,
+            expect![[r#"[Foo](https://example.com/foo/foo/struct.Foo.html)"#]],
+        );
+    }
+
+    #[test]
+    fn rewrite_on_field() {
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+pub struct Foo {
+    /// [Foo](struct.Foo.html)
+    fie$0ld: ()
+}
+"#,
+            expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+    }
+
+    #[test]
+    fn rewrite_struct() {
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+/// [Foo]
+pub struct $0Foo;
+"#,
+            expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+/// [`Foo`]
+pub struct $0Foo;
+"#,
+            expect![[r#"[`Foo`](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+/// [Foo](struct.Foo.html)
+pub struct $0Foo;
+"#,
+            expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+/// [struct Foo](struct.Foo.html)
+pub struct $0Foo;
+"#,
+            expect![[r#"[struct Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+        check_rewrite(
+            r#"
+//- /main.rs crate:foo
+/// [my Foo][foo]
+///
+/// [foo]: Foo
+pub struct $0Foo;
+"#,
+            expect![[r#"[my Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
+        );
+    }
+
+    fn check_external_docs(ra_fixture: &str, expect: Expect) {
+        let (analysis, position) = fixture::position(ra_fixture);
+        let url = analysis.external_docs(position).unwrap().expect("could not find url for symbol");
+
+        expect.assert_eq(&url)
+    }
+
+    fn check_rewrite(ra_fixture: &str, expect: Expect) {
+        let (analysis, position) = fixture::position(ra_fixture);
+        let sema = &Semantics::new(&*analysis.db);
+        let (cursor_def, docs) = def_under_cursor(sema, &position);
+        let res = rewrite_links(sema.db, docs.as_str(), cursor_def);
+        expect.assert_eq(&res)
+    }
+
+    fn check_doc_links(ra_fixture: &str) {
+        let key_fn = |&(FileRange { file_id, range }, _): &_| (file_id, range.start());
+
+        let (analysis, position, mut expected) = fixture::annotations(ra_fixture);
+        expected.sort_by_key(key_fn);
+        let sema = &Semantics::new(&*analysis.db);
+        let (cursor_def, docs) = def_under_cursor(sema, &position);
+        let defs = extract_definitions_from_docs(&docs);
+        let actual: Vec<_> = defs
+            .into_iter()
+            .map(|(_, link, ns)| {
+                let def = resolve_doc_path_for_def(sema.db, cursor_def, &link, ns)
+                    .unwrap_or_else(|| panic!("Failed to resolve {}", link));
+                let nav_target = def.try_to_nav(sema.db).unwrap();
+                let range = FileRange {
+                    file_id: nav_target.file_id,
+                    range: nav_target.focus_or_full_range(),
+                };
+                (range, link)
+            })
+            .sorted_by_key(key_fn)
+            .collect();
+        assert_eq!(expected, actual);
+    }
+
+    fn def_under_cursor(
+        sema: &Semantics<RootDatabase>,
+        position: &FilePosition,
+    ) -> (Definition, hir::Documentation) {
+        let (docs, def) = sema
+            .parse(position.file_id)
+            .syntax()
+            .token_at_offset(position.offset)
+            .left_biased()
+            .unwrap()
+            .ancestors()
+            .find_map(|it| node_to_def(sema, &it))
+            .expect("no def found")
+            .unwrap();
+        let docs = docs.expect("no docs found for cursor def");
+        (def, docs)
+    }
+
+    fn node_to_def(
+        sema: &Semantics<RootDatabase>,
+        node: &SyntaxNode,
+    ) -> Option<Option<(Option<hir::Documentation>, Definition)>> {
+        Some(match_ast! {
+            match node {
+                ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
+                ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
+                ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Function(def))),
+                ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
+                ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Union(def)))),
+                ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
+                ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Variant(def))),
+                ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Trait(def))),
+                ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Static(def))),
+                ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Const(def))),
+                ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::TypeAlias(def))),
+                ast::Impl(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::SelfType(def))),
+                ast::RecordField(it) => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
+                ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
+                ast::Macro(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Macro(def))),
+                // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))),
+                _ => return None,
+            }
+        })
+    }
+}
diff --git a/crates/ide_assists/src/handlers/number_representation.rs b/crates/ide_assists/src/handlers/number_representation.rs
deleted file mode 100644
index df01763663..0000000000
--- a/crates/ide_assists/src/handlers/number_representation.rs
+++ /dev/null
@@ -1,183 +0,0 @@
-use syntax::{ast, ast::Radix, AstToken};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
-
-const MIN_NUMBER_OF_DIGITS_TO_FORMAT: usize = 5;
-
-// Assist: reformat_number_literal
-//
-// Adds or removes seprators from integer literal.
-//
-// ```
-// const _: i32 = 1012345$0;
-// ```
-// ->
-// ```
-// const _: i32 = 1_012_345;
-// ```
-pub(crate) fn reformat_number_literal(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let literal = ctx.find_node_at_offset::<ast::Literal>()?;
-    let literal = match literal.kind() {
-        ast::LiteralKind::IntNumber(it) => it,
-        _ => return None,
-    };
-
-    let text = literal.text();
-    if text.contains('_') {
-        return remove_separators(acc, literal);
-    }
-
-    let (prefix, value, suffix) = literal.split_into_parts();
-    if value.len() < MIN_NUMBER_OF_DIGITS_TO_FORMAT {
-        return None;
-    }
-
-    let radix = literal.radix();
-    let mut converted = prefix.to_string();
-    converted.push_str(&add_group_separators(value, group_size(radix)));
-    converted.push_str(suffix);
-
-    let group_id = GroupLabel("Reformat number literal".into());
-    let label = format!("Convert {} to {}", literal, converted);
-    let range = literal.syntax().text_range();
-    acc.add_group(
-        &group_id,
-        AssistId("reformat_number_literal", AssistKind::RefactorInline),
-        label,
-        range,
-        |builder| builder.replace(range, converted),
-    )
-}
-
-fn remove_separators(acc: &mut Assists, literal: ast::IntNumber) -> Option<()> {
-    let group_id = GroupLabel("Reformat number literal".into());
-    let range = literal.syntax().text_range();
-    acc.add_group(
-        &group_id,
-        AssistId("reformat_number_literal", AssistKind::RefactorInline),
-        "Remove digit seprators",
-        range,
-        |builder| builder.replace(range, literal.text().replace("_", "")),
-    )
-}
-
-const fn group_size(r: Radix) -> usize {
-    match r {
-        Radix::Binary => 4,
-        Radix::Octal => 3,
-        Radix::Decimal => 3,
-        Radix::Hexadecimal => 4,
-    }
-}
-
-fn add_group_separators(s: &str, group_size: usize) -> String {
-    let mut chars = Vec::new();
-    for (i, ch) in s.chars().filter(|&ch| ch != '_').rev().enumerate() {
-        if i > 0 && i % group_size == 0 {
-            chars.push('_');
-        }
-        chars.push(ch);
-    }
-
-    chars.into_iter().rev().collect()
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist_by_label, check_assist_not_applicable, check_assist_target};
-
-    use super::*;
-
-    #[test]
-    fn group_separators() {
-        let cases = vec![
-            ("", 4, ""),
-            ("1", 4, "1"),
-            ("12", 4, "12"),
-            ("123", 4, "123"),
-            ("1234", 4, "1234"),
-            ("12345", 4, "1_2345"),
-            ("123456", 4, "12_3456"),
-            ("1234567", 4, "123_4567"),
-            ("12345678", 4, "1234_5678"),
-            ("123456789", 4, "1_2345_6789"),
-            ("1234567890", 4, "12_3456_7890"),
-            ("1_2_3_4_5_6_7_8_9_0_", 4, "12_3456_7890"),
-            ("1234567890", 3, "1_234_567_890"),
-            ("1234567890", 2, "12_34_56_78_90"),
-            ("1234567890", 1, "1_2_3_4_5_6_7_8_9_0"),
-        ];
-
-        for case in cases {
-            let (input, group_size, expected) = case;
-            assert_eq!(add_group_separators(input, group_size), expected)
-        }
-    }
-
-    #[test]
-    fn good_targets() {
-        let cases = vec![
-            ("const _: i32 = 0b11111$0", "0b11111"),
-            ("const _: i32 = 0o77777$0;", "0o77777"),
-            ("const _: i32 = 10000$0;", "10000"),
-            ("const _: i32 = 0xFFFFF$0;", "0xFFFFF"),
-            ("const _: i32 = 10000i32$0;", "10000i32"),
-            ("const _: i32 = 0b_10_0i32$0;", "0b_10_0i32"),
-        ];
-
-        for case in cases {
-            check_assist_target(reformat_number_literal, case.0, case.1);
-        }
-    }
-
-    #[test]
-    fn bad_targets() {
-        let cases = vec![
-            "const _: i32 = 0b111$0",
-            "const _: i32 = 0b1111$0",
-            "const _: i32 = 0o77$0;",
-            "const _: i32 = 0o777$0;",
-            "const _: i32 = 10$0;",
-            "const _: i32 = 999$0;",
-            "const _: i32 = 0xFF$0;",
-            "const _: i32 = 0xFFFF$0;",
-        ];
-
-        for case in cases {
-            check_assist_not_applicable(reformat_number_literal, case);
-        }
-    }
-
-    #[test]
-    fn labels() {
-        let cases = vec![
-            ("const _: i32 = 10000$0", "const _: i32 = 10_000", "Convert 10000 to 10_000"),
-            (
-                "const _: i32 = 0xFF0000$0;",
-                "const _: i32 = 0xFF_0000;",
-                "Convert 0xFF0000 to 0xFF_0000",
-            ),
-            (
-                "const _: i32 = 0b11111111$0;",
-                "const _: i32 = 0b1111_1111;",
-                "Convert 0b11111111 to 0b1111_1111",
-            ),
-            (
-                "const _: i32 = 0o377211$0;",
-                "const _: i32 = 0o377_211;",
-                "Convert 0o377211 to 0o377_211",
-            ),
-            (
-                "const _: i32 = 10000i32$0;",
-                "const _: i32 = 10_000i32;",
-                "Convert 10000i32 to 10_000i32",
-            ),
-            ("const _: i32 = 1_0_0_0_i32$0;", "const _: i32 = 1000i32;", "Remove digit seprators"),
-        ];
-
-        for case in cases {
-            let (before, after, label) = case;
-            check_assist_by_label(reformat_number_literal, before, after, label);
-        }
-    }
-}
diff --git a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
index 2c540dc80d..6b196681ca 100644
--- a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -102,10 +102,10 @@ fn shorten_paths(node: &SyntaxNode, path: &ast::Path) {
             match child {
                 // Don't modify `use` items, as this can break the `use` item when injecting a new
                 // import into the use tree.
-                ast::Use(_) => continue,
+                ast::Use(_it) => continue,
                 // Don't descend into submodules, they don't have the same `use` items in scope.
                 // FIXME: This isn't true due to `super::*` imports?
-                ast::Module(_) => continue,
+                ast::Module(_it) => continue,
                 ast::Path(p) => if maybe_replace_path(p.clone(), path.clone()).is_none() {
                     shorten_paths(p.syntax(), path);
                 },
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 067f4d8e14..a1dfa065ff 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -159,7 +159,6 @@ mod handlers {
     mod move_module_to_file;
     mod move_to_mod_rs;
     mod move_from_mod_rs;
-    mod number_representation;
     mod promote_local_to_const;
     mod pull_assignment_up;
     mod qualify_path;
@@ -242,7 +241,6 @@ mod handlers {
             move_module_to_file::move_module_to_file,
             move_to_mod_rs::move_to_mod_rs,
             move_from_mod_rs::move_from_mod_rs,
-            number_representation::reformat_number_literal,
             pull_assignment_up::pull_assignment_up,
             promote_local_to_const::promote_local_to_const,
             qualify_path::qualify_path,
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index c6af285e86..d459e51161 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -517,7 +517,7 @@ impl<'a> CompletionContext<'a> {
 
                         (ty, name)
                     },
-                    ast::ArgList(_) => {
+                    ast::ArgList(_it) => {
                         cov_mark::hit!(expected_type_fn_param);
                         ActiveParameter::at_token(
                             &self.sema,
@@ -608,9 +608,9 @@ impl<'a> CompletionContext<'a> {
                             .map(|c| (Some(c.return_type()), None))
                             .unwrap_or((None, None))
                     },
-                    ast::ParamList(_) => (None, None),
-                    ast::Stmt(_) => (None, None),
-                    ast::Item(_) => (None, None),
+                    ast::ParamList(__) => (None, None),
+                    ast::Stmt(__) => (None, None),
+                    ast::Item(__) => (None, None),
                     _ => {
                         match node.parent() {
                             Some(n) => {
@@ -702,10 +702,10 @@ impl<'a> CompletionContext<'a> {
 
         Some(match_ast! {
             match parent {
-                ast::LifetimeParam(_) => LifetimeContext::LifetimeParam(sema.find_node_at_offset_with_macros(original_file, offset)),
-                ast::BreakExpr(_) => LifetimeContext::LabelRef,
-                ast::ContinueExpr(_) => LifetimeContext::LabelRef,
-                ast::Label(_) => LifetimeContext::LabelDef,
+                ast::LifetimeParam(_it) => LifetimeContext::LifetimeParam(sema.find_node_at_offset_with_macros(original_file, offset)),
+                ast::BreakExpr(_it) => LifetimeContext::LabelRef,
+                ast::ContinueExpr(_it) => LifetimeContext::LabelRef,
+                ast::Label(_it) => LifetimeContext::LabelDef,
                 _ => LifetimeContext::Lifetime,
             }
         })
@@ -753,7 +753,7 @@ impl<'a> CompletionContext<'a> {
         path_ctx.kind  = path.syntax().ancestors().find_map(|it| {
             match_ast! {
                 match it {
-                    ast::PathType(_) => Some(PathKind::Type),
+                    ast::PathType(_it) => Some(PathKind::Type),
                     ast::PathExpr(it) => {
                         path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
                         Some(PathKind::Expr)
@@ -772,9 +772,9 @@ impl<'a> CompletionContext<'a> {
                         Some(PathKind::Pat)
                     },
                     ast::MacroCall(it) => it.excl_token().and(Some(PathKind::Mac)),
-                    ast::Meta(_) => Some(PathKind::Attr),
+                    ast::Meta(_it) => Some(PathKind::Attr),
                     ast::Visibility(it) => Some(PathKind::Vis { has_in_token: it.in_token().is_some() }),
-                    ast::UseTree(_) => Some(PathKind::Use),
+                    ast::UseTree(_it) => Some(PathKind::Use),
                     _ => None,
                 }
             }
@@ -851,9 +851,9 @@ fn pattern_context_for(pat: ast::Pat) -> PatternContext {
                         });
                         return (PatternRefutability::Irrefutable, param.ty().is_some())
                     },
-                    ast::MatchArm(_) => PatternRefutability::Refutable,
-                    ast::Condition(_) => PatternRefutability::Refutable,
-                    ast::ForExpr(_) => PatternRefutability::Irrefutable,
+                    ast::MatchArm(__) => PatternRefutability::Refutable,
+                    ast::Condition(__) => PatternRefutability::Refutable,
+                    ast::ForExpr(__) => PatternRefutability::Irrefutable,
                     _ => PatternRefutability::Irrefutable,
                 }
             };
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index 41e2423f46..b50f76b911 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -100,7 +100,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
         let res = match_ast! {
             match prev_sibling {
                 // vis followed by random ident will always error the parser
-                ast::Visibility(_) => ImmediatePrevSibling::Visibility,
+                ast::Visibility(_it) => ImmediatePrevSibling::Visibility,
                 _ => return None,
             }
         };
@@ -112,7 +112,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
                 let node = it.expr().filter(|_| it.semicolon_token().is_none())?.syntax().clone();
                 match_ast! {
                     match node {
-                        ast::IfExpr(_) => ImmediatePrevSibling::IfExpr,
+                        ast::IfExpr(_it) => ImmediatePrevSibling::IfExpr,
                         _ => return None,
                     }
                 }
@@ -128,7 +128,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
                 } else {
                     return None
             },
-            ast::Attr(_) => ImmediatePrevSibling::Attribute,
+            ast::Attr(_it) => ImmediatePrevSibling::Attribute,
             _ => return None,
         }
     };
@@ -200,31 +200,31 @@ pub(crate) fn determine_location(
 
     let res = match_ast! {
         match parent {
-            ast::IdentPat(_) => ImmediateLocation::IdentPat,
-            ast::Rename(_) => ImmediateLocation::Rename,
-            ast::StmtList(_) => ImmediateLocation::StmtList,
-            ast::SourceFile(_) => ImmediateLocation::ItemList,
-            ast::ItemList(_) => ImmediateLocation::ItemList,
-            ast::RefExpr(_) => ImmediateLocation::RefExpr,
-            ast::Variant(_) => ImmediateLocation::Variant,
+            ast::IdentPat(_it) => ImmediateLocation::IdentPat,
+            ast::Rename(_it) => ImmediateLocation::Rename,
+            ast::StmtList(_it) => ImmediateLocation::StmtList,
+            ast::SourceFile(_it) => ImmediateLocation::ItemList,
+            ast::ItemList(_it) => ImmediateLocation::ItemList,
+            ast::RefExpr(_it) => ImmediateLocation::RefExpr,
+            ast::Variant(_it) => ImmediateLocation::Variant,
             ast::RecordField(it) => if it.ty().map_or(false, |it| it.syntax().text_range().contains(offset)) {
                 return None;
             } else {
                 ImmediateLocation::RecordField
             },
-            ast::RecordExprFieldList(_) => sema
+            ast::RecordExprFieldList(_it) => sema
                 .find_node_at_offset_with_macros(original_file, offset)
                 .map(ImmediateLocation::RecordExprUpdate)?,
-            ast::TupleField(_) => ImmediateLocation::TupleField,
-            ast::TupleFieldList(_) => ImmediateLocation::TupleField,
-            ast::TypeBound(_) => ImmediateLocation::TypeBound,
-            ast::TypeBoundList(_) => ImmediateLocation::TypeBound,
+            ast::TupleField(_it) => ImmediateLocation::TupleField,
+            ast::TupleFieldList(_it) => ImmediateLocation::TupleField,
+            ast::TypeBound(_it) => ImmediateLocation::TypeBound,
+            ast::TypeBoundList(_it) => ImmediateLocation::TypeBound,
             ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) {
                 Some(IMPL) => ImmediateLocation::Impl,
                 Some(TRAIT) => ImmediateLocation::Trait,
                 _ => return None,
             },
-            ast::GenericArgList(_) => sema
+            ast::GenericArgList(_it) => sema
                 .find_node_at_offset_with_macros(original_file, offset)
                 .map(ImmediateLocation::GenericArgList)?,
             ast::Module(it) => {
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 30ebf7828a..ef2f0f940f 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -447,7 +447,7 @@ impl NameRefClass {
             }
         }
 
-        if let Some(path) = ast::PathSegment::cast(parent.clone()).map(|it| it.parent_path()) {
+        if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
             if path.qualifier().is_none() {
                 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
                     // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 0d0f7b78d8..c23a9ee257 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -657,7 +657,7 @@ impl ReferenceCategory {
 
         let mode = r.syntax().ancestors().find_map(|node| {
         match_ast! {
-            match node {
+            match (node) {
                 ast::BinExpr(expr) => {
                     if matches!(expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
                         // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index c32ab686cc..1fb7f158f2 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -623,38 +623,41 @@ impl ast::IntNumber {
         }
     }
 
-    pub fn split_into_parts(&self) -> (&str, &str, &str) {
-        let radix = self.radix();
-        let (prefix, mut text) = self.text().split_at(radix.prefix_len());
+    pub fn value(&self) -> Option<u128> {
+        let token = self.syntax();
 
-        let is_suffix_start: fn(&(usize, char)) -> bool = match radix {
-            Radix::Hexadecimal => |(_, c)| matches!(c, 'g'..='z' | 'G'..='Z'),
-            _ => |(_, c)| c.is_ascii_alphabetic(),
-        };
+        let mut text = token.text();
+        if let Some(suffix) = self.suffix() {
+            text = &text[..text.len() - suffix.len()];
+        }
 
-        let mut suffix = "";
-        if let Some((suffix_start, _)) = text.char_indices().find(is_suffix_start) {
-            let (text2, suffix2) = text.split_at(suffix_start);
-            text = text2;
-            suffix = suffix2;
-        };
+        let radix = self.radix();
+        text = &text[radix.prefix_len()..];
 
-        (prefix, text, suffix)
-    }
+        let buf;
+        if text.contains('_') {
+            buf = text.replace('_', "");
+            text = buf.as_str();
+        };
 
-    pub fn value(&self) -> Option<u128> {
-        let (_, text, _) = self.split_into_parts();
-        let value = u128::from_str_radix(&text.replace("_", ""), self.radix() as u32).ok()?;
+        let value = u128::from_str_radix(text, radix as u32).ok()?;
         Some(value)
     }
 
     pub fn suffix(&self) -> Option<&str> {
-        let (_, _, suffix) = self.split_into_parts();
-        if suffix.is_empty() {
-            None
-        } else {
-            Some(suffix)
+        let text = self.text();
+        let radix = self.radix();
+        let mut indices = text.char_indices();
+        if radix != Radix::Decimal {
+            indices.next()?;
+            indices.next()?;
         }
+        let is_suffix_start: fn(&(usize, char)) -> bool = match radix {
+            Radix::Hexadecimal => |(_, c)| matches!(c, 'g'..='z' | 'G'..='Z'),
+            _ => |(_, c)| c.is_ascii_alphabetic(),
+        };
+        let (suffix_start, _) = indices.find(is_suffix_start)?;
+        Some(&text[suffix_start..])
     }
 }
 
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index ec281625a6..24a099cb3c 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -242,7 +242,7 @@ macro_rules! match_ast {
     (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
 
     (match ($node:expr) {
-        $( ast::$ast:ident($it:pat) => $res:expr, )*
+        $( ast::$ast:ident($it:ident) => $res:expr, )*
         _ => $catch_all:expr $(,)?
     }) => {{
         $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 8dc47e0bd3..a0a0bab5b3 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -275,7 +275,7 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
                             return Some(tree_path);
                         }
                     },
-                    ast::UseTreeList(_) => continue,
+                    ast::UseTreeList(_it) => continue,
                     ast::Path(parent) => path = parent,
                     _ => return None,
                 }


Test patch:
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 9c0c00da3b..731605ced1 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -84,37 +84,6 @@ fn infer_associated_method_struct() {
     );
 }
 
-#[test]
-fn infer_associated_method_struct_in_local_scope() {
-    check_infer(
-        r#"
-        fn mismatch() {
-            struct A;
-
-            impl A {
-                fn from(_: i32, _: i32) -> Self {
-                    A
-                }
-            }
-
-            let _a = A::from(1, 2);
-        }
-        "#,
-        expect![[r#"
-            14..146 '{     ... 2); }': ()
-            125..127 '_a': A
-            130..137 'A::from': fn from(i32, i32) -> A
-            130..143 'A::from(1, 2)': A
-            138..139 '1': i32
-            141..142 '2': i32
-            60..61 '_': i32
-            68..69 '_': i32
-            84..109 '{     ...     }': A
-            98..99 'A': A
-        "#]],
-    );
-}
-
 #[test]
 fn infer_associated_method_enum() {
     check_infer(
@@ -308,7 +277,7 @@ fn test() {
 pub mod foo {
     pub struct S;
     impl S {
-        pub fn thing() -> i128 { 0 }
+        fn thing() -> i128 { 0 }
     }
 }
 "#,
diff --git a/crates/ide/src/doc_links/tests.rs b/crates/ide/src/doc_links/tests.rs
deleted file mode 100644
index 27a70b18aa..0000000000
--- a/crates/ide/src/doc_links/tests.rs
+++ /dev/null
@@ -1,411 +0,0 @@
-use expect_test::{expect, Expect};
-use hir::{HasAttrs, Semantics};
-use ide_db::{
-    base_db::{FilePosition, FileRange},
-    defs::Definition,
-    RootDatabase,
-};
-use itertools::Itertools;
-use syntax::{ast, match_ast, AstNode, SyntaxNode};
-
-use crate::{
-    doc_links::{extract_definitions_from_docs, resolve_doc_path_for_def, rewrite_links},
-    fixture, TryToNav,
-};
-
-fn check_external_docs(ra_fixture: &str, expect: Expect) {
-    let (analysis, position) = fixture::position(ra_fixture);
-    let url = analysis.external_docs(position).unwrap().expect("could not find url for symbol");
-
-    expect.assert_eq(&url)
-}
-
-fn check_rewrite(ra_fixture: &str, expect: Expect) {
-    let (analysis, position) = fixture::position(ra_fixture);
-    let sema = &Semantics::new(&*analysis.db);
-    let (cursor_def, docs) = def_under_cursor(sema, &position);
-    let res = rewrite_links(sema.db, docs.as_str(), cursor_def);
-    expect.assert_eq(&res)
-}
-
-fn check_doc_links(ra_fixture: &str) {
-    let key_fn = |&(FileRange { file_id, range }, _): &_| (file_id, range.start());
-
-    let (analysis, position, mut expected) = fixture::annotations(ra_fixture);
-    expected.sort_by_key(key_fn);
-    let sema = &Semantics::new(&*analysis.db);
-    let (cursor_def, docs) = def_under_cursor(sema, &position);
-    let defs = extract_definitions_from_docs(&docs);
-    let actual: Vec<_> = defs
-        .into_iter()
-        .map(|(_, link, ns)| {
-            let def = resolve_doc_path_for_def(sema.db, cursor_def, &link, ns)
-                .unwrap_or_else(|| panic!("Failed to resolve {}", link));
-            let nav_target = def.try_to_nav(sema.db).unwrap();
-            let range =
-                FileRange { file_id: nav_target.file_id, range: nav_target.focus_or_full_range() };
-            (range, link)
-        })
-        .sorted_by_key(key_fn)
-        .collect();
-    assert_eq!(expected, actual);
-}
-
-fn def_under_cursor(
-    sema: &Semantics<RootDatabase>,
-    position: &FilePosition,
-) -> (Definition, hir::Documentation) {
-    let (docs, def) = sema
-        .parse(position.file_id)
-        .syntax()
-        .token_at_offset(position.offset)
-        .left_biased()
-        .unwrap()
-        .ancestors()
-        .find_map(|it| node_to_def(sema, &it))
-        .expect("no def found")
-        .unwrap();
-    let docs = docs.expect("no docs found for cursor def");
-    (def, docs)
-}
-
-fn node_to_def(
-    sema: &Semantics<RootDatabase>,
-    node: &SyntaxNode,
-) -> Option<Option<(Option<hir::Documentation>, Definition)>> {
-    Some(match_ast! {
-        match node {
-            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
-            ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
-            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Function(def))),
-            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
-            ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Union(def)))),
-            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
-            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Variant(def))),
-            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Trait(def))),
-            ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Static(def))),
-            ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Const(def))),
-            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::TypeAlias(def))),
-            ast::Impl(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::SelfType(def))),
-            ast::RecordField(it) => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
-            ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
-            ast::Macro(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Macro(def))),
-            // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))),
-            _ => return None,
-        }
-    })
-}
-
-#[test]
-fn external_docs_doc_url_crate() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:main deps:foo
-use foo$0::Foo;
-//- /lib.rs crate:foo
-pub struct Foo;
-"#,
-        expect![[r#"https://docs.rs/foo/*/foo/index.html"#]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_std_crate() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:std
-use self$0;
-"#,
-        expect![[r#"https://doc.rust-lang.org/nightly/std/index.html"#]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_struct() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Fo$0o;
-"#,
-        expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_struct_field() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo {
-    field$0: ()
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#structfield.field"##]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_fn() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub fn fo$0o() {}
-"#,
-        expect![[r#"https://docs.rs/foo/*/foo/fn.foo.html"#]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_impl_assoc() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo;
-impl Foo {
-    pub fn method$0() {}
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
-    );
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo;
-impl Foo {
-    const CONST$0: () = ();
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_impl_trait_assoc() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo;
-pub trait Trait {
-    fn method() {}
-}
-impl Trait for Foo {
-    pub fn method$0() {}
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#method.method"##]],
-    );
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo;
-pub trait Trait {
-    const CONST: () = ();
-}
-impl Trait for Foo {
-    const CONST$0: () = ();
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.CONST"##]],
-    );
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo;
-pub trait Trait {
-    type Type;
-}
-impl Trait for Foo {
-    type Type$0 = ();
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/struct.Foo.html#associatedtype.Type"##]],
-    );
-}
-
-#[test]
-fn external_docs_doc_url_trait_assoc() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub trait Foo {
-    fn method$0();
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#tymethod.method"##]],
-    );
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub trait Foo {
-    const CONST$0: ();
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedconstant.CONST"##]],
-    );
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub trait Foo {
-    type Type$0;
-}
-"#,
-        expect![[r##"https://docs.rs/foo/*/foo/trait.Foo.html#associatedtype.Type"##]],
-    );
-}
-
-#[test]
-fn external_docs_trait() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-trait Trait$0 {}
-"#,
-        expect![[r#"https://docs.rs/foo/*/foo/trait.Trait.html"#]],
-    )
-}
-
-#[test]
-fn external_docs_module() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub mod foo {
-    pub mod ba$0r {}
-}
-"#,
-        expect![[r#"https://docs.rs/foo/*/foo/foo/bar/index.html"#]],
-    )
-}
-
-#[test]
-fn external_docs_reexport_order() {
-    check_external_docs(
-        r#"
-//- /main.rs crate:foo
-pub mod wrapper {
-    pub use module::Item;
-
-    pub mod module {
-        pub struct Item;
-    }
-}
-
-fn foo() {
-    let bar: wrapper::It$0em;
-}
-        "#,
-        expect![[r#"https://docs.rs/foo/*/foo/wrapper/module/struct.Item.html"#]],
-    )
-}
-
-#[test]
-fn test_trait_items() {
-    check_doc_links(
-        r#"
-/// [`Trait`]
-/// [`Trait::Type`]
-/// [`Trait::CONST`]
-/// [`Trait::func`]
-trait Trait$0 {
-   // ^^^^^ Trait
-    type Type;
-      // ^^^^ Trait::Type
-    const CONST: usize;
-       // ^^^^^ Trait::CONST
-    fn func();
-    // ^^^^ Trait::func
-}
-        "#,
-    )
-}
-
-#[test]
-fn rewrite_html_root_url() {
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-#![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)]
-
-pub mod foo {
-    pub struct Foo;
-}
-/// [Foo](foo::Foo)
-pub struct B$0ar
-"#,
-        expect![[r#"[Foo](https://example.com/foo/foo/struct.Foo.html)"#]],
-    );
-}
-
-#[test]
-fn rewrite_on_field() {
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-pub struct Foo {
-    /// [Foo](struct.Foo.html)
-    fie$0ld: ()
-}
-"#,
-        expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-}
-
-#[test]
-fn rewrite_struct() {
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [Foo]
-pub struct $0Foo;
-"#,
-        expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [`Foo`]
-pub struct $0Foo;
-"#,
-        expect![[r#"[`Foo`](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [Foo](struct.Foo.html)
-pub struct $0Foo;
-"#,
-        expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [struct Foo](struct.Foo.html)
-pub struct $0Foo;
-"#,
-        expect![[r#"[struct Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [my Foo][foo]
-///
-/// [foo]: Foo
-pub struct $0Foo;
-"#,
-        expect![[r#"[my Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
-    );
-    // FIXME #11008
-    check_rewrite(
-        r#"
-//- /main.rs crate:foo
-/// [`foo`]
-///
-/// [`foo`]: Foo
-pub struct $0Foo;
-"#,
-        expect![[r#"
-            [`foo`]
-
-            []: https://docs.rs/foo/*/foo/struct.Foo.html"#]],
-    );
-}
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 28dd2afa02..f1d7d2791d 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -823,10 +823,10 @@ fn test_hover_infer_associated_method_exact() {
     check(
         r#"
 mod wrapper {
-    pub struct Thing { x: u32 }
+    struct Thing { x: u32 }
 
     impl Thing {
-        pub fn new() -> Thing { Thing { x: 0 } }
+        fn new() -> Thing { Thing { x: 0 } }
     }
 }
 
@@ -840,9 +840,9 @@ fn main() { let foo_test = wrapper::Thing::new$0(); }
                 ```
 
                 ```rust
-                pub fn new() -> Thing
+                fn new() -> Thing
                 ```
-        "#]],
+            "#]],
     )
 }
 
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index ab5ef91657..c67e15b2ce 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -1607,19 +1607,6 @@ pub mod std { pub mod collections { pub struct HashMap { } } }
     )
 }
 
-#[test]
-fn doctest_reformat_number_literal() {
-    check_doc_test(
-        "reformat_number_literal",
-        r#####"
-const _: i32 = 1012345$0;
-"#####,
-        r#####"
-const _: i32 = 1_012_345;
-"#####,
-    )
-}
-
 #[test]
 fn doctest_remove_dbg() {
     check_doc_test(