summaryrefslogtreecommitdiffstats
path: root/src/test/rustdoc-js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/rustdoc-js
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/rustdoc-js-std/alias-1.js7
-rw-r--r--src/test/rustdoc-js-std/alias-2.js10
-rw-r--r--src/test/rustdoc-js-std/alias-3.js7
-rw-r--r--src/test/rustdoc-js-std/alias-4.js7
-rw-r--r--src/test/rustdoc-js-std/alias.js11
-rw-r--r--src/test/rustdoc-js-std/asrawfd.js14
-rw-r--r--src/test/rustdoc-js-std/basic.js15
-rw-r--r--src/test/rustdoc-js-std/deduplication.js11
-rw-r--r--src/test/rustdoc-js-std/enum-option.js7
-rw-r--r--src/test/rustdoc-js-std/filter-crate.js9
-rw-r--r--src/test/rustdoc-js-std/fn-forget.js8
-rw-r--r--src/test/rustdoc-js-std/from_u.js9
-rw-r--r--src/test/rustdoc-js-std/keyword.js10
-rw-r--r--src/test/rustdoc-js-std/macro-check.js10
-rw-r--r--src/test/rustdoc-js-std/macro-print.js10
-rw-r--r--src/test/rustdoc-js-std/never.js7
-rw-r--r--src/test/rustdoc-js-std/parser-errors.js385
-rw-r--r--src/test/rustdoc-js-std/parser-filter.js43
-rw-r--r--src/test/rustdoc-js-std/parser-generics.js62
-rw-r--r--src/test/rustdoc-js-std/parser-ident.js93
-rw-r--r--src/test/rustdoc-js-std/parser-literal.js27
-rw-r--r--src/test/rustdoc-js-std/parser-paths.js90
-rw-r--r--src/test/rustdoc-js-std/parser-quote.js87
-rw-r--r--src/test/rustdoc-js-std/parser-returned.js99
-rw-r--r--src/test/rustdoc-js-std/parser-separators.js206
-rw-r--r--src/test/rustdoc-js-std/parser-weird-queries.js123
-rw-r--r--src/test/rustdoc-js-std/path-ordering.js12
-rw-r--r--src/test/rustdoc-js-std/primitive.js75
-rw-r--r--src/test/rustdoc-js-std/quoted.js21
-rw-r--r--src/test/rustdoc-js-std/return-specific-literal.js10
-rw-r--r--src/test/rustdoc-js-std/return-specific.js10
-rw-r--r--src/test/rustdoc-js-std/should-fail.js9
-rw-r--r--src/test/rustdoc-js-std/string-from_ut.js11
-rw-r--r--src/test/rustdoc-js-std/struct-vec.js8
-rw-r--r--src/test/rustdoc-js-std/typed-query.js17
-rw-r--r--src/test/rustdoc-js-std/vec-new.js9
-rw-r--r--src/test/rustdoc-js/basic.js7
-rw-r--r--src/test/rustdoc-js/basic.rs2
-rw-r--r--src/test/rustdoc-js/doc-alias-filter-out.js9
-rw-r--r--src/test/rustdoc-js/doc-alias-filter-out.rs2
-rw-r--r--src/test/rustdoc-js/doc-alias-filter.js17
-rw-r--r--src/test/rustdoc-js/doc-alias-filter.rs5
-rw-r--r--src/test/rustdoc-js/doc-alias-whitespace.js19
-rw-r--r--src/test/rustdoc-js/doc-alias-whitespace.rs2
-rw-r--r--src/test/rustdoc-js/doc-alias.js295
-rw-r--r--src/test/rustdoc-js/doc-alias.rs75
-rw-r--r--src/test/rustdoc-js/exact-match.js9
-rw-r--r--src/test/rustdoc-js/exact-match.rs68
-rw-r--r--src/test/rustdoc-js/foreign-type-path.js9
-rw-r--r--src/test/rustdoc-js/foreign-type-path.rs13
-rw-r--r--src/test/rustdoc-js/generics-impl.js57
-rw-r--r--src/test/rustdoc-js/generics-impl.rs35
-rw-r--r--src/test/rustdoc-js/generics-multi-trait.js32
-rw-r--r--src/test/rustdoc-js/generics-multi-trait.rs12
-rw-r--r--src/test/rustdoc-js/generics-trait.js23
-rw-r--r--src/test/rustdoc-js/generics-trait.rs8
-rw-r--r--src/test/rustdoc-js/generics.js73
-rw-r--r--src/test/rustdoc-js/generics.rs28
-rw-r--r--src/test/rustdoc-js/impl-trait.js51
-rw-r--r--src/test/rustdoc-js/impl-trait.rs21
-rw-r--r--src/test/rustdoc-js/module-substring.js9
-rw-r--r--src/test/rustdoc-js/module-substring.rs68
-rw-r--r--src/test/rustdoc-js/path-ordering.js14
-rw-r--r--src/test/rustdoc-js/path-ordering.rs9
-rw-r--r--src/test/rustdoc-js/primitive.js25
-rw-r--r--src/test/rustdoc-js/primitive.rs5
-rw-r--r--src/test/rustdoc-js/prototype.js16
-rw-r--r--src/test/rustdoc-js/prototype.rs4
-rw-r--r--src/test/rustdoc-js/raw-pointer.js55
-rw-r--r--src/test/rustdoc-js/raw-pointer.rs24
-rw-r--r--src/test/rustdoc-js/search-short-types.js10
-rw-r--r--src/test/rustdoc-js/search-short-types.rs74
-rw-r--r--src/test/rustdoc-js/struct-like-variant.js7
-rw-r--r--src/test/rustdoc-js/struct-like-variant.rs8
-rw-r--r--src/test/rustdoc-js/substring.js8
-rw-r--r--src/test/rustdoc-js/substring.rs21
-rw-r--r--src/test/rustdoc-js/summaries.js21
-rw-r--r--src/test/rustdoc-js/summaries.rs22
-rw-r--r--src/test/rustdoc-json/assoc_items.rs29
-rw-r--r--src/test/rustdoc-json/assoc_type.rs22
-rw-r--r--src/test/rustdoc-json/blanket_impls.rs9
-rw-r--r--src/test/rustdoc-json/doc_hidden_failure.rs22
-rw-r--r--src/test/rustdoc-json/enums/variant_struct.rs11
-rw-r--r--src/test/rustdoc-json/enums/variant_tuple_struct.rs8
-rw-r--r--src/test/rustdoc-json/fn_pointer/abi.rs25
-rw-r--r--src/test/rustdoc-json/fn_pointer/generics.rs14
-rw-r--r--src/test/rustdoc-json/fn_pointer/qualifiers.rs9
-rw-r--r--src/test/rustdoc-json/fns/abi.rs25
-rw-r--r--src/test/rustdoc-json/fns/generic_args.rs71
-rw-r--r--src/test/rustdoc-json/fns/generic_returns.rs21
-rw-r--r--src/test/rustdoc-json/fns/generics.rs26
-rw-r--r--src/test/rustdoc-json/fns/qualifiers.rs33
-rw-r--r--src/test/rustdoc-json/generic-associated-types/gats.rs44
-rw-r--r--src/test/rustdoc-json/generic_impl.rs24
-rw-r--r--src/test/rustdoc-json/glob_import.rs24
-rw-r--r--src/test/rustdoc-json/impls/blanket_with_local.rs18
-rw-r--r--src/test/rustdoc-json/keyword.rs21
-rw-r--r--src/test/rustdoc-json/lifetime/longest.rs33
-rw-r--r--src/test/rustdoc-json/lifetime/outlives.rs23
-rw-r--r--src/test/rustdoc-json/methods/abi.rs55
-rw-r--r--src/test/rustdoc-json/methods/qualifiers.rs37
-rw-r--r--src/test/rustdoc-json/nested.rs30
-rw-r--r--src/test/rustdoc-json/output_generics.rs38
-rw-r--r--src/test/rustdoc-json/primitive.rs14
-rw-r--r--src/test/rustdoc-json/primitive_overloading.rs17
-rw-r--r--src/test/rustdoc-json/primitives.rs22
-rw-r--r--src/test/rustdoc-json/reexport/auxiliary/pub-struct.rs1
-rw-r--r--src/test/rustdoc-json/reexport/glob_extern.rs18
-rw-r--r--src/test/rustdoc-json/reexport/glob_private.rs32
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod.rs17
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs20
-rw-r--r--src/test/rustdoc-json/reexport/macro.rs17
-rw-r--r--src/test/rustdoc-json/reexport/private_twice_one_inline.rs18
-rw-r--r--src/test/rustdoc-json/reexport/private_two_names.rs17
-rw-r--r--src/test/rustdoc-json/reexport/rename_private.rs14
-rw-r--r--src/test/rustdoc-json/reexport/rename_public.rs17
-rw-r--r--src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs15
-rw-r--r--src/test/rustdoc-json/reexport/simple_private.rs15
-rw-r--r--src/test/rustdoc-json/reexport/simple_public.rs18
-rw-r--r--src/test/rustdoc-json/return_private.rs15
-rw-r--r--src/test/rustdoc-json/stripped_modules.rs21
-rw-r--r--src/test/rustdoc-json/structs/plain_empty.rs6
-rw-r--r--src/test/rustdoc-json/structs/tuple.rs5
-rw-r--r--src/test/rustdoc-json/structs/unit.rs5
-rw-r--r--src/test/rustdoc-json/structs/with_generics.rs14
-rw-r--r--src/test/rustdoc-json/structs/with_primitives.rs10
-rw-r--r--src/test/rustdoc-json/traits/has_body.rs21
-rw-r--r--src/test/rustdoc-json/traits/implementors.rs19
-rw-r--r--src/test/rustdoc-json/traits/supertrait.rs26
-rw-r--r--src/test/rustdoc-json/type/dyn.rs21
-rw-r--r--src/test/rustdoc-json/type/fn_lifetime.rs28
-rw-r--r--src/test/rustdoc-json/type/generic_default.rs33
-rw-r--r--src/test/rustdoc-json/unions/impl.rs15
-rw-r--r--src/test/rustdoc-json/unions/union.rs7
134 files changed, 4011 insertions, 0 deletions
diff --git a/src/test/rustdoc-js-std/alias-1.js b/src/test/rustdoc-js-std/alias-1.js
new file mode 100644
index 000000000..7c6327fcd
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias-1.js
@@ -0,0 +1,7 @@
+const QUERY = '&';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'reference' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js
new file mode 100644
index 000000000..798fa29ef
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias-2.js
@@ -0,0 +1,10 @@
+const QUERY = '+';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::ops', 'name': 'AddAssign' },
+ { 'path': 'std::ops', 'name': 'Add' },
+ { 'path': 'core::ops', 'name': 'AddAssign' },
+ { 'path': 'core::ops', 'name': 'Add' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/alias-3.js b/src/test/rustdoc-js-std/alias-3.js
new file mode 100644
index 000000000..392b1e818
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias-3.js
@@ -0,0 +1,7 @@
+const QUERY = '!';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'never' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/alias-4.js b/src/test/rustdoc-js-std/alias-4.js
new file mode 100644
index 000000000..bf2bb4d29
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias-4.js
@@ -0,0 +1,7 @@
+const QUERY = '<';
+
+const EXPECTED = {
+ 'others': [
+ { 'name': 'Ord' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/alias.js b/src/test/rustdoc-js-std/alias.js
new file mode 100644
index 000000000..2b709c991
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias.js
@@ -0,0 +1,11 @@
+// ignore-order
+
+const QUERY = '[';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'slice' },
+ { 'path': 'std::ops', 'name': 'IndexMut' },
+ { 'path': 'std::ops', 'name': 'Index' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/asrawfd.js b/src/test/rustdoc-js-std/asrawfd.js
new file mode 100644
index 000000000..fd228a590
--- /dev/null
+++ b/src/test/rustdoc-js-std/asrawfd.js
@@ -0,0 +1,14 @@
+// ignore-order
+
+const QUERY = 'RawFd::as_raw_fd';
+
+const EXPECTED = {
+ 'others': [
+ // Reproduction test for https://github.com/rust-lang/rust/issues/78724
+ // Validate that type alias methods get the correct path.
+ { 'path': 'std::os::unix::io::AsRawFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::wasi::io::AsRawFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::unix::io::RawFd', 'name': 'as_raw_fd' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/basic.js b/src/test/rustdoc-js-std/basic.js
new file mode 100644
index 000000000..824cac710
--- /dev/null
+++ b/src/test/rustdoc-js-std/basic.js
@@ -0,0 +1,15 @@
+const QUERY = 'String';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string', 'name': 'String' },
+ { 'path': 'std::ffi', 'name': 'CString' },
+ { 'path': 'std::ffi', 'name': 'OsString' },
+ ],
+ 'in_args': [
+ { 'path': 'std::str', 'name': 'eq' },
+ ],
+ 'returned': [
+ { 'path': 'std::string::String', 'name': 'add' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/deduplication.js b/src/test/rustdoc-js-std/deduplication.js
new file mode 100644
index 000000000..f02f6cf55
--- /dev/null
+++ b/src/test/rustdoc-js-std/deduplication.js
@@ -0,0 +1,11 @@
+// ignore-order
+
+const QUERY = 'is_nan';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::f32', 'name': 'is_nan' },
+ { 'path': 'std::f64', 'name': 'is_nan' },
+ { 'path': 'std::option::Option', 'name': 'is_none' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/enum-option.js b/src/test/rustdoc-js-std/enum-option.js
new file mode 100644
index 000000000..902e09069
--- /dev/null
+++ b/src/test/rustdoc-js-std/enum-option.js
@@ -0,0 +1,7 @@
+const QUERY = 'enum:Option';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::option', 'name': 'Option' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/filter-crate.js b/src/test/rustdoc-js-std/filter-crate.js
new file mode 100644
index 000000000..b47a1fefa
--- /dev/null
+++ b/src/test/rustdoc-js-std/filter-crate.js
@@ -0,0 +1,9 @@
+// exact-check
+
+const QUERY = '"hashmap"';
+const FILTER_CRATE = 'core';
+
+const EXPECTED = {
+ 'others': [
+ ],
+};
diff --git a/src/test/rustdoc-js-std/fn-forget.js b/src/test/rustdoc-js-std/fn-forget.js
new file mode 100644
index 000000000..66a5fcaa7
--- /dev/null
+++ b/src/test/rustdoc-js-std/fn-forget.js
@@ -0,0 +1,8 @@
+const QUERY = 'fn:forget';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::mem', 'name': 'forget' },
+ { 'path': 'std::fmt', 'name': 'format' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/from_u.js b/src/test/rustdoc-js-std/from_u.js
new file mode 100644
index 000000000..e3f3cd436
--- /dev/null
+++ b/src/test/rustdoc-js-std/from_u.js
@@ -0,0 +1,9 @@
+const QUERY = 'from_u';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::char', 'name': 'from_u32' },
+ { 'path': 'std::str', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/keyword.js b/src/test/rustdoc-js-std/keyword.js
new file mode 100644
index 000000000..868ddd7b6
--- /dev/null
+++ b/src/test/rustdoc-js-std/keyword.js
@@ -0,0 +1,10 @@
+// ignore-order
+
+const QUERY = 'fn';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'fn', ty: 15 }, // 15 is for primitive types
+ { 'path': 'std', 'name': 'fn', ty: 21 }, // 21 is for keywords
+ ],
+};
diff --git a/src/test/rustdoc-js-std/macro-check.js b/src/test/rustdoc-js-std/macro-check.js
new file mode 100644
index 000000000..242e0cbf5
--- /dev/null
+++ b/src/test/rustdoc-js-std/macro-check.js
@@ -0,0 +1,10 @@
+// ignore-order
+
+const QUERY = 'panic';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
+ { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
+ ],
+};
diff --git a/src/test/rustdoc-js-std/macro-print.js b/src/test/rustdoc-js-std/macro-print.js
new file mode 100644
index 000000000..858046e72
--- /dev/null
+++ b/src/test/rustdoc-js-std/macro-print.js
@@ -0,0 +1,10 @@
+const QUERY = 'macro:print';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'print' },
+ { 'path': 'std', 'name': 'eprint' },
+ { 'path': 'std', 'name': 'println' },
+ { 'path': 'std', 'name': 'eprintln' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/never.js b/src/test/rustdoc-js-std/never.js
new file mode 100644
index 000000000..392b1e818
--- /dev/null
+++ b/src/test/rustdoc-js-std/never.js
@@ -0,0 +1,7 @@
+const QUERY = '!';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'never' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/parser-errors.js b/src/test/rustdoc-js-std/parser-errors.js
new file mode 100644
index 000000000..dc42031e0
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-errors.js
@@ -0,0 +1,385 @@
+const QUERY = [
+ '<P>',
+ '-> <P>',
+ 'a<"P">',
+ '"P" "P"',
+ 'P "P"',
+ '"p" p',
+ '"const": p',
+ "a<:a>",
+ "a<::a>",
+ "((a))",
+ "(p -> p",
+ "::a::b",
+ "a::::b",
+ "a::b::",
+ ":a",
+ "a b:",
+ "a (b:",
+ "_:",
+ "a-bb",
+ "a>bb",
+ "ab'",
+ "a->",
+ '"p" <a>',
+ '"p" a<a>',
+ "a,<",
+ "aaaaa<>b",
+ "fn:aaaaa<>b",
+ "->a<>b",
+ "a<->",
+ "a:: a",
+ "a ::a",
+ "a<a>:",
+ "a<>:",
+ "a,:",
+ " a<> :",
+ "mod : :",
+ "a!a",
+ "a!!",
+];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 0,
+ original: "<P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "<p>",
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "-> <P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "-> <p>",
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<\"P\">",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<\"p\">",
+ error: "`\"` cannot be used in generics",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"P\" \"P\"",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"p\" \"p\"",
+ error: "Cannot have more than one literal search element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "P \"P\"",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "p \"p\"",
+ error: "Cannot use literal search when there is more than one element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"p\" p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"p\" p",
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"const\": p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"const\": p",
+ error: "You cannot use quotes on type filter",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<:a>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<:a>",
+ error: "Unexpected `:` after `<`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<::a>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<::a>",
+ error: "Unexpected `::`: paths cannot start with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "((a))",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "((a))",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "(p -> p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "(p -> p",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "::a::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "::a::b",
+ error: "Paths cannot start with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a::::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::::b",
+ error: "Unexpected `::::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a::b::",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::b::",
+ error: "Paths cannot end with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: ":a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: ":a",
+ error: "Expected type filter before `:`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a b:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b:",
+ error: "Unexpected `:`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a (b:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a (b:",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "_:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "_:",
+ error: "Unknown type filter `_`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a-bb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a-bb",
+ error: "Unexpected `-` (did you mean `->`?)",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a>bb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a>bb",
+ error: "Unexpected `>` (did you mean `->`?)",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "ab'",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "ab'",
+ error: "Unexpected `'`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a->",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a->",
+ error: "Expected at least one item after `->`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" <a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" <a>',
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" a<a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" a<a>',
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a,<',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a,<',
+ error: 'Found generics without a path',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'aaaaa<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'aaaaa<>b',
+ error: 'Expected `,`, ` `, `:` or `->`, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'fn:aaaaa<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'fn:aaaaa<>b',
+ error: 'Expected `,`, ` ` or `->`, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '->a<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '->a<>b',
+ error: 'Expected `,` or ` `, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a<->',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a<->',
+ error: 'Unexpected `-` after `<`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a:: a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a:: a',
+ error: 'Paths cannot end with `::`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a ::a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a ::a',
+ error: 'Paths cannot start with `::`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<a>:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<a>:",
+ error: 'Unexpected `:`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<>:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<>:",
+ error: 'Unexpected `<` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a,:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,:",
+ error: 'Unexpected `,` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<> :",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<> :",
+ error: 'Unexpected `<` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "mod : :",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "mod : :",
+ error: 'Unexpected `:`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a!a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!a",
+ error: '`!` can only be at the end of an ident',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a!!",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!!",
+ error: 'Cannot have more than one `!` in an ident',
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-filter.js b/src/test/rustdoc-js-std/parser-filter.js
new file mode 100644
index 000000000..e5a87a415
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-filter.js
@@ -0,0 +1,43 @@
+const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "foo",
+ fullPath: ["foo"],
+ pathWithoutLast: [],
+ pathLast: "foo",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "fn:foo",
+ returned: [],
+ typeFilter: 5,
+ userQuery: "fn:foo",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "foo",
+ fullPath: ["foo"],
+ pathWithoutLast: [],
+ pathLast: "foo",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "enum : foo",
+ returned: [],
+ typeFilter: 4,
+ userQuery: "enum : foo",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "macro<f>:foo",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "macro<f>:foo",
+ error: "Unexpected `:`",
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-generics.js b/src/test/rustdoc-js-std/parser-generics.js
new file mode 100644
index 000000000..0cf7f5019
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-generics.js
@@ -0,0 +1,62 @@
+const QUERY = ['A<B<C<D>, E>', 'p<> u8', '"p"<a>'];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'A<B<C<D>, E>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a<b<c<d>, e>',
+ error: 'Unexpected `<` after `<`',
+ },
+ {
+ elems: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ {
+ name: "u8",
+ fullPath: ["u8"],
+ pathWithoutLast: [],
+ pathLast: "u8",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "p<> u8",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "p<> u8",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: '"p"<a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p"<a>',
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-ident.js b/src/test/rustdoc-js-std/parser-ident.js
new file mode 100644
index 000000000..4b5ab01ac
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-ident.js
@@ -0,0 +1,93 @@
+const QUERY = [
+ "R<!>",
+ "!",
+ "a!",
+ "a!::b",
+ "a!::b!",
+];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "r",
+ fullPath: ["r"],
+ pathWithoutLast: [],
+ pathLast: "r",
+ generics: [
+ {
+ name: "!",
+ fullPath: ["!"],
+ pathWithoutLast: [],
+ pathLast: "!",
+ generics: [],
+ },
+ ],
+ }],
+ foundElems: 1,
+ original: "R<!>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "r<!>",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "!",
+ fullPath: ["!"],
+ pathWithoutLast: [],
+ pathLast: "!",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "!",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "!",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "a!",
+ fullPath: ["a!"],
+ pathWithoutLast: [],
+ pathLast: "a!",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "a!",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "a!::b",
+ fullPath: ["a!", "b"],
+ pathWithoutLast: ["a!"],
+ pathLast: "b",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "a!::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!::b",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "a!::b!",
+ fullPath: ["a!", "b!"],
+ pathWithoutLast: ["a!"],
+ pathLast: "b!",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "a!::b!",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!::b!",
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-literal.js b/src/test/rustdoc-js-std/parser-literal.js
new file mode 100644
index 000000000..87b3baff1
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-literal.js
@@ -0,0 +1,27 @@
+const QUERY = ['R<P>'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "r",
+ fullPath: ["r"],
+ pathWithoutLast: [],
+ pathLast: "r",
+ generics: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ ],
+ }],
+ foundElems: 1,
+ original: "R<P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "r<p>",
+ error: null,
+ }
+];
diff --git a/src/test/rustdoc-js-std/parser-paths.js b/src/test/rustdoc-js-std/parser-paths.js
new file mode 100644
index 000000000..9f823f933
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-paths.js
@@ -0,0 +1,90 @@
+const QUERY = ['A::B', 'A::B,C', 'A::B<f>,C', 'mod::a'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "A::B",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [],
+ },
+ {
+ name: "c",
+ fullPath: ["c"],
+ pathWithoutLast: [],
+ pathLast: "c",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: 'A::B,C',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a::b,c',
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [
+ {
+ name: "f",
+ fullPath: ["f"],
+ pathWithoutLast: [],
+ pathLast: "f",
+ generics: [],
+ },
+ ],
+ },
+ {
+ name: "c",
+ fullPath: ["c"],
+ pathWithoutLast: [],
+ pathLast: "c",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: 'A::B<f>,C',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a::b<f>,c',
+ error: null,
+ },
+ {
+ elems: [{
+ name: "mod::a",
+ fullPath: ["mod", "a"],
+ pathWithoutLast: ["mod"],
+ pathLast: "a",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "mod::a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "mod::a",
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-quote.js b/src/test/rustdoc-js-std/parser-quote.js
new file mode 100644
index 000000000..1e16c90de
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-quote.js
@@ -0,0 +1,87 @@
+const QUERY = [
+ '-> "p"',
+ '"p",',
+ '"p" -> a',
+ '"a" -> "p"',
+ '->"-"',
+ '"a',
+ '""',
+];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 1,
+ original: '-> "p"',
+ returned: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: '-> "p"',
+ error: null,
+ },
+ {
+ elems: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: '"p",',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p",',
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" -> a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" -> a',
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"a" -> "p"',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"a" -> "p"',
+ error: "Cannot have more than one literal search element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '->"-"',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '->"-"',
+ error: 'Unexpected `-` in a string element',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"a',
+ error: 'Unclosed `"`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '""',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '""',
+ error: 'Cannot have empty string element',
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-returned.js b/src/test/rustdoc-js-std/parser-returned.js
new file mode 100644
index 000000000..6fce17dca
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-returned.js
@@ -0,0 +1,99 @@
+const QUERY = [
+ "-> F<P>",
+ "-> P",
+ "->,a",
+ "aaaaa->a",
+ "-> !",
+];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 1,
+ original: "-> F<P>",
+ returned: [{
+ name: "f",
+ fullPath: ["f"],
+ pathWithoutLast: [],
+ pathLast: "f",
+ generics: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ ],
+ }],
+ typeFilter: -1,
+ userQuery: "-> f<p>",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 1,
+ original: "-> P",
+ returned: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "-> p",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 1,
+ original: "->,a",
+ returned: [{
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "->,a",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "aaaaa",
+ fullPath: ["aaaaa"],
+ pathWithoutLast: [],
+ pathLast: "aaaaa",
+ generics: [],
+ }],
+ foundElems: 2,
+ original: "aaaaa->a",
+ returned: [{
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "aaaaa->a",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 1,
+ original: "-> !",
+ returned: [{
+ name: "!",
+ fullPath: ["!"],
+ pathWithoutLast: [],
+ pathLast: "!",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "-> !",
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-separators.js b/src/test/rustdoc-js-std/parser-separators.js
new file mode 100644
index 000000000..5b7abdfa8
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-separators.js
@@ -0,0 +1,206 @@
+// ignore-tidy-tab
+
+const QUERY = [
+ 'aaaaaa b',
+ 'a b',
+ 'a,b',
+ 'a\tb',
+ 'a<b c>',
+ 'a<b,c>',
+ 'a<b\tc>',
+];
+
+const PARSED = [
+ {
+ elems: [
+ {
+ name: 'aaaaaa',
+ fullPath: ['aaaaaa'],
+ pathWithoutLast: [],
+ pathLast: 'aaaaaa',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "aaaaaa b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "aaaaaa b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a,b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a\tb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a\tb",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b c>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b c>",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b,c>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b,c>",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b\tc>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b\tc>",
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/parser-weird-queries.js b/src/test/rustdoc-js-std/parser-weird-queries.js
new file mode 100644
index 000000000..a3d85aeca
--- /dev/null
+++ b/src/test/rustdoc-js-std/parser-weird-queries.js
@@ -0,0 +1,123 @@
+// This test is mostly to check that the parser still kinda outputs something
+// (and doesn't enter an infinite loop!) even though the query is completely
+// invalid.
+const QUERY = [
+ 'a b',
+ 'a b',
+ 'a,b(c)',
+ 'aaa,a',
+ ',,,,',
+ 'mod :',
+ 'mod\t:',
+];
+
+const PARSED = [
+ {
+ elems: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ {
+ name: "b",
+ fullPath: ["b"],
+ pathWithoutLast: [],
+ pathLast: "b",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ {
+ name: "b",
+ fullPath: ["b"],
+ pathWithoutLast: [],
+ pathLast: "b",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a,b(c)",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,b(c)",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [
+ {
+ name: "aaa",
+ fullPath: ["aaa"],
+ pathWithoutLast: [],
+ pathLast: "aaa",
+ generics: [],
+ },
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "aaa,a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "aaa,a",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: ",,,,",
+ returned: [],
+ typeFilter: -1,
+ userQuery: ",,,,",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'mod :',
+ returned: [],
+ typeFilter: 0,
+ userQuery: 'mod :',
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'mod\t:',
+ returned: [],
+ typeFilter: 0,
+ userQuery: 'mod\t:',
+ error: null,
+ },
+];
diff --git a/src/test/rustdoc-js-std/path-ordering.js b/src/test/rustdoc-js-std/path-ordering.js
new file mode 100644
index 000000000..7dcdd4023
--- /dev/null
+++ b/src/test/rustdoc-js-std/path-ordering.js
@@ -0,0 +1,12 @@
+const QUERY = 'hashset::insert';
+
+const EXPECTED = {
+ 'others': [
+ // ensure hashset::insert comes first
+ { 'path': 'std::collections::hash_set::HashSet', 'name': 'insert' },
+ { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert' },
+ { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_with' },
+ { 'path': 'std::collections::hash_set::HashSet', 'name': 'get_or_insert_owned' },
+ { 'path': 'std::collections::hash_map::HashMap', 'name': 'insert' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/primitive.js b/src/test/rustdoc-js-std/primitive.js
new file mode 100644
index 000000000..e5690383e
--- /dev/null
+++ b/src/test/rustdoc-js-std/primitive.js
@@ -0,0 +1,75 @@
+const QUERY = [
+ 'i8',
+ 'u32',
+ 'str',
+ 'char',
+ 'unit',
+ 'tuple',
+ 'fn',
+];
+
+const EXPECTED = [
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'i8',
+ 'href': '../std/primitive.i8.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'u32',
+ 'href': '../std/primitive.u32.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'str',
+ 'href': '../std/primitive.str.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'char',
+ 'href': '../std/primitive.char.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'unit',
+ 'href': '../std/primitive.unit.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'tuple',
+ 'href': '../std/primitive.tuple.html',
+ },
+ ]
+ },
+ {
+ 'others': [
+ {
+ 'path': 'std',
+ 'name': 'fn',
+ 'href': '../std/primitive.fn.html',
+ },
+ ]
+ },
+];
diff --git a/src/test/rustdoc-js-std/quoted.js b/src/test/rustdoc-js-std/quoted.js
new file mode 100644
index 000000000..aec8484a4
--- /dev/null
+++ b/src/test/rustdoc-js-std/quoted.js
@@ -0,0 +1,21 @@
+// ignore-order
+
+const QUERY = '"error"';
+const FILTER_CRATE = 'std';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'error' },
+ { 'path': 'std::fmt', 'name': 'Error' },
+ { 'path': 'std::io', 'name': 'Error' },
+ ],
+ 'in_args': [
+ { 'path': 'std::fmt::Error', 'name': 'eq' },
+ { 'path': 'std::fmt::Error', 'name': 'cmp' },
+ { 'path': 'std::fmt::Error', 'name': 'partial_cmp' },
+
+ ],
+ 'returned': [
+ { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/return-specific-literal.js b/src/test/rustdoc-js-std/return-specific-literal.js
new file mode 100644
index 000000000..c7c347240
--- /dev/null
+++ b/src/test/rustdoc-js-std/return-specific-literal.js
@@ -0,0 +1,10 @@
+const QUERY = 'struct:"string"';
+
+const EXPECTED = {
+ 'in_args': [
+ { 'path': 'std::string::String', 'name': 'ne' },
+ ],
+ 'returned': [
+ { 'path': 'std::string::String', 'name': 'add' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js
new file mode 100644
index 000000000..d9a910553
--- /dev/null
+++ b/src/test/rustdoc-js-std/return-specific.js
@@ -0,0 +1,10 @@
+const QUERY = 'struct:string';
+
+const EXPECTED = {
+ 'in_args': [
+ { 'path': 'std::string::String', 'name': 'ne' },
+ ],
+ 'returned': [
+ { 'path': 'std::string::String', 'name': 'add' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/should-fail.js b/src/test/rustdoc-js-std/should-fail.js
new file mode 100644
index 000000000..b85a47dc0
--- /dev/null
+++ b/src/test/rustdoc-js-std/should-fail.js
@@ -0,0 +1,9 @@
+// should-fail
+
+const QUERY = 'fn';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'fn', ty: 14 },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/string-from_ut.js b/src/test/rustdoc-js-std/string-from_ut.js
new file mode 100644
index 000000000..f9edf4408
--- /dev/null
+++ b/src/test/rustdoc-js-std/string-from_ut.js
@@ -0,0 +1,11 @@
+const QUERY = 'String::from_ut';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf16_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_unchecked' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/struct-vec.js b/src/test/rustdoc-js-std/struct-vec.js
new file mode 100644
index 000000000..29609904b
--- /dev/null
+++ b/src/test/rustdoc-js-std/struct-vec.js
@@ -0,0 +1,8 @@
+const QUERY = 'struct:VecD';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::collections', 'name': 'VecDeque' },
+ { 'path': 'std::vec', 'name': 'Vec' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/typed-query.js b/src/test/rustdoc-js-std/typed-query.js
new file mode 100644
index 000000000..25efbad26
--- /dev/null
+++ b/src/test/rustdoc-js-std/typed-query.js
@@ -0,0 +1,17 @@
+// exact-check
+
+const QUERY = 'macro:print';
+const FILTER_CRATE = 'std';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'print' },
+ { 'path': 'std', 'name': 'eprint' },
+ { 'path': 'std', 'name': 'println' },
+ { 'path': 'std', 'name': 'eprintln' },
+ { 'path': 'std::pin', 'name': 'pin' },
+ { 'path': 'std::future', 'name': 'join' },
+ { 'path': 'std', 'name': 'line' },
+ { 'path': 'std', 'name': 'write' },
+ ],
+};
diff --git a/src/test/rustdoc-js-std/vec-new.js b/src/test/rustdoc-js-std/vec-new.js
new file mode 100644
index 000000000..cd0e8e7b4
--- /dev/null
+++ b/src/test/rustdoc-js-std/vec-new.js
@@ -0,0 +1,9 @@
+const QUERY = 'Vec::new';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::vec::Vec', 'name': 'new' },
+ { 'path': 'std::vec::Vec', 'name': 'ne' },
+ { 'path': 'alloc::vec::Vec', 'name': 'ne' },
+ ],
+};
diff --git a/src/test/rustdoc-js/basic.js b/src/test/rustdoc-js/basic.js
new file mode 100644
index 000000000..d99b23468
--- /dev/null
+++ b/src/test/rustdoc-js/basic.js
@@ -0,0 +1,7 @@
+const QUERY = 'Fo';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'basic', 'name': 'Foo' },
+ ],
+};
diff --git a/src/test/rustdoc-js/basic.rs b/src/test/rustdoc-js/basic.rs
new file mode 100644
index 000000000..da946a58b
--- /dev/null
+++ b/src/test/rustdoc-js/basic.rs
@@ -0,0 +1,2 @@
+/// Docs for Foo
+pub struct Foo;
diff --git a/src/test/rustdoc-js/doc-alias-filter-out.js b/src/test/rustdoc-js/doc-alias-filter-out.js
new file mode 100644
index 000000000..46a089d06
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-filter-out.js
@@ -0,0 +1,9 @@
+// exact-check
+
+const QUERY = 'true';
+
+const FILTER_CRATE = 'some_other_crate';
+
+const EXPECTED = {
+ 'others': [],
+};
diff --git a/src/test/rustdoc-js/doc-alias-filter-out.rs b/src/test/rustdoc-js/doc-alias-filter-out.rs
new file mode 100644
index 000000000..3f0c09479
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-filter-out.rs
@@ -0,0 +1,2 @@
+#[doc(alias = "true")]
+pub struct Foo;
diff --git a/src/test/rustdoc-js/doc-alias-filter.js b/src/test/rustdoc-js/doc-alias-filter.js
new file mode 100644
index 000000000..e06047ba7
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-filter.js
@@ -0,0 +1,17 @@
+// exact-check
+
+const QUERY = '"true"';
+
+const FILTER_CRATE = 'doc_alias_filter';
+
+const EXPECTED = {
+ 'others': [
+ {
+ 'path': 'doc_alias_filter',
+ 'name': 'Foo',
+ 'alias': 'true',
+ 'href': '../doc_alias_filter/struct.Foo.html',
+ 'is_alias': true
+ },
+ ],
+};
diff --git a/src/test/rustdoc-js/doc-alias-filter.rs b/src/test/rustdoc-js/doc-alias-filter.rs
new file mode 100644
index 000000000..d5227814c
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-filter.rs
@@ -0,0 +1,5 @@
+#[doc(alias = "true")]
+pub struct Foo;
+
+#[doc(alias = "false")]
+pub struct Bar;
diff --git a/src/test/rustdoc-js/doc-alias-whitespace.js b/src/test/rustdoc-js/doc-alias-whitespace.js
new file mode 100644
index 000000000..c9fc0c431
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-whitespace.js
@@ -0,0 +1,19 @@
+// exact-check
+
+const QUERY = [
+ 'Demon Lord',
+];
+
+const EXPECTED = [
+ {
+ 'others': [
+ {
+ 'path': 'doc_alias_whitespace',
+ 'name': 'Struct',
+ 'alias': 'Demon Lord',
+ 'href': '../doc_alias_whitespace/struct.Struct.html',
+ 'is_alias': true
+ },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/doc-alias-whitespace.rs b/src/test/rustdoc-js/doc-alias-whitespace.rs
new file mode 100644
index 000000000..16c022c74
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias-whitespace.rs
@@ -0,0 +1,2 @@
+#[doc(alias = "Demon Lord")]
+pub struct Struct;
diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js
new file mode 100644
index 000000000..7bb0cbe38
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias.js
@@ -0,0 +1,295 @@
+// exact-check
+
+const QUERY = [
+ 'StructItem',
+ 'StructFieldItem',
+ 'StructMethodItem',
+ 'ImplTraitItem',
+ 'StructImplConstItem',
+ 'ImplTraitFunction',
+ 'EnumItem',
+ 'VariantItem',
+ 'EnumMethodItem',
+ 'TypedefItem',
+ 'TraitItem',
+ 'TraitTypeItem',
+ 'AssociatedConstItem',
+ 'TraitFunctionItem',
+ 'FunctionItem',
+ 'ModuleItem',
+ 'ConstItem',
+ 'StaticItem',
+ 'UnionItem',
+ 'UnionFieldItem',
+ 'UnionMethodItem',
+ 'MacroItem',
+];
+
+const EXPECTED = [
+ {
+ // StructItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Struct',
+ 'alias': 'StructItem',
+ 'href': '../doc_alias/struct.Struct.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // StructFieldItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Struct',
+ 'name': 'field',
+ 'alias': 'StructFieldItem',
+ 'href': '../doc_alias/struct.Struct.html#structfield.field',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // StructMethodItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Struct',
+ 'name': 'method',
+ 'alias': 'StructMethodItem',
+ 'href': '../doc_alias/struct.Struct.html#method.method',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // ImplTraitItem
+ 'others': [],
+ },
+ {
+ // StructImplConstItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Struct',
+ 'name': 'ImplConstItem',
+ 'alias': 'StructImplConstItem',
+ 'href': '../doc_alias/struct.Struct.html#associatedconstant.ImplConstItem',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // ImplTraitFunction
+ 'others': [
+ {
+ 'path': 'doc_alias::Struct',
+ 'name': 'function',
+ 'alias': 'ImplTraitFunction',
+ 'href': '../doc_alias/struct.Struct.html#method.function',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // EnumItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Enum',
+ 'alias': 'EnumItem',
+ 'href': '../doc_alias/enum.Enum.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // VariantItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Enum',
+ 'name': 'Variant',
+ 'alias': 'VariantItem',
+ 'href': '../doc_alias/enum.Enum.html#variant.Variant',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // EnumMethodItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Enum',
+ 'name': 'method',
+ 'alias': 'EnumMethodItem',
+ 'href': '../doc_alias/enum.Enum.html#method.method',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // TypedefItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Typedef',
+ 'alias': 'TypedefItem',
+ 'href': '../doc_alias/type.Typedef.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // TraitItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Trait',
+ 'alias': 'TraitItem',
+ 'href': '../doc_alias/trait.Trait.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // TraitTypeItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Trait',
+ 'name': 'Target',
+ 'alias': 'TraitTypeItem',
+ 'href': '../doc_alias/trait.Trait.html#associatedtype.Target',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // AssociatedConstItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Trait',
+ 'name': 'AssociatedConst',
+ 'alias': 'AssociatedConstItem',
+ 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // TraitFunctionItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Trait',
+ 'name': 'function',
+ 'alias': 'TraitFunctionItem',
+ 'href': '../doc_alias/trait.Trait.html#tymethod.function',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // FunctionItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'function',
+ 'alias': 'FunctionItem',
+ 'href': '../doc_alias/fn.function.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // ModuleItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Module',
+ 'alias': 'ModuleItem',
+ 'href': '../doc_alias/Module/index.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // ConstItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Const',
+ 'alias': 'ConstItem',
+ 'href': '../doc_alias/constant.Const.html',
+ 'is_alias': true
+ },
+ {
+ 'path': 'doc_alias::Struct',
+ 'name': 'ImplConstItem',
+ },
+ ],
+ },
+ {
+ // StaticItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Static',
+ 'alias': 'StaticItem',
+ 'href': '../doc_alias/static.Static.html',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // UnionItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Union',
+ 'alias': 'UnionItem',
+ 'href': '../doc_alias/union.Union.html',
+ 'is_alias': true
+ },
+ // Not an alias!
+ {
+ 'path': 'doc_alias::Union',
+ 'name': 'union_item',
+ 'href': '../doc_alias/union.Union.html#structfield.union_item'
+ },
+ ],
+ },
+ {
+ // UnionFieldItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Union',
+ 'name': 'union_item',
+ 'alias': 'UnionFieldItem',
+ 'href': '../doc_alias/union.Union.html#structfield.union_item',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // UnionMethodItem
+ 'others': [
+ {
+ 'path': 'doc_alias::Union',
+ 'name': 'method',
+ 'alias': 'UnionMethodItem',
+ 'href': '../doc_alias/union.Union.html#method.method',
+ 'is_alias': true
+ },
+ ],
+ },
+ {
+ // MacroItem
+ 'others': [
+ {
+ 'path': 'doc_alias',
+ 'name': 'Macro',
+ 'alias': 'MacroItem',
+ 'href': '../doc_alias/macro.Macro.html',
+ 'is_alias': true
+ },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs
new file mode 100644
index 000000000..750b7b757
--- /dev/null
+++ b/src/test/rustdoc-js/doc-alias.rs
@@ -0,0 +1,75 @@
+#[doc(alias = "StructItem")]
+pub struct Struct {
+ #[doc(alias = "StructFieldItem")]
+ pub field: u32,
+}
+
+impl Struct {
+ #[doc(alias = "StructImplConstItem")]
+ pub const ImplConstItem: i32 = 0;
+ #[doc(alias = "StructMethodItem")]
+ pub fn method(&self) {}
+}
+
+impl Trait for Struct {
+ type Target = u32;
+ const AssociatedConst: i32 = 12;
+
+ #[doc(alias = "ImplTraitFunction")]
+ fn function() -> Self::Target { 0 }
+}
+
+#[doc(alias = "EnumItem")]
+pub enum Enum {
+ #[doc(alias = "VariantItem")]
+ Variant,
+}
+
+impl Enum {
+ #[doc(alias = "EnumMethodItem")]
+ pub fn method(&self) {}
+}
+
+#[doc(alias = "TypedefItem")]
+pub type Typedef = i32;
+
+#[doc(alias = "TraitItem")]
+pub trait Trait {
+ #[doc(alias = "TraitTypeItem")]
+ type Target;
+ #[doc(alias = "AssociatedConstItem")]
+ const AssociatedConst: i32;
+
+ #[doc(alias = "TraitFunctionItem")]
+ fn function() -> Self::Target;
+}
+
+#[doc(alias = "FunctionItem")]
+pub fn function() {}
+
+#[doc(alias = "ModuleItem")]
+pub mod Module {}
+
+#[doc(alias = "ConstItem")]
+pub const Const: u32 = 0;
+
+#[doc(alias = "StaticItem")]
+pub static Static: u32 = 0;
+
+#[doc(alias = "UnionItem")]
+pub union Union {
+ #[doc(alias = "UnionFieldItem")]
+ pub union_item: u32,
+ pub y: f32,
+}
+
+impl Union {
+ #[doc(alias = "UnionMethodItem")]
+ pub fn method(&self) {}
+}
+
+#[doc(alias = "MacroItem")]
+#[macro_export]
+macro_rules! Macro {
+ () => {}
+}
diff --git a/src/test/rustdoc-js/exact-match.js b/src/test/rustdoc-js/exact-match.js
new file mode 100644
index 000000000..b0a411bee
--- /dev/null
+++ b/src/test/rustdoc-js/exact-match.js
@@ -0,0 +1,9 @@
+const QUERY = 'si::pc';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'exact_match::Si', 'name': 'pc' },
+ { 'path': 'exact_match::Psi', 'name': 'pc' },
+ { 'path': 'exact_match::Si', 'name': 'pa' },
+ ],
+};
diff --git a/src/test/rustdoc-js/exact-match.rs b/src/test/rustdoc-js/exact-match.rs
new file mode 100644
index 000000000..2eacc0a35
--- /dev/null
+++ b/src/test/rustdoc-js/exact-match.rs
@@ -0,0 +1,68 @@
+macro_rules! imp {
+ ($name:ident) => {
+ pub struct $name {
+ pub op: usize,
+ }
+ impl $name {
+ pub fn op() {}
+ pub fn cmp() {}
+ pub fn map() {}
+ pub fn pop() {}
+ pub fn ptr() {}
+ pub fn rpo() {}
+ pub fn drop() {}
+ pub fn copy() {}
+ pub fn zip() {}
+ pub fn sup() {}
+ pub fn pa() {}
+ pub fn pb() {}
+ pub fn pc() {}
+ pub fn pd() {}
+ pub fn pe() {}
+ pub fn pf() {}
+ pub fn pg() {}
+ pub fn ph() {}
+ pub fn pi() {}
+ pub fn pj() {}
+ pub fn pk() {}
+ pub fn pl() {}
+ pub fn pm() {}
+ pub fn pn() {}
+ pub fn po() {}
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ imp!($name);
+ imp!($($names),*);
+ };
+}
+macro_rules! en {
+ ($name:ident) => {
+ pub enum $name {
+ Ptr,
+ Rp,
+ Rpo,
+ Pt,
+ Drop,
+ Dr,
+ Dro,
+ Sup,
+ Op,
+ Cmp,
+ Map,
+ Mp,
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ en!($name);
+ en!($($names),*);
+ };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
diff --git a/src/test/rustdoc-js/foreign-type-path.js b/src/test/rustdoc-js/foreign-type-path.js
new file mode 100644
index 000000000..334761bad
--- /dev/null
+++ b/src/test/rustdoc-js/foreign-type-path.js
@@ -0,0 +1,9 @@
+const QUERY = 'MyForeignType::my_method';
+
+const EXPECTED = {
+ 'others': [
+ // Test case for https://github.com/rust-lang/rust/pull/96887#pullrequestreview-967154358
+ // Validates that the parent path for a foreign type method is correct.
+ { 'path': 'foreign_type_path::aaaaaaa::MyForeignType', 'name': 'my_method' },
+ ],
+};
diff --git a/src/test/rustdoc-js/foreign-type-path.rs b/src/test/rustdoc-js/foreign-type-path.rs
new file mode 100644
index 000000000..83400104e
--- /dev/null
+++ b/src/test/rustdoc-js/foreign-type-path.rs
@@ -0,0 +1,13 @@
+#![feature(extern_types)]
+
+pub mod aaaaaaa {
+
+ extern {
+ pub type MyForeignType;
+ }
+
+ impl MyForeignType {
+ pub fn my_method() {}
+ }
+
+}
diff --git a/src/test/rustdoc-js/generics-impl.js b/src/test/rustdoc-js/generics-impl.js
new file mode 100644
index 000000000..bb6e0041d
--- /dev/null
+++ b/src/test/rustdoc-js/generics-impl.js
@@ -0,0 +1,57 @@
+// exact-check
+
+const QUERY = [
+ 'Aaaaaaa -> u32',
+ 'Aaaaaaa -> bool',
+ 'Aaaaaaa -> usize',
+ 'Read -> u64',
+ 'bool -> u64',
+ 'Ddddddd -> u64',
+ '-> Ddddddd'
+];
+
+const EXPECTED = [
+ {
+ // Aaaaaaa -> u32
+ 'others': [
+ { 'path': 'generics_impl::Aaaaaaa', 'name': 'bbbbbbb' },
+ ],
+ },
+ {
+ // Aaaaaaa -> bool
+ 'others': [
+ { 'path': 'generics_impl::Aaaaaaa', 'name': 'ccccccc' },
+ ],
+ },
+ {
+ // Aaaaaaa -> usize
+ 'others': [
+ { 'path': 'generics_impl::Aaaaaaa', 'name': 'read' },
+ ],
+ },
+ {
+ // Read -> u64
+ 'others': [
+ { 'path': 'generics_impl::Ddddddd', 'name': 'eeeeeee' },
+ { 'path': 'generics_impl::Ddddddd', 'name': 'ggggggg' },
+ ],
+ },
+ {
+ // bool -> u64
+ 'others': [
+ { 'path': 'generics_impl::Ddddddd', 'name': 'fffffff' },
+ ],
+ },
+ {
+ // Ddddddd -> u64
+ 'others': [
+ { 'path': 'generics_impl::Ddddddd', 'name': 'ggggggg' },
+ ],
+ },
+ {
+ // -> Ddddddd
+ 'others': [
+ { 'path': 'generics_impl::Ddddddd', 'name': 'hhhhhhh' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/generics-impl.rs b/src/test/rustdoc-js/generics-impl.rs
new file mode 100644
index 000000000..696218021
--- /dev/null
+++ b/src/test/rustdoc-js/generics-impl.rs
@@ -0,0 +1,35 @@
+use std::io::{Result as IoResult, Read};
+
+pub struct Aaaaaaa;
+
+impl Aaaaaaa {
+ pub fn bbbbbbb(self) -> u32 {
+ 1
+ }
+ pub fn ccccccc(&self) -> bool {
+ true
+ }
+}
+
+impl Read for Aaaaaaa {
+ fn read(&mut self, out: &mut [u8]) -> IoResult<usize> {
+ Ok(out.len())
+ }
+}
+
+pub struct Ddddddd<T>(T);
+
+impl<T: Read> Ddddddd<T> {
+ pub fn eeeeeee(_: T) -> u64 {
+ 1
+ }
+ pub fn fffffff(_: bool) -> u64 {
+ 1
+ }
+ pub fn ggggggg(self) -> u64 {
+ 1
+ }
+ pub fn hhhhhhh() -> Self where T: Default {
+ Ddddddd(T::default())
+ }
+}
diff --git a/src/test/rustdoc-js/generics-multi-trait.js b/src/test/rustdoc-js/generics-multi-trait.js
new file mode 100644
index 000000000..e7fcea876
--- /dev/null
+++ b/src/test/rustdoc-js/generics-multi-trait.js
@@ -0,0 +1,32 @@
+// exact-check
+
+const QUERY = [
+ 'Result<SomeTrait>',
+ 'Zzzzzzzzzzzzzzzzzz',
+ 'Nonononononononono',
+];
+
+const EXPECTED = [
+ // check one of the generic items
+ {
+ 'in_args': [
+ { 'path': 'generics_multi_trait', 'name': 'beta' },
+ ],
+ 'returned': [
+ { 'path': 'generics_multi_trait', 'name': 'bet' },
+ ],
+ },
+ {
+ 'in_args': [
+ { 'path': 'generics_multi_trait', 'name': 'beta' },
+ ],
+ 'returned': [
+ { 'path': 'generics_multi_trait', 'name': 'bet' },
+ ],
+ },
+ // ignore the name of the generic itself
+ {
+ 'in_args': [],
+ 'returned': [],
+ },
+];
diff --git a/src/test/rustdoc-js/generics-multi-trait.rs b/src/test/rustdoc-js/generics-multi-trait.rs
new file mode 100644
index 000000000..e6fd06d25
--- /dev/null
+++ b/src/test/rustdoc-js/generics-multi-trait.rs
@@ -0,0 +1,12 @@
+pub trait SomeTrait {}
+pub trait Zzzzzzzzzzzzzzzzzz {}
+
+pub fn bet<Nonononononononono: SomeTrait + Zzzzzzzzzzzzzzzzzz>() -> Result<Nonononononononono, ()> {
+ loop {}
+}
+
+pub fn beta<Nonononononononono: SomeTrait + Zzzzzzzzzzzzzzzzzz>(
+ _param: Result<Nonononononononono, ()>,
+) {
+ loop {}
+}
diff --git a/src/test/rustdoc-js/generics-trait.js b/src/test/rustdoc-js/generics-trait.js
new file mode 100644
index 000000000..787662243
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.js
@@ -0,0 +1,23 @@
+const QUERY = [
+ 'Result<SomeTrait>',
+ 'OtherThingxxxxxxxx',
+];
+
+const EXPECTED = [
+ {
+ 'in_args': [
+ { 'path': 'generics_trait', 'name': 'beta' },
+ ],
+ 'returned': [
+ { 'path': 'generics_trait', 'name': 'bet' },
+ ],
+ },
+ {
+ 'in_args': [
+ { 'path': 'generics_trait', 'name': 'alpha' },
+ ],
+ 'returned': [
+ { 'path': 'generics_trait', 'name': 'alef' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/generics-trait.rs b/src/test/rustdoc-js/generics-trait.rs
new file mode 100644
index 000000000..20db117cc
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.rs
@@ -0,0 +1,8 @@
+pub trait SomeTrait {}
+pub trait OtherThingxxxxxxxx {}
+
+pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> { loop {} }
+pub fn bet<T: SomeTrait>() -> Result<T, ()> { loop {} }
+
+pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) { loop {} }
+pub fn beta<T: SomeTrait>(_param: Result<T, ()>) { loop {} }
diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js
new file mode 100644
index 000000000..5e5ba7cd9
--- /dev/null
+++ b/src/test/rustdoc-js/generics.js
@@ -0,0 +1,73 @@
+// exact-check
+
+const QUERY = [
+ 'R<P>',
+ '"P"',
+ 'P',
+ 'ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>',
+ 'TraitCat',
+ 'TraitDog',
+ 'Result<String>',
+];
+
+const EXPECTED = [
+ {
+ // R<P>
+ 'returned': [
+ { 'path': 'generics', 'name': 'alef' },
+ ],
+ 'in_args': [
+ { 'path': 'generics', 'name': 'alpha' },
+ ],
+ },
+ {
+ // "P"
+ 'others': [
+ { 'path': 'generics', 'name': 'P' },
+ ],
+ 'returned': [
+ { 'path': 'generics', 'name': 'alef' },
+ ],
+ 'in_args': [
+ { 'path': 'generics', 'name': 'alpha' },
+ ],
+ },
+ {
+ // P
+ 'returned': [
+ { 'path': 'generics', 'name': 'alef' },
+ ],
+ 'in_args': [
+ { 'path': 'generics', 'name': 'alpha' },
+ ],
+ },
+ {
+ // "ExtraCreditStructMulti"<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
+ 'in_args': [
+ { 'path': 'generics', 'name': 'extracreditlabhomework' },
+ ],
+ 'returned': [],
+ },
+ {
+ // TraitCat
+ 'in_args': [
+ { 'path': 'generics', 'name': 'gamma' },
+ ],
+ },
+ {
+ // TraitDog
+ 'in_args': [
+ { 'path': 'generics', 'name': 'gamma' },
+ ],
+ },
+ {
+ // Result<String>
+ 'others': [],
+ 'returned': [
+ { 'path': 'generics', 'name': 'super_soup' },
+ ],
+ 'in_args': [
+ { 'path': 'generics', 'name': 'super_soup' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs
new file mode 100644
index 000000000..055c51c7e
--- /dev/null
+++ b/src/test/rustdoc-js/generics.rs
@@ -0,0 +1,28 @@
+pub struct P;
+pub struct Q;
+pub struct R<T>(T);
+
+// returns test
+pub fn alef() -> R<P> { loop {} }
+pub fn bet() -> R<Q> { loop {} }
+
+// in_args test
+pub fn alpha(_x: R<P>) { loop {} }
+pub fn beta(_x: R<Q>) { loop {} }
+
+// test case with multiple appearances of the same type
+pub struct ExtraCreditStructMulti<T, U> { t: T, u: U }
+pub struct ExtraCreditInnerMulti {}
+pub fn extracreditlabhomework(
+ _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
+) { loop {} }
+pub fn redherringmatchforextracredit(
+ _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>
+) { loop {} }
+
+pub trait TraitCat {}
+pub trait TraitDog {}
+
+pub fn gamma<T: TraitCat + TraitDog>(t: T) {}
+
+pub fn super_soup(s: Result<String, i32>) -> Result<String, i32> { s }
diff --git a/src/test/rustdoc-js/impl-trait.js b/src/test/rustdoc-js/impl-trait.js
new file mode 100644
index 000000000..8d594bf8a
--- /dev/null
+++ b/src/test/rustdoc-js/impl-trait.js
@@ -0,0 +1,51 @@
+// ignore-order
+
+const QUERY = [
+ 'Aaaaaaa -> i32',
+ 'Aaaaaaa -> Aaaaaaa',
+ 'Aaaaaaa -> usize',
+ '-> Aaaaaaa',
+ 'Aaaaaaa',
+];
+
+const EXPECTED = [
+ {
+ // Aaaaaaa -> i32
+ 'others': [
+ { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' },
+ ],
+ },
+ {
+ // Aaaaaaa -> Aaaaaaa
+ 'others': [
+ { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+ ],
+ },
+ {
+ // Aaaaaaa -> usize
+ 'others': [],
+ },
+ {
+ // -> Aaaaaaa
+ 'others': [
+ { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+ { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+ ],
+ },
+ {
+ // Aaaaaaa
+ 'others': [
+ { 'path': 'impl_trait', 'name': 'Aaaaaaa' },
+ ],
+ 'in_args': [
+ { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' },
+ ],
+ 'returned': [
+ { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+ { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/impl-trait.rs b/src/test/rustdoc-js/impl-trait.rs
new file mode 100644
index 000000000..fb8869b46
--- /dev/null
+++ b/src/test/rustdoc-js/impl-trait.rs
@@ -0,0 +1,21 @@
+pub trait Aaaaaaa {}
+
+impl Aaaaaaa for () {}
+
+pub fn bbbbbbb() -> impl Aaaaaaa {
+ ()
+}
+
+pub struct Ccccccc {}
+
+impl Ccccccc {
+ pub fn ddddddd(&self) -> impl Aaaaaaa {
+ ()
+ }
+ pub fn eeeeeee(&self, _x: impl Aaaaaaa) -> i32 {
+ 0
+ }
+ pub fn fffffff(&self, x: impl Aaaaaaa) -> impl Aaaaaaa {
+ x
+ }
+}
diff --git a/src/test/rustdoc-js/module-substring.js b/src/test/rustdoc-js/module-substring.js
new file mode 100644
index 000000000..a446c39eb
--- /dev/null
+++ b/src/test/rustdoc-js/module-substring.js
@@ -0,0 +1,9 @@
+const QUERY = 'ig::pc';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'module_substring::Sig', 'name': 'pc' },
+ { 'path': 'module_substring::Si', 'name': 'pc' },
+ { 'path': 'module_substring::Si', 'name': 'pa' },
+ ],
+};
diff --git a/src/test/rustdoc-js/module-substring.rs b/src/test/rustdoc-js/module-substring.rs
new file mode 100644
index 000000000..2eacc0a35
--- /dev/null
+++ b/src/test/rustdoc-js/module-substring.rs
@@ -0,0 +1,68 @@
+macro_rules! imp {
+ ($name:ident) => {
+ pub struct $name {
+ pub op: usize,
+ }
+ impl $name {
+ pub fn op() {}
+ pub fn cmp() {}
+ pub fn map() {}
+ pub fn pop() {}
+ pub fn ptr() {}
+ pub fn rpo() {}
+ pub fn drop() {}
+ pub fn copy() {}
+ pub fn zip() {}
+ pub fn sup() {}
+ pub fn pa() {}
+ pub fn pb() {}
+ pub fn pc() {}
+ pub fn pd() {}
+ pub fn pe() {}
+ pub fn pf() {}
+ pub fn pg() {}
+ pub fn ph() {}
+ pub fn pi() {}
+ pub fn pj() {}
+ pub fn pk() {}
+ pub fn pl() {}
+ pub fn pm() {}
+ pub fn pn() {}
+ pub fn po() {}
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ imp!($name);
+ imp!($($names),*);
+ };
+}
+macro_rules! en {
+ ($name:ident) => {
+ pub enum $name {
+ Ptr,
+ Rp,
+ Rpo,
+ Pt,
+ Drop,
+ Dr,
+ Dro,
+ Sup,
+ Op,
+ Cmp,
+ Map,
+ Mp,
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ en!($name);
+ en!($($names),*);
+ };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
diff --git a/src/test/rustdoc-js/path-ordering.js b/src/test/rustdoc-js/path-ordering.js
new file mode 100644
index 000000000..4aee569b0
--- /dev/null
+++ b/src/test/rustdoc-js/path-ordering.js
@@ -0,0 +1,14 @@
+// exact-check
+
+const QUERY = 'b::ccccccc';
+
+const EXPECTED = {
+ 'others': [
+ // `ccccccc` is an exact match for all three of these.
+ // However `b` is a closer match for `bb` than for any
+ // of the others, so it ought to go first.
+ { 'path': 'path_ordering::bb', 'name': 'Ccccccc' },
+ { 'path': 'path_ordering::aa', 'name': 'Ccccccc' },
+ { 'path': 'path_ordering::dd', 'name': 'Ccccccc' },
+ ],
+};
diff --git a/src/test/rustdoc-js/path-ordering.rs b/src/test/rustdoc-js/path-ordering.rs
new file mode 100644
index 000000000..7843cf7f9
--- /dev/null
+++ b/src/test/rustdoc-js/path-ordering.rs
@@ -0,0 +1,9 @@
+pub mod dd {
+ pub struct Ccccccc;
+}
+pub mod aa {
+ pub struct Ccccccc;
+}
+pub mod bb {
+ pub struct Ccccccc;
+}
diff --git a/src/test/rustdoc-js/primitive.js b/src/test/rustdoc-js/primitive.js
new file mode 100644
index 000000000..918f70999
--- /dev/null
+++ b/src/test/rustdoc-js/primitive.js
@@ -0,0 +1,25 @@
+// exact-check
+
+const QUERY = [
+ "i32",
+ "str",
+ "TotoIsSomewhere",
+];
+
+const EXPECTED = [
+ {
+ 'in_args': [
+ { 'path': 'primitive', 'name': 'foo' },
+ ],
+ },
+ {
+ 'returned': [
+ { 'path': 'primitive', 'name': 'foo' },
+ ],
+ },
+ {
+ 'others': [],
+ 'in_args': [],
+ 'returned': [],
+ },
+];
diff --git a/src/test/rustdoc-js/primitive.rs b/src/test/rustdoc-js/primitive.rs
new file mode 100644
index 000000000..2b30ccf15
--- /dev/null
+++ b/src/test/rustdoc-js/primitive.rs
@@ -0,0 +1,5 @@
+pub fn foo(i: i32) -> &'static str {
+ "hello"
+}
+
+pub fn foo2<TotoIsSomewhere>(i: &TotoIsSomewhere, j: TotoIsSomewhere) {}
diff --git a/src/test/rustdoc-js/prototype.js b/src/test/rustdoc-js/prototype.js
new file mode 100644
index 000000000..2f1d841c3
--- /dev/null
+++ b/src/test/rustdoc-js/prototype.js
@@ -0,0 +1,16 @@
+// exact-check
+
+const QUERY = ['constructor', '__proto__'];
+
+const EXPECTED = [
+ {
+ 'others': [],
+ 'returned': [],
+ 'in_args': [],
+ },
+ {
+ 'others': [],
+ 'returned': [],
+ 'in_args': [],
+ },
+];
diff --git a/src/test/rustdoc-js/prototype.rs b/src/test/rustdoc-js/prototype.rs
new file mode 100644
index 000000000..5f6d73cc1
--- /dev/null
+++ b/src/test/rustdoc-js/prototype.rs
@@ -0,0 +1,4 @@
+// The alias needed to be there to reproduce the bug
+// that used to be here.
+#[doc(alias="other_alias")]
+pub fn something_else() {}
diff --git a/src/test/rustdoc-js/raw-pointer.js b/src/test/rustdoc-js/raw-pointer.js
new file mode 100644
index 000000000..140b955ea
--- /dev/null
+++ b/src/test/rustdoc-js/raw-pointer.js
@@ -0,0 +1,55 @@
+// ignore-order
+
+const QUERY = [
+ 'Aaaaaaa -> i32',
+ 'Aaaaaaa -> Aaaaaaa',
+ 'Aaaaaaa -> usize',
+ '-> Aaaaaaa',
+ 'Aaaaaaa',
+];
+
+const EXPECTED = [
+ {
+ // Aaaaaaa -> i32
+ 'others': [
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'eeeeeee' },
+ ],
+ },
+ {
+ // Aaaaaaa -> Aaaaaaa
+ 'others': [
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+ ],
+ },
+ {
+ // Aaaaaaa -> usize
+ 'others': [],
+ },
+ {
+ // -> Aaaaaaa
+ 'others': [
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ddddddd' },
+ { 'path': 'raw_pointer', 'name': 'bbbbbbb' },
+ ],
+ },
+ {
+ // Aaaaaaa
+ 'others': [
+ { 'path': 'raw_pointer', 'name': 'Aaaaaaa' },
+ ],
+ 'in_args': [
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'eeeeeee' },
+ ],
+ 'returned': [
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'fffffff' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ggggggg' },
+ { 'path': 'raw_pointer::Ccccccc', 'name': 'ddddddd' },
+ { 'path': 'raw_pointer', 'name': 'bbbbbbb' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/raw-pointer.rs b/src/test/rustdoc-js/raw-pointer.rs
new file mode 100644
index 000000000..b8ace2e0b
--- /dev/null
+++ b/src/test/rustdoc-js/raw-pointer.rs
@@ -0,0 +1,24 @@
+use std::ptr;
+
+pub struct Aaaaaaa {}
+
+pub fn bbbbbbb() -> *const Aaaaaaa {
+ ptr::null()
+}
+
+pub struct Ccccccc {}
+
+impl Ccccccc {
+ pub fn ddddddd(&self) -> *const Aaaaaaa {
+ ptr::null()
+ }
+ pub fn eeeeeee(&self, _x: *const Aaaaaaa) -> i32 {
+ 0
+ }
+ pub fn fffffff(&self, x: *const Aaaaaaa) -> *const Aaaaaaa {
+ x
+ }
+ pub fn ggggggg(&self, x: *mut Aaaaaaa) -> *mut Aaaaaaa {
+ x
+ }
+}
diff --git a/src/test/rustdoc-js/search-short-types.js b/src/test/rustdoc-js/search-short-types.js
new file mode 100644
index 000000000..d14672af7
--- /dev/null
+++ b/src/test/rustdoc-js/search-short-types.js
@@ -0,0 +1,10 @@
+const QUERY = 'P';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'search_short_types', 'name': 'P' },
+ { 'path': 'search_short_types::VeryLongTypeName', 'name': 'p' },
+ { 'path': 'search_short_types', 'name': 'Ap' },
+ { 'path': 'search_short_types::VeryLongTypeName', 'name': 'ap' },
+ ],
+};
diff --git a/src/test/rustdoc-js/search-short-types.rs b/src/test/rustdoc-js/search-short-types.rs
new file mode 100644
index 000000000..a4083f9a7
--- /dev/null
+++ b/src/test/rustdoc-js/search-short-types.rs
@@ -0,0 +1,74 @@
+macro_rules! imp {
+ ($name:ident) => {
+ pub struct $name {
+ pub op: usize,
+ }
+ impl $name {
+ pub fn op() {}
+ pub fn cmp() {}
+ pub fn map() {}
+ pub fn pop() {}
+ pub fn ptr() {}
+ pub fn rpo() {}
+ pub fn drop() {}
+ pub fn copy() {}
+ pub fn zip() {}
+ pub fn sup() {}
+ pub fn pa() {}
+ pub fn pb() {}
+ pub fn pc() {}
+ pub fn pd() {}
+ pub fn pe() {}
+ pub fn pf() {}
+ pub fn pg() {}
+ pub fn ph() {}
+ pub fn pi() {}
+ pub fn pj() {}
+ pub fn pk() {}
+ pub fn pl() {}
+ pub fn pm() {}
+ pub fn pn() {}
+ pub fn po() {}
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ imp!($name);
+ imp!($($names),*);
+ };
+}
+macro_rules! en {
+ ($name:ident) => {
+ pub enum $name {
+ Ptr,
+ Rp,
+ Rpo,
+ Pt,
+ Drop,
+ Dr,
+ Dro,
+ Sup,
+ Op,
+ Cmp,
+ Map,
+ Mp,
+ }
+ };
+ ($name:ident, $($names:ident),*) => {
+ en!($name);
+ en!($($names),*);
+ };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
+
+pub struct VeryLongTypeName;
+impl VeryLongTypeName {
+ pub fn p() {}
+ pub fn ap() {}
+}
diff --git a/src/test/rustdoc-js/struct-like-variant.js b/src/test/rustdoc-js/struct-like-variant.js
new file mode 100644
index 000000000..f6deea51e
--- /dev/null
+++ b/src/test/rustdoc-js/struct-like-variant.js
@@ -0,0 +1,7 @@
+const QUERY = 'name';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'struct_like_variant::Enum::Bar', 'name': 'name', 'desc': 'This is a name.' },
+ ],
+};
diff --git a/src/test/rustdoc-js/struct-like-variant.rs b/src/test/rustdoc-js/struct-like-variant.rs
new file mode 100644
index 000000000..2f52a319a
--- /dev/null
+++ b/src/test/rustdoc-js/struct-like-variant.rs
@@ -0,0 +1,8 @@
+#![crate_name = "struct_like_variant"]
+
+pub enum Enum {
+ Bar {
+ /// This is a name.
+ name: String
+ }
+}
diff --git a/src/test/rustdoc-js/substring.js b/src/test/rustdoc-js/substring.js
new file mode 100644
index 000000000..af05cd1ad
--- /dev/null
+++ b/src/test/rustdoc-js/substring.js
@@ -0,0 +1,8 @@
+const QUERY = 'waker_from';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'substring::SuperWaker', 'name': 'local_waker_from_nonlocal' },
+ { 'path': 'substring::SuperWakerTask', 'name': 'local_waker_from_nonlocal' },
+ ],
+};
diff --git a/src/test/rustdoc-js/substring.rs b/src/test/rustdoc-js/substring.rs
new file mode 100644
index 000000000..e729c722c
--- /dev/null
+++ b/src/test/rustdoc-js/substring.rs
@@ -0,0 +1,21 @@
+pub struct SuperWaker;
+
+impl SuperWaker {
+ pub fn local_waker_from_nonlocal() {}
+ pub fn local_waker_frm_nonlocal() {}
+ pub fn some_method() {}
+ pub fn some_other_method() {}
+ pub fn waker_non_local() {}
+ pub fn from_non_local() {}
+}
+
+pub struct SuperWakerTask;
+
+impl SuperWakerTask {
+ pub fn local_waker_from_nonlocal() {}
+ pub fn local_waker_frm_nonlocal() {}
+ pub fn some_method() {}
+ pub fn some_other_method() {}
+ pub fn waker_non_local() {}
+ pub fn from_non_local() {}
+}
diff --git a/src/test/rustdoc-js/summaries.js b/src/test/rustdoc-js/summaries.js
new file mode 100644
index 000000000..dfb11e804
--- /dev/null
+++ b/src/test/rustdoc-js/summaries.js
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2'];
+
+const EXPECTED = [
+ {
+ 'others': [
+ { 'path': '', 'name': 'summaries', 'desc': 'This <em>summary</em> has a link, [<code>code</code>], and <code>Sidebar2</code> intra-doc.' },
+ ],
+ },
+ {
+ 'others': [
+ { 'path': 'summaries', 'name': 'Sidebar', 'desc': 'This <code>code</code> will be rendered in a code tag.' },
+ ],
+ },
+ {
+ 'others': [
+ { 'path': 'summaries', 'name': 'Sidebar2', 'desc': '' },
+ ],
+ },
+];
diff --git a/src/test/rustdoc-js/summaries.rs b/src/test/rustdoc-js/summaries.rs
new file mode 100644
index 000000000..1ee1c34aa
--- /dev/null
+++ b/src/test/rustdoc-js/summaries.rs
@@ -0,0 +1,22 @@
+#![crate_type = "lib"]
+#![crate_name = "summaries"]
+
+#![allow(rustdoc::broken_intra_doc_links)]
+
+//! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc.
+//!
+//! This is the second paragraph. It should not be rendered.
+//! To test that intra-doc links are resolved properly, [`code`] should render
+//! the square brackets, and [`Sidebar2`] should not.
+//!
+//! [link]: https://example.com
+
+/// This `code` will be rendered in a code tag.
+///
+/// This text should not be rendered.
+pub struct Sidebar;
+
+/// ```text
+/// this block should not be rendered
+/// ```
+pub struct Sidebar2;
diff --git a/src/test/rustdoc-json/assoc_items.rs b/src/test/rustdoc-json/assoc_items.rs
new file mode 100644
index 000000000..2ee64c9f6
--- /dev/null
+++ b/src/test/rustdoc-json/assoc_items.rs
@@ -0,0 +1,29 @@
+#![no_std]
+
+// @has assoc_items.json
+
+pub struct Simple;
+
+impl Simple {
+ // @has - "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\"
+ pub const CONSTANT: usize = 0;
+}
+
+pub trait EasyToImpl {
+ // @has - "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\"
+ // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default" null
+ type ToDeclare;
+ // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\"
+ // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null
+ const AN_ATTRIBUTE: usize;
+}
+
+impl EasyToImpl for Simple {
+ // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\"
+ // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\"
+ type ToDeclare = usize;
+ // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\"
+ // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\"
+ // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\"
+ const AN_ATTRIBUTE: usize = 12;
+}
diff --git a/src/test/rustdoc-json/assoc_type.rs b/src/test/rustdoc-json/assoc_type.rs
new file mode 100644
index 000000000..716bb3d28
--- /dev/null
+++ b/src/test/rustdoc-json/assoc_type.rs
@@ -0,0 +1,22 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/98547>.
+
+// @has assoc_type.json
+// @has - "$.index[*][?(@.name=='Trait')]"
+// @has - "$.index[*][?(@.name=='AssocType')]"
+// @has - "$.index[*][?(@.name=='S')]"
+// @has - "$.index[*][?(@.name=='S2')]"
+
+pub trait Trait {
+ type AssocType;
+}
+
+impl<T> Trait for T {
+ type AssocType = Self;
+}
+
+pub struct S;
+
+/// Not needed for the #98547 ICE to occur, but added to maximize the chance of
+/// getting an ICE in the future. See
+/// <https://github.com/rust-lang/rust/pull/98548#discussion_r908219164>
+pub struct S2;
diff --git a/src/test/rustdoc-json/blanket_impls.rs b/src/test/rustdoc-json/blanket_impls.rs
new file mode 100644
index 000000000..edf1a9fe2
--- /dev/null
+++ b/src/test/rustdoc-json/blanket_impls.rs
@@ -0,0 +1,9 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/98658>
+
+#![no_std]
+
+// @has blanket_impls.json
+// @has - "$.index[*][?(@.name=='Error')].kind" \"assoc_type\"
+// @has - "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\"
+// @has - "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\"
+pub struct ForBlanketTryFromImpl;
diff --git a/src/test/rustdoc-json/doc_hidden_failure.rs b/src/test/rustdoc-json/doc_hidden_failure.rs
new file mode 100644
index 000000000..5c4ccf996
--- /dev/null
+++ b/src/test/rustdoc-json/doc_hidden_failure.rs
@@ -0,0 +1,22 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/98007>.
+
+#![feature(no_core)]
+#![no_core]
+
+mod auto {
+ mod action_row {
+ pub struct ActionRowBuilder;
+ }
+
+ #[doc(hidden)]
+ pub mod builders {
+ pub use super::action_row::ActionRowBuilder;
+ }
+}
+
+// @count doc_hidden_failure.json "$.index[*][?(@.name=='builders')]" 2
+pub use auto::*;
+
+pub mod builders {
+ pub use crate::auto::builders::*;
+}
diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs
new file mode 100644
index 000000000..fcd92887c
--- /dev/null
+++ b/src/test/rustdoc-json/enums/variant_struct.rs
@@ -0,0 +1,11 @@
+// @has variant_struct.json "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\"
+pub enum EnumStruct {
+ // @has - "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\"
+ // @has - "$.index[*][?(@.name=='x')].kind" \"struct_field\"
+ // @has - "$.index[*][?(@.name=='y')].kind" \"struct_field\"
+ VariantS {
+ x: u32,
+ y: String,
+ },
+}
diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs
new file mode 100644
index 000000000..ac3e72e29
--- /dev/null
+++ b/src/test/rustdoc-json/enums/variant_tuple_struct.rs
@@ -0,0 +1,8 @@
+// @has variant_tuple_struct.json "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\"
+pub enum EnumTupleStruct {
+ // @has - "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\"
+ // @has - "$.index[*][?(@.name=='0')].kind" \"struct_field\"
+ // @has - "$.index[*][?(@.name=='1')].kind" \"struct_field\"
+ VariantA(u32, String),
+}
diff --git a/src/test/rustdoc-json/fn_pointer/abi.rs b/src/test/rustdoc-json/fn_pointer/abi.rs
new file mode 100644
index 000000000..eef20e60a
--- /dev/null
+++ b/src/test/rustdoc-json/fn_pointer/abi.rs
@@ -0,0 +1,25 @@
+// ignore-tidy-linelength
+
+#![feature(abi_vectorcall)]
+#![feature(c_unwind)]
+
+// @is abi.json "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\"
+pub type AbiRust = fn();
+
+// @is - "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}'
+pub type AbiC = extern "C" fn();
+
+// @is - "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}'
+pub type AbiSystem = extern "system" fn();
+
+// @is - "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}'
+pub type AbiCUnwind = extern "C-unwind" fn();
+
+// @is - "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}'
+pub type AbiSystemUnwind = extern "system-unwind" fn();
+
+// @is - "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""'
+pub type AbiVecorcall = extern "vectorcall" fn();
+
+// @is - "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""'
+pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn();
diff --git a/src/test/rustdoc-json/fn_pointer/generics.rs b/src/test/rustdoc-json/fn_pointer/generics.rs
new file mode 100644
index 000000000..646f720e6
--- /dev/null
+++ b/src/test/rustdoc-json/fn_pointer/generics.rs
@@ -0,0 +1,14 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @count generics.json "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"'
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\"
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }'
+// @count - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\"
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32;
diff --git a/src/test/rustdoc-json/fn_pointer/qualifiers.rs b/src/test/rustdoc-json/fn_pointer/qualifiers.rs
new file mode 100644
index 000000000..381922085
--- /dev/null
+++ b/src/test/rustdoc-json/fn_pointer/qualifiers.rs
@@ -0,0 +1,9 @@
+// @is qualifiers.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false
+// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false
+// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false
+pub type FnPointer = fn();
+
+// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true
+// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false
+// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false
+pub type UnsafePointer = unsafe fn();
diff --git a/src/test/rustdoc-json/fns/abi.rs b/src/test/rustdoc-json/fns/abi.rs
new file mode 100644
index 000000000..16b579130
--- /dev/null
+++ b/src/test/rustdoc-json/fns/abi.rs
@@ -0,0 +1,25 @@
+// ignore-tidy-linelength
+
+#![feature(abi_vectorcall)]
+#![feature(c_unwind)]
+
+// @is abi.json "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+pub fn abi_rust() {}
+
+// @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+pub extern "C" fn abi_c() {}
+
+// @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+pub extern "system" fn abi_system() {}
+
+// @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+pub extern "C-unwind" fn abi_c_unwind() {}
+
+// @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+pub extern "system-unwind" fn abi_system_unwind() {}
+
+// @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+pub extern "vectorcall" fn abi_vectorcall() {}
+
+// @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
diff --git a/src/test/rustdoc-json/fns/generic_args.rs b/src/test/rustdoc-json/fns/generic_args.rs
new file mode 100644
index 000000000..69150443c
--- /dev/null
+++ b/src/test/rustdoc-json/fns/generic_args.rs
@@ -0,0 +1,71 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @set foo = generic_args.json "$.index[*][?(@.name=='Foo')].id"
+pub trait Foo {}
+
+// @set generic_foo = generic_args.json "$.index[*][?(@.name=='GenericFoo')].id"
+pub trait GenericFoo<'a> {}
+
+// @is - "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]"
+// @count - "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
+// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null'
+// @count - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" '$foo'
+// @count - "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"'
+// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"'
+// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].inner" '"F"'
+pub fn generics<F: Foo>(f: F) {}
+
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]"
+// @count - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"'
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $foo
+// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"'
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"'
+// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $foo
+pub fn impl_trait(f: impl Foo) {}
+
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3
+// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3
+
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
+
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.inner.id" $generic_foo
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]"
+
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+pub fn where_clase<F, G, H>(f: F, g: G, h: H)
+where
+ F: Foo,
+ G: for<'a> GenericFoo<'a>,
+ for<'b> &'b H: Foo,
+{
+}
diff --git a/src/test/rustdoc-json/fns/generic_returns.rs b/src/test/rustdoc-json/fns/generic_returns.rs
new file mode 100644
index 000000000..1a0f33fe3
--- /dev/null
+++ b/src/test/rustdoc-json/fns/generic_returns.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @count generic_returns.json "$.index[*][?(@.name=='generic_returns')].inner.items[*]" 2
+
+// @set foo = - "$.index[*][?(@.name=='Foo')].id"
+pub trait Foo {}
+
+// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" []
+// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"'
+// @count - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1
+// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.inner.id" $foo
+pub fn get_foo() -> impl Foo {
+ Fooer {}
+}
+
+struct Fooer {}
+
+impl Foo for Fooer {}
diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs
new file mode 100644
index 000000000..e777fabaa
--- /dev/null
+++ b/src/test/rustdoc-json/fns/generics.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @set wham_id = generics.json "$.index[*][?(@.name=='Wham')].id"
+pub trait Wham {}
+
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" []
+// @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
+// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
+// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
+pub fn one_generic_param_fn<T: Wham>(w: T) {}
+
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" []
+// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
+// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
+// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
+// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id
+pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/src/test/rustdoc-json/fns/qualifiers.rs b/src/test/rustdoc-json/fns/qualifiers.rs
new file mode 100644
index 000000000..5cb3b43e6
--- /dev/null
+++ b/src/test/rustdoc-json/fns/qualifiers.rs
@@ -0,0 +1,33 @@
+// edition:2018
+
+// @is qualifiers.json "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false
+// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.const" false
+// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false
+pub fn nothing_fn() {}
+
+// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.async" false
+// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.const" false
+// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true
+pub unsafe fn unsafe_fn() {}
+
+// @is - "$.index[*][?(@.name=='const_fn')].inner.header.async" false
+// @is - "$.index[*][?(@.name=='const_fn')].inner.header.const" true
+// @is - "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false
+pub const fn const_fn() {}
+
+// @is - "$.index[*][?(@.name=='async_fn')].inner.header.async" true
+// @is - "$.index[*][?(@.name=='async_fn')].inner.header.const" false
+// @is - "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false
+pub async fn async_fn() {}
+
+// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async" true
+// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const" false
+// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true
+pub async unsafe fn async_unsafe_fn() {}
+
+// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async" false
+// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const" true
+// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true
+pub const unsafe fn const_unsafe_fn() {}
+
+// It's impossible for a function to be both const and async, so no test for that
diff --git a/src/test/rustdoc-json/generic-associated-types/gats.rs b/src/test/rustdoc-json/generic-associated-types/gats.rs
new file mode 100644
index 000000000..368ff8d8d
--- /dev/null
+++ b/src/test/rustdoc-json/generic-associated-types/gats.rs
@@ -0,0 +1,44 @@
+// ignore-tidy-linelength
+
+#![no_core]
+#![feature(generic_associated_types, lang_items, no_core)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Display {}
+
+// @has gats.json
+pub trait LendingIterator {
+ // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1
+ // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\"
+ // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1
+ // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.type.inner" \"Self\"
+ // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
+ // @count - "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1
+ type LendingItem<'a>: Display
+ where
+ Self: 'a;
+
+ // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\"
+ // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1
+ // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
+ // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\"
+ // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\"
+ fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
+}
+
+// @has gats.json
+pub trait Iterator {
+ // @count - "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0
+ // @count - "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0
+ // @count - "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1
+ type Item: Display;
+
+ // @is - "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\"
+ // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0
+ // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
+ // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\"
+ // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\"
+ fn next<'a>(&'a self) -> Self::Item;
+}
diff --git a/src/test/rustdoc-json/generic_impl.rs b/src/test/rustdoc-json/generic_impl.rs
new file mode 100644
index 000000000..ac68ba578
--- /dev/null
+++ b/src/test/rustdoc-json/generic_impl.rs
@@ -0,0 +1,24 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/97986>.
+
+// @has generic_impl.json
+// @has - "$.index[*][?(@.name=='f')]"
+// @has - "$.index[*][?(@.name=='AssocTy')]"
+// @has - "$.index[*][?(@.name=='AssocConst')]"
+
+pub mod m {
+ pub struct S;
+}
+
+pub trait F {
+ type AssocTy;
+ const AssocConst: usize;
+ fn f() -> m::S;
+}
+
+impl<T> F for T {
+ type AssocTy = u32;
+ const AssocConst: usize = 0;
+ fn f() -> m::S {
+ m::S
+ }
+}
diff --git a/src/test/rustdoc-json/glob_import.rs b/src/test/rustdoc-json/glob_import.rs
new file mode 100644
index 000000000..d7ac952d1
--- /dev/null
+++ b/src/test/rustdoc-json/glob_import.rs
@@ -0,0 +1,24 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/98003>.
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+// @has glob_import.json
+// @has - "$.index[*][?(@.name=='glob')]"
+// @has - "$.index[*][?(@.kind=='import')].inner.name" \"*\"
+
+
+mod m1 {
+ pub fn f() {}
+}
+mod m2 {
+ pub fn f(_: u8) {}
+}
+
+pub use m1::*;
+pub use m2::*;
+
+pub mod glob {
+ pub use *;
+}
diff --git a/src/test/rustdoc-json/impls/blanket_with_local.rs b/src/test/rustdoc-json/impls/blanket_with_local.rs
new file mode 100644
index 000000000..a3d55b35f
--- /dev/null
+++ b/src/test/rustdoc-json/impls/blanket_with_local.rs
@@ -0,0 +1,18 @@
+// Test for the ICE in rust/83718
+// A blanket impl plus a local type together shouldn't result in mismatched ID issues
+
+// @has blanket_with_local.json "$.index[*][?(@.name=='Load')]"
+pub trait Load {
+ // @has - "$.index[*][?(@.name=='load')]"
+ fn load() {}
+ // @has - "$.index[*][?(@.name=='write')]"
+ fn write(self) {}
+}
+
+impl<P> Load for P {
+ fn load() {}
+ fn write(self) {}
+}
+
+// @has - "$.index[*][?(@.name=='Wrapper')]"
+pub struct Wrapper {}
diff --git a/src/test/rustdoc-json/keyword.rs b/src/test/rustdoc-json/keyword.rs
new file mode 100644
index 000000000..78a843aca
--- /dev/null
+++ b/src/test/rustdoc-json/keyword.rs
@@ -0,0 +1,21 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/98002>.
+
+// Keywords should not be generated in rustdoc JSON output and this test
+// ensures it.
+
+#![feature(rustdoc_internals)]
+#![no_std]
+
+// @has keyword.json
+// @!has - "$.index[*][?(@.name=='match')]"
+// @has - "$.index[*][?(@.name=='foo')]"
+
+#[doc(keyword = "match")]
+/// this is a test!
+pub mod foo {}
+
+// @!has - "$.index[*][?(@.name=='hello')]"
+// @!has - "$.index[*][?(@.name=='bar')]"
+#[doc(keyword = "hello")]
+/// hello
+mod bar {}
diff --git a/src/test/rustdoc-json/lifetime/longest.rs b/src/test/rustdoc-json/lifetime/longest.rs
new file mode 100644
index 000000000..95b99599e
--- /dev/null
+++ b/src/test/rustdoc-json/lifetime/longest.rs
@@ -0,0 +1,33 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @is longest.json "$.index[*][?(@.name=='longest')].inner.generics.params[0].name" \"\'a\"
+// @is - "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}'
+// @is - "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}'
+// @count - "$.index[*][?(@.name=='longest')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='longest')].inner.generics.where_predicates" []
+
+// @count - "$.index[*][?(@.name=='longest')].inner.decl.inputs[*]" 2
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][0]" '"l"'
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][0]" '"r"'
+
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.mutable" false
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.mutable" false
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.mutable" false
+// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.type" '{"inner": "str", "kind": "primitive"}'
+
+pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
+ if l.len() > r.len() { l } else { r }
+}
diff --git a/src/test/rustdoc-json/lifetime/outlives.rs b/src/test/rustdoc-json/lifetime/outlives.rs
new file mode 100644
index 000000000..096dd7f7a
--- /dev/null
+++ b/src/test/rustdoc-json/lifetime/outlives.rs
@@ -0,0 +1,23 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @count outlives.json "$.index[*][?(@.name=='foo')].inner.generics.params[*]" 3
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.where_predicates" []
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[0].name" \"\'a\"
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[1].name" \"\'b\"
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].name" '"T"'
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[0].kind.lifetime.outlives" []
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.default" null
+// @count - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.mutable" false
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.lifetime" \"\'b\"
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.mutable" false
+// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.type" '{"inner": "T", "kind": "generic"}'
+pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/src/test/rustdoc-json/methods/abi.rs b/src/test/rustdoc-json/methods/abi.rs
new file mode 100644
index 000000000..07b01d03b
--- /dev/null
+++ b/src/test/rustdoc-json/methods/abi.rs
@@ -0,0 +1,55 @@
+// ignore-tidy-linelength
+
+#![feature(abi_vectorcall)]
+#![feature(c_unwind)]
+#![feature(no_core)]
+#![no_core]
+
+// @has abi.json "$.index[*][?(@.name=='Foo')]"
+pub struct Foo;
+
+impl Foo {
+ // @is - "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+ pub fn abi_rust() {}
+
+ // @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+ pub extern "C" fn abi_c() {}
+
+ // @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+ pub extern "system" fn abi_system() {}
+
+ // @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+ pub extern "C-unwind" fn abi_c_unwind() {}
+
+ // @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+ pub extern "system-unwind" fn abi_system_unwind() {}
+
+ // @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+ pub extern "vectorcall" fn abi_vectorcall() {}
+
+ // @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+ pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
+}
+
+pub trait Bar {
+ // @is - "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\"
+ fn trait_abi_rust() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+ extern "C" fn trait_abi_c() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+ extern "system" fn trait_abi_system() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+ extern "C-unwind" fn trait_abi_c_unwind() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+ extern "system-unwind" fn trait_abi_system_unwind() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+ extern "vectorcall" fn trait_abi_vectorcall() {}
+
+ // @is - "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+ extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {}
+}
diff --git a/src/test/rustdoc-json/methods/qualifiers.rs b/src/test/rustdoc-json/methods/qualifiers.rs
new file mode 100644
index 000000000..af36d36b6
--- /dev/null
+++ b/src/test/rustdoc-json/methods/qualifiers.rs
@@ -0,0 +1,37 @@
+// edition:2018
+
+pub struct Foo;
+
+impl Foo {
+ // @is qualifiers.json "$.index[*][?(@.name=='const_meth')].inner.header.async" false
+ // @is - "$.index[*][?(@.name=='const_meth')].inner.header.const" true
+ // @is - "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false
+ pub const fn const_meth() {}
+
+ // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.async" false
+ // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.const" false
+ // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false
+ pub fn nothing_meth() {}
+
+ // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.async" false
+ // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.const" false
+ // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true
+ pub unsafe fn unsafe_meth() {}
+
+ // @is - "$.index[*][?(@.name=='async_meth')].inner.header.async" true
+ // @is - "$.index[*][?(@.name=='async_meth')].inner.header.const" false
+ // @is - "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false
+ pub async fn async_meth() {}
+
+ // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async" true
+ // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const" false
+ // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true
+ pub async unsafe fn async_unsafe_meth() {}
+
+ // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async" false
+ // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const" true
+ // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true
+ pub const unsafe fn const_unsafe_meth() {}
+
+ // It's impossible for a method to be both const and async, so no test for that
+}
diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs
new file mode 100644
index 000000000..b0e717d8a
--- /dev/null
+++ b/src/test/rustdoc-json/nested.rs
@@ -0,0 +1,30 @@
+// edition:2018
+// compile-flags: --crate-version 1.0.0
+
+// @is nested.json "$.crate_version" \"1.0.0\"
+// @is - "$.index[*][?(@.name=='nested')].kind" \"module\"
+// @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true
+// @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1
+
+// @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\"
+// @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false
+// @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2
+pub mod l1 {
+
+ // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\"
+ // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false
+ // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1
+ // @set l3_id = - "$.index[*][?(@.name=='l3')].id"
+ // @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id
+ pub mod l3 {
+
+ // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\"
+ // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
+ // @set l4_id = - "$.index[*][?(@.name=='L4')].id"
+ // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
+ pub struct L4;
+ }
+ // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\"
+ // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false
+ pub use l3::L4;
+}
diff --git a/src/test/rustdoc-json/output_generics.rs b/src/test/rustdoc-json/output_generics.rs
new file mode 100644
index 000000000..d80656c7f
--- /dev/null
+++ b/src/test/rustdoc-json/output_generics.rs
@@ -0,0 +1,38 @@
+// compile-flags: --document-private-items --document-hidden-items
+
+// This is a regression test for #98009.
+
+// @has output_generics.json
+// @has - "$.index[*][?(@.name=='this_compiles')]"
+// @has - "$.index[*][?(@.name=='this_does_not')]"
+// @has - "$.index[*][?(@.name=='Events')]"
+// @has - "$.index[*][?(@.name=='Other')]"
+// @has - "$.index[*][?(@.name=='Trait')]"
+
+struct Events<R>(R);
+
+struct Other;
+
+pub trait Trait<T> {
+ fn handle(value: T) -> Self;
+}
+
+impl<T, U> Trait<U> for T where T: From<U> {
+ fn handle(_: U) -> Self { unimplemented!() }
+}
+
+impl<'a, R> Trait<&'a mut Events<R>> for Other {
+ fn handle(_: &'a mut Events<R>) -> Self { unimplemented!() }
+}
+
+fn this_compiles<'a, R>(value: &'a mut Events<R>) {
+ for _ in 0..3 {
+ Other::handle(&mut *value);
+ }
+}
+
+fn this_does_not<'a, R>(value: &'a mut Events<R>) {
+ for _ in 0..3 {
+ Other::handle(value);
+ }
+}
diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitive.rs
new file mode 100644
index 000000000..b84c2f7c6
--- /dev/null
+++ b/src/test/rustdoc-json/primitive.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![feature(rustdoc_internals)]
+
+#[doc(primitive = "usize")]
+mod usize {}
+
+// @set local_crate_id = primitive.json "$.index[*][?(@.name=='primitive')].crate_id"
+
+// @has - "$.index[*][?(@.name=='log10')]"
+// @!is - "$.index[*][?(@.name=='log10')].crate_id" $local_crate_id
+// @has - "$.index[*][?(@.name=='checked_add')]"
+// @!is - "$.index[*][?(@.name=='checked_add')]" $local_crate_id
+// @!has - "$.index[*][?(@.name=='is_ascii_uppercase')]"
diff --git a/src/test/rustdoc-json/primitive_overloading.rs b/src/test/rustdoc-json/primitive_overloading.rs
new file mode 100644
index 000000000..a10d5a837
--- /dev/null
+++ b/src/test/rustdoc-json/primitive_overloading.rs
@@ -0,0 +1,17 @@
+// compile-flags: --document-private-items
+
+// Regression test for <https://github.com/rust-lang/rust/issues/98006>.
+
+#![feature(rustdoc_internals)]
+#![feature(no_core)]
+
+#![no_core]
+
+// @has primitive_overloading.json
+// @has - "$.index[*][?(@.name=='usize')]"
+// @has - "$.index[*][?(@.name=='prim')]"
+
+#[doc(primitive = "usize")]
+/// This is the built-in type `usize`.
+mod prim {
+}
diff --git a/src/test/rustdoc-json/primitives.rs b/src/test/rustdoc-json/primitives.rs
new file mode 100644
index 000000000..fd04f04da
--- /dev/null
+++ b/src/test/rustdoc-json/primitives.rs
@@ -0,0 +1,22 @@
+#![feature(never_type)]
+
+// @has primitives.json "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\"
+// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\"
+pub type PrimNever = !;
+
+// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\"
+// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\"
+pub type PrimStr = str;
+
+// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\"
+// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\"
+pub type PrimBool = bool;
+
+// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\"
+// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\"
+pub type PrimChar = char;
+
+// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\"
+// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\"
+pub type PrimU8 = u8;
diff --git a/src/test/rustdoc-json/reexport/auxiliary/pub-struct.rs b/src/test/rustdoc-json/reexport/auxiliary/pub-struct.rs
new file mode 100644
index 000000000..4a835673a
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/auxiliary/pub-struct.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs
new file mode 100644
index 000000000..ba1cfd8a0
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_extern.rs
@@ -0,0 +1,18 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\"
+// @is glob_extern.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+mod mod1 {
+ extern "C" {
+ // @has - "$.index[*][?(@.name=='public_fn')].id"
+ pub fn public_fn();
+ // @!has - "$.index[*][?(@.name=='private_fn')]"
+ fn private_fn();
+ }
+}
+
+// @is - "$.index[*][?(@.kind=='import')].inner.glob" true
+pub use mod1::*;
diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs
new file mode 100644
index 000000000..e6a44748c
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_private.rs
@@ -0,0 +1,32 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @is glob_private.json "$.index[*][?(@.name=='mod1')].kind" \"module\"
+// @is glob_private.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+mod mod1 {
+ // @is - "$.index[*][?(@.name=='mod2')].kind" \"module\"
+ // @is - "$.index[*][?(@.name=='mod2')].inner.is_stripped" "true"
+ mod mod2 {
+ // @set m2pub_id = - "$.index[*][?(@.name=='Mod2Public')].id"
+ pub struct Mod2Public;
+
+ // @!has - "$.index[*][?(@.name=='Mod2Private')]"
+ struct Mod2Private;
+ }
+
+ // @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]"
+ pub use self::mod2::*;
+
+ // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id"
+ pub struct Mod1Public;
+ // @!has - "$.index[*][?(@.name=='Mod1Private')]"
+ struct Mod1Private;
+}
+
+// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]"
+pub use mod1::*;
+
+// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
+// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
new file mode 100644
index 000000000..7bf10a986
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
@@ -0,0 +1,17 @@
+#![feature(no_core)]
+#![no_core]
+
+// @is in_root_and_mod.json "$.index[*][?(@.name=='foo')].kind" \"module\"
+// @is in_root_and_mod.json "$.index[*][?(@.name=='foo')].inner.is_stripped" "true"
+mod foo {
+ // @has - "$.index[*][?(@.name=='Foo')]"
+ pub struct Foo;
+}
+
+// @has - "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]"
+pub use foo::Foo;
+
+pub mod bar {
+ // @has - "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]"
+ pub use crate::foo::Foo;
+}
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
new file mode 100644
index 000000000..2daadf762
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -0,0 +1,20 @@
+#![feature(no_core)]
+#![no_core]
+
+pub mod foo {
+ // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
+ // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+ pub struct Bar;
+}
+
+// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id"
+// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
+// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
+pub use foo::Bar;
+
+pub mod baz {
+ // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
+ // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
+ // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
+ pub use crate::foo::Bar;
+}
diff --git a/src/test/rustdoc-json/reexport/macro.rs b/src/test/rustdoc-json/reexport/macro.rs
new file mode 100644
index 000000000..b86614ffb
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/macro.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2
+
+// @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id"
+// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id
+#[macro_export]
+macro_rules! repro {
+ () => {};
+}
+
+// @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id"
+// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id
+pub use crate::repro as repro2;
diff --git a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs
new file mode 100644
index 000000000..327b0f45f
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -0,0 +1,18 @@
+// aux-build:pub-struct.rs
+
+// Test for the ICE in rust/83057
+// Am external type re-exported with different attributes shouldn't cause an error
+
+#![no_core]
+#![feature(no_core)]
+
+extern crate pub_struct as foo;
+
+#[doc(inline)]
+pub use foo::Foo;
+
+pub mod bar {
+ pub use foo::Foo;
+}
+
+// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2
diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs
new file mode 100644
index 000000000..36d6a50d3
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/private_two_names.rs
@@ -0,0 +1,17 @@
+// Test for the ICE in rust/83720
+// A pub-in-private type re-exported under two different names shouldn't cause an error
+
+#![no_core]
+#![feature(no_core)]
+
+// @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\"
+// @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true"
+mod style {
+ // @has - "$.index[*](?(@.name=='Color'))"
+ pub struct Color;
+}
+
+// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]"
+pub use style::Color;
+// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]"
+pub use style::Color as Colour;
diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs
new file mode 100644
index 000000000..2476399bd
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/rename_private.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @is rename_private.json "$.index[*][?(@.name=='inner')].kind" \"module\"
+// @is rename_private.json "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
+mod inner {
+ // @has - "$.index[*][?(@.name=='Public')]"
+ pub struct Public;
+}
+
+// @is - "$.index[*][?(@.kind=='import')].inner.name" \"NewName\"
+pub use inner::Public as NewName;
diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs
new file mode 100644
index 000000000..2dd438d22
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/rename_public.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id"
+// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id
+pub mod inner {
+ // @set public_id = - "$.index[*][?(@.name=='Public')].id"
+ // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+ pub struct Public;
+}
+// @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id"
+// @!has - "$.index[*][?(@.inner.name=='Public')]"
+// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id
+// @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\"
+pub use inner::Public as NewName;
diff --git a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
new file mode 100644
index 000000000..eedddd6a7
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -0,0 +1,15 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/97432>.
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+// @has same_type_reexported_more_than_once.json
+// @has - "$.index[*][?(@.name=='Trait')]"
+pub use inner::Trait;
+// @has - "$.index[*].inner[?(@.name=='Reexport')].id"
+pub use inner::Trait as Reexport;
+
+mod inner {
+ pub trait Trait {}
+}
diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs
new file mode 100644
index 000000000..5ec13e403
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/simple_private.rs
@@ -0,0 +1,15 @@
+// edition:2018
+#![no_core]
+#![feature(no_core)]
+
+// @is simple_private.json "$.index[*][?(@.name=='inner')].kind" \"module\"
+// @is simple_private.json "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
+mod inner {
+ // @set pub_id = - "$.index[*][?(@.name=='Public')].id"
+ pub struct Public;
+}
+
+// @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
+pub use inner::Public;
+
+// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs
new file mode 100644
index 000000000..2e4de301f
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/simple_public.rs
@@ -0,0 +1,18 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+
+// @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id"
+// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id
+pub mod inner {
+
+ // @set public_id = - "$.index[*][?(@.name=='Public')].id"
+ // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+ pub struct Public;
+}
+
+// @set import_id = - "$.index[*][?(@.inner.name=='Public')].id"
+// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id
+// @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\"
+pub use inner::Public;
diff --git a/src/test/rustdoc-json/return_private.rs b/src/test/rustdoc-json/return_private.rs
new file mode 100644
index 000000000..6b324d009
--- /dev/null
+++ b/src/test/rustdoc-json/return_private.rs
@@ -0,0 +1,15 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/96161>.
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+mod secret {
+ pub struct Secret;
+}
+
+// @is return_private.json "$.index[*][?(@.name=='get_secret')].kind" \"function\"
+// @is return_private.json "$.index[*][?(@.name=='get_secret')].inner.decl.output.inner.name" \"secret::Secret\"
+pub fn get_secret() -> secret::Secret {
+ secret::Secret
+}
diff --git a/src/test/rustdoc-json/stripped_modules.rs b/src/test/rustdoc-json/stripped_modules.rs
new file mode 100644
index 000000000..91f9f02ad
--- /dev/null
+++ b/src/test/rustdoc-json/stripped_modules.rs
@@ -0,0 +1,21 @@
+#![no_core]
+#![feature(no_core)]
+
+// @!has stripped_modules.json "$.index[*][?(@.name=='no_pub_inner')]"
+mod no_pub_inner {
+ fn priv_inner() {}
+}
+
+// @!has - "$.index[*][?(@.name=='pub_inner_unreachable')]"
+mod pub_inner_unreachable {
+ // @!has - "$.index[*][?(@.name=='pub_inner_1')]"
+ pub fn pub_inner_1() {}
+}
+
+// @has - "$.index[*][?(@.name=='pub_inner_reachable')]"
+mod pub_inner_reachable {
+ // @has - "$.index[*][?(@.name=='pub_inner_2')]"
+ pub fn pub_inner_2() {}
+}
+
+pub use pub_inner_reachable::pub_inner_2;
diff --git a/src/test/rustdoc-json/structs/plain_empty.rs b/src/test/rustdoc-json/structs/plain_empty.rs
new file mode 100644
index 000000000..a251caf4b
--- /dev/null
+++ b/src/test/rustdoc-json/structs/plain_empty.rs
@@ -0,0 +1,6 @@
+// @has plain_empty.json "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\"
+// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false
+// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.fields" []
+pub struct PlainEmpty {}
diff --git a/src/test/rustdoc-json/structs/tuple.rs b/src/test/rustdoc-json/structs/tuple.rs
new file mode 100644
index 000000000..4e510b398
--- /dev/null
+++ b/src/test/rustdoc-json/structs/tuple.rs
@@ -0,0 +1,5 @@
+// @has tuple.json "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\"
+// @has - "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true
+pub struct Tuple(u32, String);
diff --git a/src/test/rustdoc-json/structs/unit.rs b/src/test/rustdoc-json/structs/unit.rs
new file mode 100644
index 000000000..559d3068d
--- /dev/null
+++ b/src/test/rustdoc-json/structs/unit.rs
@@ -0,0 +1,5 @@
+// @has unit.json "$.index[*][?(@.name=='Unit')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Unit')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\"
+// @has - "$.index[*][?(@.name=='Unit')].inner.fields" []
+pub struct Unit;
diff --git a/src/test/rustdoc-json/structs/with_generics.rs b/src/test/rustdoc-json/structs/with_generics.rs
new file mode 100644
index 000000000..65cfe7eff
--- /dev/null
+++ b/src/test/rustdoc-json/structs/with_generics.rs
@@ -0,0 +1,14 @@
+use std::collections::HashMap;
+
+// @has with_generics.json "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\"
+// @has - "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true
+pub struct WithGenerics<T, U> {
+ stuff: Vec<T>,
+ things: HashMap<U, U>,
+}
diff --git a/src/test/rustdoc-json/structs/with_primitives.rs b/src/test/rustdoc-json/structs/with_primitives.rs
new file mode 100644
index 000000000..9e64317ec
--- /dev/null
+++ b/src/test/rustdoc-json/structs/with_primitives.rs
@@ -0,0 +1,10 @@
+// @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
+pub struct WithPrimitives<'a> {
+ num: u32,
+ s: &'a str,
+}
diff --git a/src/test/rustdoc-json/traits/has_body.rs b/src/test/rustdoc-json/traits/has_body.rs
new file mode 100644
index 000000000..44dacb1ee
--- /dev/null
+++ b/src/test/rustdoc-json/traits/has_body.rs
@@ -0,0 +1,21 @@
+// @has has_body.json "$.index[*][?(@.name=='Foo')]"
+pub trait Foo {
+ // @has - "$.index[*][?(@.name=='no_self')].inner.has_body" false
+ fn no_self();
+ // @has - "$.index[*][?(@.name=='move_self')].inner.has_body" false
+ fn move_self(self);
+ // @has - "$.index[*][?(@.name=='ref_self')].inner.has_body" false
+ fn ref_self(&self);
+
+ // @has - "$.index[*][?(@.name=='no_self_def')].inner.has_body" true
+ fn no_self_def() {}
+ // @has - "$.index[*][?(@.name=='move_self_def')].inner.has_body" true
+ fn move_self_def(self) {}
+ // @has - "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true
+ fn ref_self_def(&self) {}
+}
+
+pub trait Bar: Clone {
+ // @has - "$.index[*][?(@.name=='method')].inner.has_body" false
+ fn method(&self, param: usize);
+}
diff --git a/src/test/rustdoc-json/traits/implementors.rs b/src/test/rustdoc-json/traits/implementors.rs
new file mode 100644
index 000000000..f7f03d987
--- /dev/null
+++ b/src/test/rustdoc-json/traits/implementors.rs
@@ -0,0 +1,19 @@
+#![feature(no_core)]
+#![no_core]
+
+// @set wham = implementors.json "$.index[*][?(@.name=='Wham')].id"
+// @count - "$.index[*][?(@.name=='Wham')].inner.implementations[*]" 1
+// @set gmWham = - "$.index[*][?(@.name=='Wham')].inner.implementations[0]"
+pub trait Wham {}
+
+// @count - "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[*]" 1
+// @is - "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[0]" $gmWham
+// @set gm = - "$.index[*][?(@.name=='Wham')].id"
+
+// jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we
+// just check it isn't pointing to the type, but when you port to jsondocck-ng
+// check what the impl item is
+// @!is - "$.index[*][?(@.name=='Wham')].inner.implementations[0]" $gm
+pub struct GeorgeMichael {}
+
+impl Wham for GeorgeMichael {}
diff --git a/src/test/rustdoc-json/traits/supertrait.rs b/src/test/rustdoc-json/traits/supertrait.rs
new file mode 100644
index 000000000..486a8e713
--- /dev/null
+++ b/src/test/rustdoc-json/traits/supertrait.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![feature(lang_items)]
+#![no_core]
+
+// @set loud_id = supertrait.json "$.index[*][?(@.name=='Loud')].id"
+pub trait Loud {}
+
+// @set very_loud_id = - "$.index[*][?(@.name=='VeryLoud')].id"
+// @count - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.inner.id" $loud_id
+pub trait VeryLoud: Loud {}
+
+// @set sounds_good_id = - "$.index[*][?(@.name=='SoundsGood')].id"
+pub trait SoundsGood {}
+
+// @count - "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2
+// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.inner.id" $very_loud_id
+// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.inner.id" $sounds_good_id
+pub trait MetalBand: VeryLoud + SoundsGood {}
+
+// @count - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2
+// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.inner.id" $very_loud_id
+// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.inner.id" $sounds_good_id
+pub trait DnabLatem: SoundsGood + VeryLoud {}
diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs
new file mode 100644
index 000000000..f53dc03f4
--- /dev/null
+++ b/src/test/rustdoc-json/type/dyn.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items" 1
+// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
+// @is - "$.index[*][?(@.name=='dyn')].inner.items[0]" $sync_int_gen
+
+// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
+// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\"
+// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}"
+// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
+pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs
new file mode 100644
index 000000000..e0d1e9649
--- /dev/null
+++ b/src/test/rustdoc-json/type/fn_lifetime.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+
+// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
+
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1
+// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
+// @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
+// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\"
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+
+pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
+
+// @is fn_lifetime.json "$.index[*][?(@.name=='ForAll')].kind" \"typedef\"
+// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\"
+// @has - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime"
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
+// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/src/test/rustdoc-json/type/generic_default.rs b/src/test/rustdoc-json/type/generic_default.rs
new file mode 100644
index 000000000..b6bb6dcc5
--- /dev/null
+++ b/src/test/rustdoc-json/type/generic_default.rs
@@ -0,0 +1,33 @@
+// ignore-tidy-linelength
+
+// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id"
+pub enum Result<T, E> {
+ Ok(T),
+ Err(E),
+}
+
+// @set my_error = - "$.index[*][?(@.name=='MyError')].id"
+pub struct MyError {}
+
+// @is - "$.index[*][?(@.name=='MyResult')].kind" \"typedef\"
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\"
+// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type"
+// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type"
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error
+// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" []
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\"
+// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\"
+pub type MyResult<T, E = MyError> = Result<T, E>;
diff --git a/src/test/rustdoc-json/unions/impl.rs b/src/test/rustdoc-json/unions/impl.rs
new file mode 100644
index 000000000..0388b4a8c
--- /dev/null
+++ b/src/test/rustdoc-json/unions/impl.rs
@@ -0,0 +1,15 @@
+#![no_std]
+
+// @has impl.json "$.index[*][?(@.name=='Ux')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Ux')].kind" \"union\"
+pub union Ux {
+ a: u32,
+ b: u64
+}
+
+// @has - "$.index[*][?(@.name=='Num')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Num')].kind" \"trait\"
+pub trait Num {}
+
+// @count - "$.index[*][?(@.name=='Ux')].inner.impls" 1
+impl Num for Ux {}
diff --git a/src/test/rustdoc-json/unions/union.rs b/src/test/rustdoc-json/unions/union.rs
new file mode 100644
index 000000000..ac2eb7977
--- /dev/null
+++ b/src/test/rustdoc-json/unions/union.rs
@@ -0,0 +1,7 @@
+// @has union.json "$.index[*][?(@.name=='Union')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Union')].kind" \"union\"
+// @!has - "$.index[*][?(@.name=='Union')].inner.struct_type"
+pub union Union {
+ int: i32,
+ float: f32,
+}