From 3b8de99553d3c6535dc50f2eea8ff5cce97b3ec3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Mar 2021 00:16:52 +0100 Subject: [PATCH 1/2] Support case insensitive systems for file generation --- src/librustdoc/config.rs | 5 + src/librustdoc/formats/renderer.rs | 81 +++++++++++++- src/librustdoc/html/layout.rs | 36 ++++++ src/librustdoc/html/render/context.rs | 137 ++++++++++++++++++++--- src/librustdoc/html/render/mod.rs | 32 +++++- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/static/main.js | 33 +++--- src/librustdoc/html/static/storage.js | 5 + src/librustdoc/json/mod.rs | 3 +- src/librustdoc/lib.rs | 7 ++ 10 files changed, 300 insertions(+), 41 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index ecb6378f31fb4..67526fd1ec4b4 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -265,6 +265,9 @@ crate struct RenderOptions { crate document_hidden: bool, /// If `true`, generate a JSON file in the crate folder instead of HTML redirection files. crate generate_redirect_map: bool, + /// If this option is set to `true`, HTML files will be generated as it would on a + /// case-insensitive file system. + crate generate_case_insensitive: bool, crate unstable_features: rustc_feature::UnstableFeatures, } @@ -580,6 +583,7 @@ impl Options { let document_hidden = matches.opt_present("document-hidden-items"); let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); + let generate_case_insensitive = matches.opt_present("generate-case-insensitive"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -638,6 +642,7 @@ impl Options { document_private, document_hidden, generate_redirect_map, + generate_case_insensitive, unstable_features: rustc_feature::UnstableFeatures::from_environment( crate_name.as_deref(), ), diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 4e0f3a4e3c317..68f1aeb91eba1 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,10 +1,16 @@ +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::ty::TyCtxt; use rustc_span::{edition::Edition, Symbol}; +use std::fs; +use std::io::Write; +use std::path::Path; + use crate::clean; use crate::config::RenderOptions; use crate::error::Error; use crate::formats::cache::Cache; +use crate::html::render::print_item::item_path; /// Allows for different backends to rustdoc to be used with the `run_format()` function. Each /// backend renderer has hooks for initialization, documenting an item, entering and exiting a @@ -26,6 +32,7 @@ crate trait FormatRenderer<'tcx>: Sized { edition: Edition, cache: Cache, tcx: TyCtxt<'tcx>, + case_insensitive_conflicts: Option>, ) -> Result<(Self, clean::Crate), Error>; /// Make a new renderer to render a child of the item currently being rendered. @@ -52,6 +59,71 @@ crate trait FormatRenderer<'tcx>: Sized { fn cache(&self) -> &Cache; } +fn handle_module(dst: &Path, item: &clean::Item, paths_map: &mut FxHashMap) { + // modules are special because they add a namespace. We also need to + // recurse into the items of the module as well. + let name = item.name.as_ref().unwrap().to_string(); + if name.is_empty() { + panic!("Unexpected module with empty name"); + } + let module = match *item.kind { + clean::StrippedItem(box clean::ModuleItem(ref m)) | clean::ModuleItem(ref m) => m, + _ => unreachable!(), + }; + let mod_path = dst.join(&name); + for it in &module.items { + if it.is_mod() { + handle_module(&mod_path, it, paths_map); + } else if it.name.is_some() && !it.is_extern_crate() { + let name = it.name.as_ref().unwrap(); + let item_type = it.type_(); + let file_name = &item_path(item_type, &name.as_str()); + let insensitive_path = mod_path.join(file_name).display().to_string(); + + let entry = paths_map.entry(insensitive_path.to_lowercase()).or_insert(0); + *entry += 1; + } + } +} + +fn build_case_insensitive_map( + krate: &clean::Crate, + options: &RenderOptions, +) -> Option> { + let mut paths_map: FxHashMap = FxHashMap::default(); + + handle_module(&options.output, &krate.module, &mut paths_map); + Some(paths_map.into_iter().filter(|(_, count)| *count > 1).map(|(path, _)| path).collect()) +} + +fn check_if_case_insensitive(dst: &Path) -> bool { + fn create_and_write(dst: &Path, content: &str) { + if let Ok(mut f) = fs::OpenOptions::new().write(true).create(true).truncate(true).open(dst) + { + // Ignoring potential errors. + let _ = f.write(content.as_bytes()); + } + } + fn compare_content(dst: &Path, content: &str) -> bool { + fs::read_to_string(dst).unwrap_or_else(|_| String::new()).as_str() == content + } + + let path1 = dst.join("___a.tmp"); + let content1 = "a"; + let path2 = dst.join("___A.tmp"); + let content2 = "A"; + + create_and_write(&path1, content1); + create_and_write(&path1, content2); + + let res = compare_content(&path1, content1) && compare_content(&path2, content2); + // We ignore the errors when removing the files. + let _ = fs::remove_file(&path1); + let _ = fs::remove_file(&path2); + + res +} + /// Main method for rendering a crate. crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( krate: clean::Crate, @@ -63,9 +135,16 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( ) -> Result<(), Error> { let prof = &tcx.sess.prof; + let case_insensitive_conflicts = + if options.generate_case_insensitive || check_if_case_insensitive(&options.output) { + build_case_insensitive_map(&krate, &options) + } else { + None + }; + let (mut format_renderer, krate) = prof .extra_verbose_generic_activity("create_renderer", T::descr()) - .run(|| T::init(krate, options, edition, cache, tcx))?; + .run(|| T::init(krate, options, edition, cache, tcx, case_insensitive_conflicts))?; // Render the crate documentation let crate_name = krate.name; diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 68d70f27c8c78..a5ce727913105 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -222,6 +222,42 @@ crate fn render( ) } +/// Since this is a "conflict file" on case insensitive file system, it'll be loaded by JS instead +/// of being loaded directly. Which is why we need to modify its output a bit. +crate fn conflict_layout(page: &Page<'_>, sidebar: S, t: T) -> String +where + S: FnOnce(&mut Buffer) -> Option, +{ + let content = Buffer::html().to_display(t).to_string(); + let mut sidebar_buf = Buffer::html(); + let script_src = sidebar(&mut sidebar_buf); + format!( + "\ +document.getElementById('main').innerHTML = \"{content}\";\ +document.getElementsByClassName('sidebar')[0].innerHTML += \"{sidebar}\";\ +document.title = \"{title}\";\ +window.initSidebarVars();\ +rustdocInit();{script}", + content = content.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n"), + title = page.title.replace("\\", "\\\\").replace("\"", "\\\""), + sidebar = sidebar_buf + .into_inner() + .replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\n", "\\n"), + script = if let Some(script_src) = script_src { + format!( + "var script = document.createElement('script');\ + script.src = {:?};\ + document.body.appendChild(script);", + script_src, + ) + } else { + String::new() + }, + ) +} + crate fn redirect(url: &str) -> String { // ", + entries + )) + }, + &style_files, + ); + self.shared.fs.write(&path, v.as_bytes())?; + } + } + // Flush pending errors. Rc::get_mut(&mut self.shared).unwrap().fs.close(); let nb_errors = self.shared.errors.iter().map(|err| diag.struct_err(&err).emit()).count(); @@ -548,7 +643,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { info!("Recursing into {}", self.dst.display()); - let buf = self.render_item(item, false); + let buf = self.render_item(item, false, false); // buf will be empty if the module is stripped and there is no redirect for it if !buf.is_empty() { self.shared.ensure_dir(&self.dst)?; @@ -591,15 +686,21 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.render_redirect_pages = item.is_stripped(); } - let buf = self.render_item(&item, true); + let name = item.name.as_ref().unwrap(); + let item_type = item.type_(); + let file_name = &item_path(item_type, &name.as_str()); + let joint_dst = self.dst.join(file_name); + let is_conflict_path = self.is_conflict_path(&joint_dst); + + let buf = self.render_item(&item, true, is_conflict_path); // buf will be empty if the item is stripped and there is no redirect for it if !buf.is_empty() { - let name = item.name.as_ref().unwrap(); - let item_type = item.type_(); - let file_name = &item_path(item_type, &name.as_str()); self.shared.ensure_dir(&self.dst)?; - let joint_dst = self.dst.join(file_name); - self.shared.fs.write(&joint_dst, buf.as_bytes())?; + if is_conflict_path { + self.write_unconflicted_path(joint_dst, buf.as_bytes(), file_name)?; + } else { + self.shared.fs.write(&joint_dst, buf.as_bytes())?; + } if !self.render_redirect_pages { self.shared.all.borrow_mut().append(full_path(self, &item), &item_type); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 07bd26a4c5ebe..79a54f6b8c45d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -24,12 +24,12 @@ //! both occur before the crate is rendered. crate mod cache; +crate mod print_item; #[cfg(test)] mod tests; mod context; -mod print_item; mod write_shared; crate use context::*; @@ -130,6 +130,12 @@ crate struct SharedContext<'tcx> { /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of /// the crate. redirections: Option>>, + /// This map contains the conflicts of paths on case insensitive file systems. + /// + /// The HashMap key is the conflict path (the path in lowercase). + /// The value is a tuple composed of a vector of the original path (it is used when generating + /// the HTML page to know which file to load depending on the URL) and of the root path. + case_insensitive_conflicts: Option, String)>>>, } impl SharedContext<'_> { @@ -1720,6 +1726,19 @@ fn render_impl( } fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { + print_sidebar_full(cx, it, buffer, true); +} + +/// Unfortunately, we cannot simply insert a script with `innerHTML`, otherwise it'll simply be +/// ignored. To go around this limitation, we have to manipulate it as DOM element. +/// +/// This function returns the "script" src in case it wasn't put in the buffer. +fn print_sidebar_full( + cx: &Context<'_>, + it: &clean::Item, + buffer: &mut Buffer, + use_script: bool, +) -> Option { let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 }; if it.is_struct() @@ -1817,14 +1836,19 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { ty = it.type_(), path = relpath ); - if parentlen == 0 { + let ret = if parentlen == 0 { // There is no sidebar-items.js beyond the crate root path // FIXME maybe dynamic crate loading can be merged here - } else { + None + } else if use_script { write!(buffer, "", path = relpath); - } + None + } else { + Some(format!("{path}sidebar-items.js", path = relpath)) + }; // Closes sidebar-elems div. buffer.write_str(""); + ret } fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index cc93e55fc676e..3cf56ca4c9e95 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1138,7 +1138,7 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String { s } -pub(super) fn item_path(ty: ItemType, name: &str) -> String { +crate fn item_path(ty: ItemType, name: &str) -> String { match ty { ItemType::Module => format!("{}index.html", ensure_trailing_slash(name)), _ => format!("{}.{}.html", ty, name), diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index da2952bbebdbe..083b175d23f73 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2,7 +2,7 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass */ /* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */ -/* global switchTheme, useSystemTheme */ +/* global switchTheme, useSystemTheme, getNakedUrl */ if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { @@ -38,13 +38,7 @@ if (!DOMTokenList.prototype.remove) { }; } -(function () { - var rustdocVars = document.getElementById("rustdoc-vars"); - if (rustdocVars) { - window.rootPath = rustdocVars.attributes["data-root-path"].value; - window.currentCrate = rustdocVars.attributes["data-current-crate"].value; - window.searchJS = rustdocVars.attributes["data-search-js"].value; - } +function initSidebarVars() { var sidebarVars = document.getElementById("sidebar-vars"); if (sidebarVars) { window.sidebarCurrent = { @@ -53,6 +47,16 @@ if (!DOMTokenList.prototype.remove) { relpath: sidebarVars.attributes["data-relpath"].value, }; } +} + +(function () { + var rustdocVars = document.getElementById("rustdoc-vars"); + if (rustdocVars) { + window.rootPath = rustdocVars.attributes["data-root-path"].value; + window.currentCrate = rustdocVars.attributes["data-current-crate"].value; + window.searchJS = rustdocVars.attributes["data-search-js"].value; + } + initSidebarVars(); }()); // Gets the human-readable string for the virtual-key code of the @@ -96,11 +100,6 @@ function getThemePickerElement() { return document.getElementById(THEME_PICKER_ELEMENT_ID); } -// Returns the current URL without any query parameter or hash. -function getNakedUrl() { - return window.location.href.split("?")[0].split("#")[0]; -} - // Sets the focus on the search bar at the top of the page function focusSearchBar() { getSearchInput().focus(); @@ -170,7 +169,7 @@ function hideThemeButtonState() { }); }()); -(function() { +function rustdocInit() { "use strict"; // This mapping table should match the discriminants of @@ -2149,7 +2148,7 @@ function hideThemeButtonState() { sidebar.appendChild(div); } } - } + }; // delayed sidebar rendering. window.initSidebarItems = function(items) { @@ -3060,4 +3059,6 @@ function hideThemeButtonState() { onHashChange(null); window.onhashchange = onHashChange; setupSearchLoader(); -}()); +} + +rustdocInit(); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index c68128516d252..8a5b8ac74ec07 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -31,6 +31,11 @@ function getSettingValue(settingName) { return null; } +// Returns the current URL without any query parameter or hash. +function getNakedUrl() { + return window.location.href.split("?")[0].split("#")[0]; +} + var localStoredTheme = getSettingValue("theme"); var savedHref = []; diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index db3a0c5ceb167..88debeceb8133 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -11,7 +11,7 @@ use std::fs::File; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::{edition::Edition, Symbol}; @@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { _edition: Edition, cache: Cache, tcx: TyCtxt<'tcx>, + _case_insensitive_conflicts: Option>, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); Ok(( diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dabc21e3a447c..7105b979c52d3 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -527,6 +527,13 @@ fn opts() -> Vec { unstable("print", |o| { o.optmulti("", "print", "Rustdoc information to print on stdout", "[unversioned-files]") }), + unstable("generate-case-insensitive", |o| { + o.optflag( + "", + "generate-case-insensitive", + "Force the generation of HTML to be case insensitive", + ) + }), ] } From 106da77c97b811e5b269893147dedffebfadab69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Mar 2021 20:33:28 +0200 Subject: [PATCH 2/2] Add tests for case insensitive support --- src/bootstrap/test.rs | 23 +++++++++++++++---- src/test/rustdoc-gui/basic-code.goml | 2 +- src/test/rustdoc-gui/basic.goml | 2 +- .../rustdoc-gui/check_info_sign_position.goml | 2 +- src/test/rustdoc-gui/code-sidebar-toggle.goml | 2 +- .../rustdoc-gui/insensitive-case-check.goml | 7 ++++++ src/test/rustdoc-gui/insensitive-test.rs | 19 +++++++++++++++ src/test/rustdoc-gui/list_code_block.goml | 2 +- src/test/rustdoc-gui/nojs-attr-pos.goml | 2 +- src/test/rustdoc-gui/search-input-mobile.goml | 2 +- src/test/rustdoc-gui/shortcuts.goml | 2 +- src/test/rustdoc-gui/theme-change.goml | 2 +- src/test/rustdoc-gui/toggle-docs.goml | 2 +- .../rustdoc-gui/trait-sidebar-item-order.goml | 2 +- src/test/rustdoc/insensitive-case.rs | 18 +++++++++++++++ 15 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 src/test/rustdoc-gui/insensitive-case-check.goml create mode 100644 src/test/rustdoc-gui/insensitive-test.rs create mode 100644 src/test/rustdoc/insensitive-case.rs diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 86d940cd733da..62c458fe81770 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -734,9 +734,24 @@ impl Step for RustdocGUI { } let out_dir = builder.test_out(self.target).join("rustdoc-gui"); - let mut command = builder.rustdoc_cmd(self.compiler); - command.arg("src/test/rustdoc-gui/lib.rs").arg("-o").arg(&out_dir); - builder.run(&mut command); + + for file in fs::read_dir("src/test/rustdoc-gui").unwrap() { + let file = file.unwrap(); + let file_name = file.file_name(); + + if !file_name.to_str().unwrap().ends_with(".rs") { + continue; + } + + let mut command = builder.rustdoc_cmd(self.compiler); + command + .arg(&Path::new("src/test/rustdoc-gui").join(file_name)) + .arg("-o") + .arg(&out_dir) + .arg("-Zunstable-options") + .arg("--generate-case-insensitive"); + builder.run(&mut command); + } for file in fs::read_dir("src/test/rustdoc-gui").unwrap() { let file = file.unwrap(); @@ -750,7 +765,7 @@ impl Step for RustdocGUI { command .arg("src/tools/rustdoc-gui/tester.js") .arg("--doc-folder") - .arg(out_dir.join("test_docs")) + .arg(&out_dir) .arg("--test-file") .arg(file_path); builder.run(&mut command); diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml index 8da465662547a..d014ed60eb039 100644 --- a/src/test/rustdoc-gui/basic-code.goml +++ b/src/test/rustdoc-gui/basic-code.goml @@ -1,3 +1,3 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html click: ".srclink" assert: (".line-numbers", 1) diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml index ed23300860b70..44fcec3393744 100644 --- a/src/test/rustdoc-gui/basic.goml +++ b/src/test/rustdoc-gui/basic.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html assert: ("#functions") goto: ./struct.Foo.html assert: ("div.type-decl") diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml index 9aa72a3ad53e7..d64ee0261370c 100644 --- a/src/test/rustdoc-gui/check_info_sign_position.goml +++ b/src/test/rustdoc-gui/check_info_sign_position.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html goto: ./fn.check_list_code_block.html // If the codeblock is the first element of the docblock, the information tooltip must have // have some top margin to avoid going over the toggle (the "[+]"). diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml index 69fc860244b7b..7e7003d4340a3 100644 --- a/src/test/rustdoc-gui/code-sidebar-toggle.goml +++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html click: ".srclink" click: "#sidebar-toggle" wait-for: 500 diff --git a/src/test/rustdoc-gui/insensitive-case-check.goml b/src/test/rustdoc-gui/insensitive-case-check.goml new file mode 100644 index 0000000000000..d25fbfac70b7b --- /dev/null +++ b/src/test/rustdoc-gui/insensitive-case-check.goml @@ -0,0 +1,7 @@ +goto: file://|DOC_PATH|/insensitive_case_docs/struct.ab.html +// Checks that the sidebar was filled. +wait-for: ".sidebar-elems > .items > .sidebar-title" +// Checks that the content has been loaded +assert: ".impl-items > h4" +// Checks that the collapse toggles have been generated as expected +assert: ".impl-items > h4 > .collapse-toggle" diff --git a/src/test/rustdoc-gui/insensitive-test.rs b/src/test/rustdoc-gui/insensitive-test.rs new file mode 100644 index 0000000000000..6f63c32127a51 --- /dev/null +++ b/src/test/rustdoc-gui/insensitive-test.rs @@ -0,0 +1,19 @@ +//! The point of this crate is to test the insensitive case handling. + +#![crate_name = "insensitive_case_docs"] + +#![allow(non_camel_case_types)] + +/// This is ab. +pub struct ab; + +impl ab { + pub fn foo(&self) {} +} + +/// This is another Ab! +pub struct Ab; + +impl Ab { + pub fn bar(&self) {} +} diff --git a/src/test/rustdoc-gui/list_code_block.goml b/src/test/rustdoc-gui/list_code_block.goml index 6f2465a5587f2..7d3490e9d9410 100644 --- a/src/test/rustdoc-gui/list_code_block.goml +++ b/src/test/rustdoc-gui/list_code_block.goml @@ -1,3 +1,3 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html goto: ./fn.check_list_code_block.html assert: ("pre.rust.fn") diff --git a/src/test/rustdoc-gui/nojs-attr-pos.goml b/src/test/rustdoc-gui/nojs-attr-pos.goml index 35daa4cb9e322..0e87c93ab3b32 100644 --- a/src/test/rustdoc-gui/nojs-attr-pos.goml +++ b/src/test/rustdoc-gui/nojs-attr-pos.goml @@ -1,5 +1,5 @@ // Check that the attributes are well positioned when javascript is disabled (since // there is no toggle to display) javascript: false -goto: file://|DOC_PATH|/struct.Foo.html +goto: file://|DOC_PATH|/test_docs/struct.Foo.html assert: (".attributes", {"margin-left": "0px"}) diff --git a/src/test/rustdoc-gui/search-input-mobile.goml b/src/test/rustdoc-gui/search-input-mobile.goml index 3eec3459a6393..5c95db70aecdd 100644 --- a/src/test/rustdoc-gui/search-input-mobile.goml +++ b/src/test/rustdoc-gui/search-input-mobile.goml @@ -1,6 +1,6 @@ // Test to ensure that you can click on the search input, whatever the width. // The PR which fixed it is: https://github.com/rust-lang/rust/pull/81592 -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html size: (463, 700) // We first check that the search input isn't already focused. assert-false: ("input.search-input:focus") diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml index c35b48f57f4d2..884c38d85fbdb 100644 --- a/src/test/rustdoc-gui/shortcuts.goml +++ b/src/test/rustdoc-gui/shortcuts.goml @@ -1,5 +1,5 @@ // Check that the various shortcuts are working. -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html // We first check that the search input isn't already focused. assert-false: "input.search-input:focus" press-key: "s" diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml index 5bd65f61f4905..bc9063edd1e7a 100644 --- a/src/test/rustdoc-gui/theme-change.goml +++ b/src/test/rustdoc-gui/theme-change.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html click: "#theme-picker" click: "#theme-choices > button:first-child" wait-for: 500 diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index 1ded33f659d3c..93bdf41a6a09e 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/index.html +goto: file://|DOC_PATH|/test_docs/index.html click: "#toggle-all-docs" wait-for: 5000 assert: ("#main > div.docblock.hidden-by-usual-hider") diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml index 914486e1c281d..2e9f85336ecd8 100644 --- a/src/test/rustdoc-gui/trait-sidebar-item-order.goml +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -1,4 +1,4 @@ -goto: file://|DOC_PATH|/trait.AnotherOne.html +goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html assert: (".sidebar-links a:nth-of-type(1)", "another") assert: (".sidebar-links a:nth-of-type(2)", "func1") assert: (".sidebar-links a:nth-of-type(3)", "func2") diff --git a/src/test/rustdoc/insensitive-case.rs b/src/test/rustdoc/insensitive-case.rs new file mode 100644 index 0000000000000..a64e794adcf01 --- /dev/null +++ b/src/test/rustdoc/insensitive-case.rs @@ -0,0 +1,18 @@ +// compile-flags: -Zunstable-options --generate-case-insensitive + +#![crate_name = "foo"] + +// @!has 'foo/struct.Aa.html' +// @has 'foo/struct.aa.html' +// @!has 'foo/struct.aa.html' '//h4[@id="method.new"]' +pub struct aa; + +impl aa { + pub fn foo(&self) {} +} + +pub struct Aa; + +impl Aa { + pub fn foo(&self) {} +}