diff --git a/compiler/rustc_error_codes/src/error_codes/E0729.md b/compiler/rustc_error_codes/src/error_codes/E0729.md index 74f89080b91a1..3891745b5008e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0729.md +++ b/compiler/rustc_error_codes/src/error_codes/E0729.md @@ -1,3 +1,5 @@ +#### Note: this error code is no longer emitted by the compiler + Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow checker for NLL uncovered some bugs in the old borrow checker, which in some diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 136c360201e61..621704335e432 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -978,6 +978,7 @@ impl Handler { self.inner.borrow_mut().span_bug(span, msg) } + /// For documentation on this, see `Session::delay_span_bug`. #[track_caller] pub fn delay_span_bug( &self, @@ -1529,6 +1530,7 @@ impl HandlerInner { self.emit_diagnostic(diag.set_span(sp)); } + /// For documentation on this, see `Session::delay_span_bug`. #[track_caller] fn delay_span_bug( &mut self, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 01fe72de61258..5ca4d260179ce 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -1,3 +1,13 @@ +/// A macro for triggering an ICE. +/// Calling `bug` instead of panicking will result in a nicer error message and should +/// therefore be prefered over `panic`/`unreachable` or others. +/// +/// If you have a span available, you should use [`span_bug`] instead. +/// +/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// +/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug +/// [`span_bug`]: crate::span_bug #[macro_export] macro_rules! bug { () => ( $crate::bug!("impossible case reached") ); @@ -8,6 +18,14 @@ macro_rules! bug { }); } +/// A macro for triggering an ICE with a span. +/// Calling `span_bug!` instead of panicking will result in a nicer error message and point +/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger +/// ICEs. +/// +/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// +/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug #[macro_export] macro_rules! span_bug { ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) }); diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index fd7045d6a03f2..b73ae59390535 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -35,8 +35,7 @@ fn opt_span_bug_fmt>( (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), (None, _) => panic_any(msg), } - }); - unreachable!(); + }) } /// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1fc1ffd6cb6ed..9f436783ceda6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1503,12 +1503,13 @@ impl<'a> Parser<'a> { prior_type_ascription: self.last_type_ascription, }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) - } else if self.check(&token::OpenDelim(Delimiter::Brace)) && - let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) { - if qself.is_some() { - self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); - } - return expr; + } else if self.check(&token::OpenDelim(Delimiter::Brace)) + && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) + { + if qself.is_some() { + self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); + } + return expr; } else { (path.span, ExprKind::Path(qself, path)) }; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a87e820386e7c..1ccfc59f7a9d6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -35,6 +35,7 @@ use std::hash::Hash; use std::iter; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; +use std::sync::LazyLock; pub mod sigpipe; @@ -1322,7 +1323,12 @@ mod opt { unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } } - +static EDITION_STRING: LazyLock = LazyLock::new(|| { + format!( + "Specify which edition of the compiler to use when compiling code. \ +The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}." + ) +}); /// Returns the "short" subset of the rustc command line options, /// including metadata for each option, such as whether the option is /// part of the stable long-term interface for rustc. @@ -1355,7 +1361,7 @@ pub fn rustc_short_optgroups() -> Vec { opt::opt_s( "", "edition", - "Specify which edition of the compiler to use when compiling code.", + &*EDITION_STRING, EDITION_NAME_LIST, ), opt::multi_s( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4a3d29414d6e5..1b2e8d9dc707b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -590,7 +590,19 @@ impl Session { pub fn warn(&self, msg: impl Into) { self.diagnostic().warn(msg) } - /// Delay a span_bug() call until abort_if_errors() + + /// Ensures that compilation cannot succeed. + /// + /// If this function has been called but no errors have been emitted and + /// compilation succeeds, it will cause an internal compiler error (ICE). + /// + /// This can be used in code paths that should never run on successful compilations. + /// For example, it can be used to create an [`ErrorGuaranteed`] + /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission directly). + /// + /// If no span is available, use [`DUMMY_SP`]. + /// + /// [`DUMMY_SP`]: rustc_span::DUMMY_SP #[track_caller] pub fn delay_span_bug>( &self, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index cfc1cabe229e5..3b026bc0e0f38 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1315,22 +1315,41 @@ pub(crate) mod builtin { /// Parses a file as an expression or an item according to the context. /// - /// The file is located relative to the current file (similarly to how - /// modules are found). The provided path is interpreted in a platform-specific - /// way at compile time. So, for instance, an invocation with a Windows path - /// containing backslashes `\` would not compile correctly on Unix. + /// **Warning**: For multi-file Rust projects, the `include!` macro is probably not what you + /// are looking for. Usually, multi-file Rust projects use + /// [modules](https://doc.rust-lang.org/reference/items/modules.html). Multi-file projects and + /// modules are explained in the Rust-by-Example book + /// [here](https://doc.rust-lang.org/rust-by-example/mod/split.html) and the module system is + /// explained in the Rust Book + /// [here](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html). + /// + /// The included file is placed in the surrounding code + /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). If + /// the included file is parsed as an expression and variables or functions share names across + /// both files, it could result in variables or functions being different from what the + /// included file expected. + /// + /// The included file is located relative to the current file (similarly to how modules are + /// found). The provided path is interpreted in a platform-specific way at compile time. So, + /// for instance, an invocation with a Windows path containing backslashes `\` would not + /// compile correctly on Unix. /// - /// Using this macro is often a bad idea, because if the file is - /// parsed as an expression, it is going to be placed in the - /// surrounding code unhygienically. This could result in variables - /// or functions being different from what the file expected if - /// there are variables or functions that have the same name in - /// the current file. + /// # Uses + /// + /// The `include!` macro is primarily used for two purposes. It is used to include + /// documentation that is written in a separate file and it is used to include [build artifacts + /// usually as a result from the `build.rs` + /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). + /// + /// When using the `include` macro to include stretches of documentation, remember that the + /// included file still needs to be a valid rust syntax. It is also possible to + /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or + /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain + /// text or markdown file. /// /// # Examples /// - /// Assume there are two files in the same directory with the following - /// contents: + /// Assume there are two files in the same directory with the following contents: /// /// File 'monkeys.in': /// diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 475434e5aef86..c39e9c5fbc9d6 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.13.4 \ No newline at end of file +0.14.1 \ No newline at end of file diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index d4d3e4f6ea795..c8899ee62b5f9 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -309,7 +309,7 @@ impl<'tcx> Context<'tcx> { pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option { let mut root = self.root_path(); - let mut path = String::new(); + let mut path: String; let cnum = span.cnum(self.sess()); // We can safely ignore synthetic `SourceFile`s. @@ -340,10 +340,24 @@ impl<'tcx> Context<'tcx> { ExternalLocation::Unknown => return None, }; - sources::clean_path(&src_root, file, false, |component| { - path.push_str(&component.to_string_lossy()); + let href = RefCell::new(PathBuf::new()); + sources::clean_path( + &src_root, + file, + |component| { + href.borrow_mut().push(component); + }, + || { + href.borrow_mut().pop(); + }, + ); + + path = href.into_inner().to_string_lossy().to_string(); + + if let Some(c) = path.as_bytes().last() && *c != b'/' { path.push('/'); - }); + } + let mut fname = file.file_name().expect("source has no filename").to_os_string(); fname.push(".html"); path.push_str(&fname.to_string_lossy()); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index eaf149a43005b..3ea4c4bea8828 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -1,8 +1,9 @@ +use std::cell::RefCell; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Component, Path}; -use std::rc::Rc; +use std::rc::{Rc, Weak}; use itertools::Itertools; use rustc_data_structures::flock; @@ -184,23 +185,26 @@ pub(super) fn write_shared( use std::ffi::OsString; - #[derive(Debug)] + #[derive(Debug, Default)] struct Hierarchy { + parent: Weak, elem: OsString, - children: FxHashMap, - elems: FxHashSet, + children: RefCell>>, + elems: RefCell>, } impl Hierarchy { - fn new(elem: OsString) -> Hierarchy { - Hierarchy { elem, children: FxHashMap::default(), elems: FxHashSet::default() } + fn with_parent(elem: OsString, parent: &Rc) -> Self { + Self { elem, parent: Rc::downgrade(parent), ..Self::default() } } fn to_json_string(&self) -> String { - let mut subs: Vec<&Hierarchy> = self.children.values().collect(); + let borrow = self.children.borrow(); + let mut subs: Vec<_> = borrow.values().collect(); subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem)); let mut files = self .elems + .borrow() .iter() .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion"))) .collect::>(); @@ -220,36 +224,52 @@ pub(super) fn write_shared( files = files ) } - } - if cx.include_sources { - let mut hierarchy = Hierarchy::new(OsString::new()); - for source in cx - .shared - .local_sources - .iter() - .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok()) - { - let mut h = &mut hierarchy; - let mut elems = source + fn add_path(self: &Rc, path: &Path) { + let mut h = Rc::clone(&self); + let mut elems = path .components() .filter_map(|s| match s { Component::Normal(s) => Some(s.to_owned()), + Component::ParentDir => Some(OsString::from("..")), _ => None, }) .peekable(); loop { let cur_elem = elems.next().expect("empty file path"); + if cur_elem == ".." { + if let Some(parent) = h.parent.upgrade() { + h = parent; + } + continue; + } if elems.peek().is_none() { - h.elems.insert(cur_elem); + h.elems.borrow_mut().insert(cur_elem); break; } else { - let e = cur_elem.clone(); - h = h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e)); + let entry = Rc::clone( + h.children + .borrow_mut() + .entry(cur_elem.clone()) + .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))), + ); + h = entry; } } } + } + if cx.include_sources { + let hierarchy = Rc::new(Hierarchy::default()); + for source in cx + .shared + .local_sources + .iter() + .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok()) + { + hierarchy.add_path(source); + } + let hierarchy = Rc::try_unwrap(hierarchy).unwrap(); let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); let make_sources = || { let (mut all_sources, _krates) = diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index e639fadeb9673..799c497d13709 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::source_map::FileName; +use std::cell::RefCell; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; @@ -72,12 +73,22 @@ impl LocalSourcesCollector<'_, '_> { return; } - let mut href = String::new(); - clean_path(self.src_root, &p, false, |component| { - href.push_str(&component.to_string_lossy()); - href.push('/'); - }); + let href = RefCell::new(PathBuf::new()); + clean_path( + &self.src_root, + &p, + |component| { + href.borrow_mut().push(component); + }, + || { + href.borrow_mut().pop(); + }, + ); + let mut href = href.into_inner().to_string_lossy().to_string(); + if let Some(c) = href.as_bytes().last() && *c != b'/' { + href.push('/'); + } let mut src_fname = p.file_name().expect("source has no filename").to_os_string(); src_fname.push(".html"); href.push_str(&src_fname.to_string_lossy()); @@ -180,13 +191,28 @@ impl SourceCollector<'_, '_> { let shared = Rc::clone(&self.cx.shared); // Create the intermediate directories - let mut cur = self.dst.clone(); - let mut root_path = String::from("../../"); - clean_path(&shared.src_root, &p, false, |component| { - cur.push(component); - root_path.push_str("../"); - }); + let cur = RefCell::new(PathBuf::new()); + let root_path = RefCell::new(PathBuf::new()); + + clean_path( + &shared.src_root, + &p, + |component| { + cur.borrow_mut().push(component); + root_path.borrow_mut().push(".."); + }, + || { + cur.borrow_mut().pop(); + root_path.borrow_mut().pop(); + }, + ); + let root_path = PathBuf::from("../../").join(root_path.into_inner()); + let mut root_path = root_path.to_string_lossy(); + if let Some(c) = root_path.as_bytes().last() && *c != b'/' { + root_path += "/"; + } + let mut cur = self.dst.join(cur.into_inner()); shared.ensure_dir(&cur)?; let src_fname = p.file_name().expect("source has no filename").to_os_string(); @@ -232,11 +258,13 @@ impl SourceCollector<'_, '_> { /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a /// static HTML tree. Each component in the cleaned path will be passed as an -/// argument to `f`. The very last component of the path (ie the file name) will -/// be passed to `f` if `keep_filename` is true, and ignored otherwise. -pub(crate) fn clean_path(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) +/// argument to `f`. The very last component of the path (ie the file name) is ignored. +/// If a `..` is encountered, the `parent` closure will be called to allow the callee to +/// handle it. +pub(crate) fn clean_path(src_root: &Path, p: &Path, mut f: F, mut parent: P) where F: FnMut(&OsStr), + P: FnMut(), { // make it relative, if possible let p = p.strip_prefix(src_root).unwrap_or(p); @@ -244,12 +272,12 @@ where let mut iter = p.components().peekable(); while let Some(c) = iter.next() { - if !keep_filename && iter.peek().is_none() { + if iter.peek().is_none() { break; } match c { - Component::ParentDir => f("up".as_ref()), + Component::ParentDir => parent(), Component::Normal(c) => f(c), _ => continue, } diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml index fb8e288fae882..c9b53a1a0f76c 100644 --- a/src/test/rustdoc-gui/anchors.goml +++ b/src/test/rustdoc-gui/anchors.goml @@ -3,70 +3,72 @@ define-function: ( "check-colors", (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color), - [ - ("goto", "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"), + block { + goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" // This is needed to ensure that the text color is computed. - ("show-text", true), + show-text: true // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("#toggle-all-docs", {"color": |main_color|})), - ("assert-css", (".fqn a:nth-of-type(1)", {"color": |fqn_color|})), - ("assert-css", (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})), - ("assert-css", ( + assert-css: ("#toggle-all-docs", {"color": |main_color|}) + assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|}) + assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|}) + assert-css: ( ".rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, ALL, - )), - ( - "compare-elements-css", - (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"]), - ), - ( - "compare-elements-css", - (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"]), - ), + ) + compare-elements-css: ( + ".rightside .srclink", + ".rightside.srclink", + ["color", "text-decoration"], + ) + compare-elements-css: ( + ".main-heading .srclink", + ".rightside.srclink", + ["color", "text-decoration"], + ) - ("move-cursor-to", ".main-heading .srclink"), - ("assert-css", ( + move-cursor-to: ".main-heading .srclink" + assert-css: ( ".main-heading .srclink", {"color": |src_link_color|, "text-decoration": "underline solid " + |src_link_color|}, - )), - ("move-cursor-to", ".impl-items .rightside .srclink"), - ("assert-css", ( + ) + move-cursor-to: ".impl-items .rightside .srclink" + assert-css: ( ".impl-items .rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, - )), - ("move-cursor-to", ".impl-items .rightside.srclink"), - ("assert-css", ( + ) + move-cursor-to: ".impl-items .rightside.srclink" + assert-css: ( ".impl-items .rightside.srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, - )), + ) - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"), + goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" // Since we changed page, we need to set the theme again. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("#top-doc-prose-title", {"color": |title_color|})), + assert-css: ("#top-doc-prose-title", {"color": |title_color|}) - ("assert-css", (".sidebar a", {"color": |sidebar_link_color|})), - ("assert-css", ("h1.fqn a", {"color": |title_color|})), + assert-css: (".sidebar a", {"color": |sidebar_link_color|}) + assert-css: ("h1.fqn a", {"color": |title_color|}) // We move the cursor over the "Implementations" title so the anchor is displayed. - ("move-cursor-to", "h2#implementations"), - ("assert-css", ("h2#implementations a.anchor", {"color": |main_color|})), + move-cursor-to: "h2#implementations" + assert-css: ("h2#implementations a.anchor", {"color": |main_color|}) // Same thing with the impl block title. - ("move-cursor-to", "#impl-HeavilyDocumentedStruct"), - ("assert-css", ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|})), + move-cursor-to: "#impl-HeavilyDocumentedStruct" + assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|}) - ("assert-css", ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})), - ], + assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"}) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/code-color.goml b/src/test/rustdoc-gui/code-color.goml index 118f04ad6dcba..cb550a4573a6f 100644 --- a/src/test/rustdoc-gui/code-color.goml +++ b/src/test/rustdoc-gui/code-color.goml @@ -9,14 +9,14 @@ show-text: true define-function: ( "check-colors", (theme, doc_code_color, doc_inline_code_color), - [ + block { // Set the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", (".docblock pre > code", {"color": |doc_code_color|}, ALL)), - ("assert-css", (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL)), - ], + reload: + assert-css: (".docblock pre > code", {"color": |doc_code_color|}, ALL) + assert-css: (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL) + }, ) call-function: ("check-colors", ("ayu", "rgb(230, 225, 207)", "rgb(255, 180, 84)")) diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml index d4443f821d2a7..a3ef4e77b5424 100644 --- a/src/test/rustdoc-gui/codeblock-tooltip.goml +++ b/src/test/rustdoc-gui/codeblock-tooltip.goml @@ -5,32 +5,32 @@ show-text: true define-function: ( "check-colors", (theme, background, color, border), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // compile_fail block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip", {"color": "rgba(255, 0, 0, 0.5)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.compile_fail .tooltip"), + move-cursor-to: ".docblock .example-wrap.compile_fail .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip", {"color": "rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip::after", { "content": '"This example deliberately fails to compile"', @@ -39,37 +39,37 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), + ) // should_panic block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.should_panic .tooltip", {"color": "rgba(255, 0, 0, 0.5)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.should_panic .tooltip"), + move-cursor-to: ".docblock .example-wrap.should_panic .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.should_panic .tooltip", {"color": "rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic .tooltip::after", { "content": '"This example panics"', @@ -78,37 +78,37 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), + ) // ignore block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.ignore .tooltip", {"color": "rgba(255, 142, 0, 0.6)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.ignore .tooltip"), + move-cursor-to: ".docblock .example-wrap.ignore .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.ignore .tooltip", {"color": "rgb(255, 142, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore .tooltip::after", { "content": '"This example is not tested"', @@ -117,16 +117,16 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), - ], + ) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index a3ed008719c00..69bcf5339ef2c 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -11,19 +11,19 @@ assert-false: "pre.example-line-numbers" define-function: ( "check-colors", (theme, color), - [ + block { // We now set the setting to show the line numbers on code examples. - ("local-storage", { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", "rustdoc-line-numbers": "true" - }), + } // We reload to make the line numbers appear and change theme. - ("reload"), + reload: // We wait for them to be added into the DOM by the JS... - ("wait-for", "pre.example-line-numbers"), + wait-for: "pre.example-line-numbers" // If the test didn't fail, it means that it was found! - ("assert-css", ( + assert-css: ( "pre.example-line-numbers", { "color": |color|, @@ -32,8 +32,8 @@ define-function: ( "text-align": "right", }, ALL, - )), - ], + ) + }, ) call-function: ("check-colors", { "theme": "ayu", diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml index 6f9209e0ab4a0..3dcb8abd41598 100644 --- a/src/test/rustdoc-gui/docblock-table.goml +++ b/src/test/rustdoc-gui/docblock-table.goml @@ -7,32 +7,32 @@ compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock tab define-function: ( "check-colors", (theme, border_color, zebra_stripe_color), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("reload"), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", { + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + reload: + assert-css: (".top-doc .docblock table tbody tr:nth-child(1)", { "background-color": "rgba(0, 0, 0, 0)", - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(2)", { "background-color": |zebra_stripe_color|, - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(3)", { "background-color": "rgba(0, 0, 0, 0)", - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(4)", { "background-color": |zebra_stripe_color|, - })), - ("assert-css", (".top-doc .docblock table td", { + }) + assert-css: (".top-doc .docblock table td", { "border-style": "solid", "border-width": "1px", "border-color": |border_color|, - })), - ("assert-css", (".top-doc .docblock table th", { + }) + assert-css: (".top-doc .docblock table th", { "border-style": "solid", "border-width": "1px", "border-color": |border_color|, - })), - ] + }) + } ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index c80a49c52f03a..92cf050a514ff 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -3,39 +3,39 @@ define-function: ( "check-colors", (theme, color, code_header_color, focus_background_color, headings_color), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // This is needed so that the text color is computed. - ("show-text", true), - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + show-text: true + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".impl", {"color": |color|, "background-color": "rgba(0, 0, 0, 0)"}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".impl .code-header", {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"}, ALL, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"), - ("assert-css", ( + ) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo" + assert-css: ( "#impl-Foo", {"color": |color|, "background-color": |focus_background_color|}, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"), - ("assert-css", ( + ) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use" + assert-css: ( "#method\.must_use", {"color": |color|, "background-color": |focus_background_color|}, ALL, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), - ("assert-css", (".small-section-header a", {"color": |color|}, ALL)), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"), + ) + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" + assert-css: (".small-section-header a", {"color": |color|}, ALL) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" // We select headings (h2, h3, h...). - ("assert-css", (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)), - ], + assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml index 85e17ca9551a2..45b3fee26e413 100644 --- a/src/test/rustdoc-gui/headings.goml +++ b/src/test/rustdoc-gui/headings.goml @@ -157,38 +157,38 @@ goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" define-function: ( "check-colors", (theme, heading_color, small_heading_color, heading_border_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".top-doc .docblock h2", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h3", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h4", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h5", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h4", {"color": |heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h5", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h6", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ], + ) + }, ) call-function: ( "check-colors", @@ -221,11 +221,11 @@ call-function: ( define-function: ( "check-since-color", (theme), - [ - ("local-storage", {"rustdoc-theme": |theme|}), - ("reload"), - ("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)), - ], + block { + local-storage: {"rustdoc-theme": |theme|} + reload: + assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL) + }, ) goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml index 62cc9ac649725..5f4c1ba2f8536 100644 --- a/src/test/rustdoc-gui/help-page.goml +++ b/src/test/rustdoc-gui/help-page.goml @@ -18,17 +18,17 @@ show-text: true define-function: ( "check-colors", (theme, color, background, box_shadow), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", ("#help kbd", { + reload: + assert-css: ("#help kbd", { "color": |color|, "background-color": |background|, "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset", - }, ALL)), - ], + }, ALL) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/highlight-colors.goml b/src/test/rustdoc-gui/highlight-colors.goml index ff1be389dcb07..b182150a577d5 100644 --- a/src/test/rustdoc-gui/highlight-colors.goml +++ b/src/test/rustdoc-gui/highlight-colors.goml @@ -21,24 +21,24 @@ define-function: ( comment, doc_comment, ), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ("pre.rust .kw", {"color": |kw|}, ALL)), - ("assert-css", ("pre.rust .kw-2", {"color": |kw2|}, ALL)), - ("assert-css", ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL)), - ("assert-css", ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL)), - ("assert-css", ("pre.rust .lifetime", {"color": |lifetime|}, ALL)), - ("assert-css", ("pre.rust .number", {"color": |number|}, ALL)), - ("assert-css", ("pre.rust .string", {"color": |string|}, ALL)), - ("assert-css", ("pre.rust .bool-val", {"color": |bool_val|}, ALL)), - ("assert-css", ("pre.rust .self", {"color": |self|}, ALL)), - ("assert-css", ("pre.rust .attr", {"color": |attr|}, ALL)), - ("assert-css", ("pre.rust .macro", {"color": |macro|}, ALL)), - ("assert-css", ("pre.rust .question-mark", {"color": |question_mark|}, ALL)), - ("assert-css", ("pre.rust .comment", {"color": |comment|}, ALL)), - ("assert-css", ("pre.rust .doccomment", {"color": |doc_comment|}, ALL)), - ], + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ("pre.rust .kw", {"color": |kw|}, ALL) + assert-css: ("pre.rust .kw-2", {"color": |kw2|}, ALL) + assert-css: ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL) + assert-css: ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL) + assert-css: ("pre.rust .lifetime", {"color": |lifetime|}, ALL) + assert-css: ("pre.rust .number", {"color": |number|}, ALL) + assert-css: ("pre.rust .string", {"color": |string|}, ALL) + assert-css: ("pre.rust .bool-val", {"color": |bool_val|}, ALL) + assert-css: ("pre.rust .self", {"color": |self|}, ALL) + assert-css: ("pre.rust .attr", {"color": |attr|}, ALL) + assert-css: ("pre.rust .macro", {"color": |macro|}, ALL) + assert-css: ("pre.rust .question-mark", {"color": |question_mark|}, ALL) + assert-css: ("pre.rust .comment", {"color": |comment|}, ALL) + assert-css: ("pre.rust .doccomment", {"color": |doc_comment|}, ALL) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/item-decl-colors.goml b/src/test/rustdoc-gui/item-decl-colors.goml index 2e07f19b13d64..c58e3eb7c237f 100644 --- a/src/test/rustdoc-gui/item-decl-colors.goml +++ b/src/test/rustdoc-gui/item-decl-colors.goml @@ -17,22 +17,23 @@ define-function: ( fn_color, assoc_type_color, ), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"), - ("show-text", true), - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".item-decl .code-attribute", {"color": |attr_color|}, ALL)), - ("assert-css", (".item-decl .trait", {"color": |trait_color|}, ALL)), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html" + show-text: true + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".item-decl .code-attribute", {"color": |attr_color|}, ALL) + assert-css: (".item-decl .trait", {"color": |trait_color|}, ALL) // We need to add `code` here because otherwise it would select the parent too. - ("assert-css", (".item-decl code .struct", {"color": |struct_color|}, ALL)), - ("assert-css", (".item-decl .enum", {"color": |enum_color|}, ALL)), - ("assert-css", (".item-decl .primitive", {"color": |primitive_color|}, ALL)), - ("goto", "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"), - ("assert-css", (".item-decl .constant", {"color": |constant_color|}, ALL)), - ("assert-css", (".item-decl .fn", {"color": |fn_color|}, ALL)), - ("assert-css", (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)), - ], + assert-css: (".item-decl code .struct", {"color": |struct_color|}, ALL) + assert-css: (".item-decl .enum", {"color": |enum_color|}, ALL) + assert-css: (".item-decl .primitive", {"color": |primitive_color|}, ALL) + + goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html" + assert-css: (".item-decl .constant", {"color": |constant_color|}, ALL) + assert-css: (".item-decl .fn", {"color": |fn_color|}, ALL) + assert-css: (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml index b65faf13d0c53..8ee3ccf4a2118 100644 --- a/src/test/rustdoc-gui/jump-to-def-background.goml +++ b/src/test/rustdoc-gui/jump-to-def-background.goml @@ -4,17 +4,17 @@ goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html" define-function: ( "check-background-color", (theme, background_color), - [ + block { // Set the theme. - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }), + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", ( + reload: + assert-css: ( "body.source .example-wrap pre.rust a", {"background-color": |background_color|}, ALL, - )), - ], + ) + }, ) call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)")) diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml index 9402c09eb69e7..14f7d99351a64 100644 --- a/src/test/rustdoc-gui/links-color.goml +++ b/src/test/rustdoc-gui/links-color.goml @@ -8,29 +8,29 @@ define-function: ( "check-colors", (theme, mod, macro, struct, enum, trait, fn, type, union, keyword, sidebar, sidebar_current, sidebar_current_background), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".item-table .mod", {"color": |mod|}, ALL)), - ("assert-css", (".item-table .macro", {"color": |macro|}, ALL)), - ("assert-css", (".item-table .struct", {"color": |struct|}, ALL)), - ("assert-css", (".item-table .enum", {"color": |enum|}, ALL)), - ("assert-css", (".item-table .trait", {"color": |trait|}, ALL)), - ("assert-css", (".item-table .fn", {"color": |fn|}, ALL)), - ("assert-css", (".item-table .type", {"color": |type|}, ALL)), - ("assert-css", (".item-table .union", {"color": |union|}, ALL)), - ("assert-css", (".item-table .keyword", {"color": |keyword|}, ALL)), + assert-css: (".item-table .mod", {"color": |mod|}, ALL) + assert-css: (".item-table .macro", {"color": |macro|}, ALL) + assert-css: (".item-table .struct", {"color": |struct|}, ALL) + assert-css: (".item-table .enum", {"color": |enum|}, ALL) + assert-css: (".item-table .trait", {"color": |trait|}, ALL) + assert-css: (".item-table .fn", {"color": |fn|}, ALL) + assert-css: (".item-table .type", {"color": |type|}, ALL) + assert-css: (".item-table .union", {"color": |union|}, ALL) + assert-css: (".item-table .keyword", {"color": |keyword|}, ALL) // Checking sidebar elements. - ("assert-css", ( + assert-css: ( ".sidebar-elems a:not(.current)", {"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".sidebar-elems a.current", { "color": |sidebar_current|, @@ -38,8 +38,8 @@ define-function: ( "font-weight": "500", }, ALL, - )), - ], + ) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index 7d4bd27d42d4d..b4fa7d0dbf0e2 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -123,40 +123,40 @@ assert-count: ("//*[@class='notable popover']", 0) define-function: ( "check-colors", (theme, header_color, content_color, type_color, trait_color), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html" // This is needed to ensure that the text color is computed. - ("show-text", true), + show-text: true // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("move-cursor-to", "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"), - ("assert-count", (".notable.popover", 1)), + move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" + assert-count: (".notable.popover", 1) - ("assert-css", ( + assert-css: ( ".notable.popover h3", {"color": |header_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre", {"color": |content_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre a.struct", {"color": |type_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre a.trait", {"color": |trait_color|}, ALL, - )), - ] + ) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml index 57d63049f28ca..8dcb62c10aaac 100644 --- a/src/test/rustdoc-gui/run-on-hover.goml +++ b/src/test/rustdoc-gui/run-on-hover.goml @@ -8,27 +8,27 @@ show-text: true define-function: ( "check-run-button", (theme, color, background, hover_color, hover_background), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".test-arrow", {"visibility": "hidden"})), - ("move-cursor-to", ".example-wrap"), - ("assert-css", (".test-arrow", { + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".test-arrow", {"visibility": "hidden"}) + move-cursor-to: ".example-wrap" + assert-css: (".test-arrow", { "visibility": "visible", "color": |color|, "background-color": |background|, "font-size": "22px", "border-radius": "5px", - })), - ("move-cursor-to", ".test-arrow"), - ("assert-css", (".test-arrow:hover", { + }) + move-cursor-to: ".test-arrow" + assert-css: (".test-arrow:hover", { "visibility": "visible", "color": |hover_color|, "background-color": |hover_background|, "font-size": "22px", "border-radius": "5px", - })), - ], + }) + }, ) call-function: ("check-run-button", { diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml index 816cc9abd693d..e94dc9a964ddd 100644 --- a/src/test/rustdoc-gui/rust-logo.goml +++ b/src/test/rustdoc-gui/rust-logo.goml @@ -4,29 +4,29 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" define-function: ( "check-logo", (theme, filter), - [ + block { // Going to the doc page. - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" // Changing theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".rust-logo", {"filter": |filter|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".rust-logo", {"filter": |filter|}) // Going to the source code page. - ("goto", "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"), + goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" // Changing theme (since it's local files, the local storage works by folder). - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".rust-logo", {"filter": |filter|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".rust-logo", {"filter": |filter|}) // Now we check that the non-rust logos don't have a CSS filter set. - ("goto", "file://" + |DOC_PATH| + "/huge_logo/index.html"), + goto: "file://" + |DOC_PATH| + "/huge_logo/index.html" // Changing theme on the new page (again...). - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // Check there is no rust logo - ("assert-false", ".rust-logo"), + assert-false: ".rust-logo" // Check there is no filter. - ("assert-css", (".sidebar .logo-container img", {"filter": "none"})), - ], + assert-css: (".sidebar .logo-container img", {"filter": "none"}) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/scrape-examples-color.goml b/src/test/rustdoc-gui/scrape-examples-color.goml index 360e2af8ba427..40f31b2771b25 100644 --- a/src/test/rustdoc-gui/scrape-examples-color.goml +++ b/src/test/rustdoc-gui/scrape-examples-color.goml @@ -6,29 +6,29 @@ define-function: ( "check-colors", (theme, highlight, highlight_focus, help_border, help_color, help_hover_border, help_hover_color), - [ - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }), - ("reload"), - ("wait-for", ".more-examples-toggle"), - ("assert-css", (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", } + reload: + wait-for: ".more-examples-toggle" + assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { "background-color": |highlight|, - }, ALL)), - ("assert-css", (".scraped-example .example-wrap .rust span.highlight.focus", { + }, ALL) + assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", { "background-color": |highlight_focus|, - }, ALL)), + }, ALL) - ("assert-css", (".scraped-example-list .scrape-help", { + assert-css: (".scraped-example-list .scrape-help", { "border-color": |help_border|, "color": |help_color|, - })), - ("move-cursor-to", ".scraped-example-list .scrape-help"), - ("assert-css", (".scraped-example-list .scrape-help:hover", { + }) + move-cursor-to: ".scraped-example-list .scrape-help" + assert-css: (".scraped-example-list .scrape-help:hover", { "border-color": |help_hover_border|, "color": |help_hover_color|, - })), + }) // Moving the cursor to another item to not break next runs. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + } ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml index 8c84fbc0c3056..2d5df6a5d25e0 100644 --- a/src/test/rustdoc-gui/scrape-examples-toggle.goml +++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml @@ -6,24 +6,24 @@ show-text: true define-function: ( "check-color", (theme, toggle_line_color, toggle_line_hover_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // Clicking "More examples..." will open additional examples - ("assert-attribute-false", (".more-examples-toggle", {"open": ""})), - ("click", ".more-examples-toggle"), - ("assert-attribute", (".more-examples-toggle", {"open": ""})), + assert-attribute-false: (".more-examples-toggle", {"open": ""}) + click: ".more-examples-toggle" + assert-attribute: (".more-examples-toggle", {"open": ""}) - ("assert-css", (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)), - ("move-cursor-to", ".toggle-line"), - ("assert-css", ( + assert-css: (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL) + move-cursor-to: ".toggle-line" + assert-css: ( ".toggle-line:hover .toggle-line-inner", {"background-color": |toggle_line_hover_color|}, - )), + ) // Moving cursor away from the toggle line to prevent disrupting next test. - ("move-cursor-to", ".search-input"), - ], + move-cursor-to: ".search-input" + }, ) call-function: ("check-color", { diff --git a/src/test/rustdoc-gui/search-no-result.goml b/src/test/rustdoc-gui/search-no-result.goml index b88be32c94a4b..b76a44fa992e6 100644 --- a/src/test/rustdoc-gui/search-no-result.goml +++ b/src/test/rustdoc-gui/search-no-result.goml @@ -5,18 +5,18 @@ show-text: true define-function: ( "check-no-result", (theme, link, link_hover), - [ + block { // Changing theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for", "#results"), - ("assert", ".search-failed.active"), - ("assert-css", ("#results a", {"color": |link|}, ALL)), - ("move-cursor-to", "#results a"), - ("assert-css", ("#results a:hover", {"color": |link_hover|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for: "#results" + assert: ".search-failed.active" + assert-css: ("#results a", {"color": |link|}, ALL) + move-cursor-to: "#results a" + assert-css: ("#results a:hover", {"color": |link_hover|}) // Moving the cursor to some other place to not create issues with next function run. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + }, ) call-function: ("check-no-result", { diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml index 3c5fe9b74b74f..d6d54ec4bee9b 100644 --- a/src/test/rustdoc-gui/search-result-color.goml +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -3,53 +3,32 @@ define-function: ( "check-result-color", (result_kind, color, hover_color), - [ - ( - "assert-css", - (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL), - ), - ( - "assert-css", - ( - ".result-" + |result_kind|, - {"color": |entry_color|, "background-color": |background_color|}, - ), - ), - ( - "move-cursor-to", + block { + assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) + assert-css: ( ".result-" + |result_kind|, - ), - ( - "assert-css", - ( - ".result-" + |result_kind| + ":hover", - {"color": |hover_entry_color|, "background-color": |hover_background_color|}, - ), - ), - ( - "assert-css", - (".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}), - ), - ( - "move-cursor-to", - ".search-input", - ), - ( - "focus", - ".result-" + |result_kind|, - ), - ( - "assert-css", - ( - ".result-" + |result_kind| + ":focus", - {"color": |hover_entry_color|, "background-color": |hover_background_color|}, - ), - ), - ( - "assert-css", - (".result-" + |result_kind| + ":focus ." + |result_kind|, {"color": |hover_color|}), - ), - ], + {"color": |entry_color|, "background-color": |background_color|}, + ) + move-cursor-to: ".result-" + |result_kind| + assert-css: ( + ".result-" + |result_kind| + ":hover", + {"color": |hover_entry_color|, "background-color": |hover_background_color|}, + ) + assert-css: ( + ".result-" + |result_kind| + ":hover ." + |result_kind|, + {"color": |hover_color|}, + ) + move-cursor-to: ".search-input" + focus: ".result-" + |result_kind| + assert-css: ( + ".result-" + |result_kind| + ":focus", + {"color": |hover_entry_color|, "background-color": |hover_background_color|}, + ) + assert-css: ( + ".result-" + |result_kind| + ":focus ." + |result_kind|, + {"color": |hover_color|}, + ) + }, ) goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo" @@ -389,20 +368,20 @@ show-text: true define-function: ( "check-alias", (theme, alias, grey), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("write", (".search-input", "thisisanalias")), + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + write: (".search-input", "thisisanalias") // To be SURE that the search will be run. - ("press-key", 'Enter'), + press-key: 'Enter' // Waiting for the search results to appear... - ("wait-for", "#search-tabs"), + wait-for: "#search-tabs" // Checking that the colors for the alias element are the ones expected. - ("assert-css", (".result-name > .alias", {"color": |alias|})), - ("assert-css", (".result-name > .alias > .grey", {"color": |grey|})), + assert-css: (".result-name > .alias", {"color": |alias|}) + assert-css: (".result-name > .alias > .grey", {"color": |grey|}) // Leave the search results to prevent reloading with an already filled search input. - ("press-key", "Escape"), - ], + press-key: "Escape" + }, ) call-function: ("check-alias", { diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index 13a5e4c717b65..43e608228d8e3 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -42,17 +42,17 @@ show-text: true define-function: ( "check-filter", (theme, border, filter, hover_border, hover_filter), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for", "#crate-search"), - ("assert-css", ("#crate-search", {"border": "1px solid " + |border|})), - ("assert-css", ("#crate-search-div::after", {"filter": |filter|})), - ("move-cursor-to", "#crate-search"), - ("assert-css", ("#crate-search", {"border": "1px solid " + |hover_border|})), - ("assert-css", ("#crate-search-div::after", {"filter": |hover_filter|})), - ("move-cursor-to", ".search-input"), - ], + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for: "#crate-search" + assert-css: ("#crate-search", {"border": "1px solid " + |border|}) + assert-css: ("#crate-search-div::after", {"filter": |filter|}) + move-cursor-to: "#crate-search" + assert-css: ("#crate-search", {"border": "1px solid " + |hover_border|}) + assert-css: ("#crate-search-div::after", {"filter": |hover_filter|}) + move-cursor-to: ".search-input" + }, ) call-function: ("check-filter", { diff --git a/src/test/rustdoc-gui/search-tab.goml b/src/test/rustdoc-gui/search-tab.goml index c2634a04c8a74..36958f7004446 100644 --- a/src/test/rustdoc-gui/search-tab.goml +++ b/src/test/rustdoc-gui/search-tab.goml @@ -7,35 +7,35 @@ define-function: ( (theme, background, background_selected, background_hover, border_bottom, border_bottom_selected, border_bottom_hover, border_top, border_top_selected, border_top_hover), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // These two commands are used to be sure the search will be run. - ("focus", ".search-input"), - ("press-key", "Enter"), + focus: ".search-input" + press-key: "Enter" - ("wait-for", "#search-tabs"), - ("assert-css", ("#search-tabs > button:not(.selected)", { + wait-for: "#search-tabs" + assert-css: ("#search-tabs > button:not(.selected)", { "background-color": |background|, "border-bottom": |border_bottom|, "border-top": |border_top|, - })), - ("assert-css", ("#search-tabs > button.selected", { + }) + assert-css: ("#search-tabs > button.selected", { "background-color": |background_selected|, "border-bottom": |border_bottom_selected|, "border-top": |border_top_selected|, - })), - ("move-cursor-to", "#search-tabs > button:not(.selected)"), - ("assert-css", ("#search-tabs > button:not(.selected):hover", { + }) + move-cursor-to: "#search-tabs > button:not(.selected)" + assert-css: ("#search-tabs > button:not(.selected):hover", { "background-color": |background_hover|, "border-bottom": |border_bottom_hover|, "border-top": |border_top_hover|, - })), + }) // To prevent disrupting next run of this function. - ("move-cursor-to", ".search-input"), - ], + move-cursor-to: ".search-input" + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-links-color.goml b/src/test/rustdoc-gui/sidebar-links-color.goml index 7ef7ec90cd269..1d5fdb7a48fc7 100644 --- a/src/test/rustdoc-gui/sidebar-links-color.goml +++ b/src/test/rustdoc-gui/sidebar-links-color.goml @@ -12,80 +12,80 @@ define-function: ( trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover, type_hover_background, keyword, keyword_hover, keyword_hover_background, ), - [ - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }), - ("reload"), + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } + reload: // Struct - ("assert-css", ( + assert-css: ( ".sidebar .block.struct a:not(.current)", {"color": |struct|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.struct a:not(.current)"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.struct a:not(.current)" + assert-css: ( ".sidebar .block.struct a:hover", {"color": |struct_hover|, "background-color": |struct_hover_background|}, - )), + ) // Enum - ("assert-css", ( + assert-css: ( ".sidebar .block.enum a", {"color": |enum|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.enum a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.enum a" + assert-css: ( ".sidebar .block.enum a:hover", {"color": |enum_hover|, "background-color": |enum_hover_background|}, - )), + ) // Union - ("assert-css", ( + assert-css: ( ".sidebar .block.union a", {"color": |union|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.union a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.union a" + assert-css: ( ".sidebar .block.union a:hover", {"color": |union_hover|, "background-color": |union_hover_background|}, - )), + ) // Trait - ("assert-css", ( + assert-css: ( ".sidebar .block.trait a", {"color": |trait|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.trait a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.trait a" + assert-css: ( ".sidebar .block.trait a:hover", {"color": |trait_hover|, "background-color": |trait_hover_background|}, - )), + ) // Function - ("assert-css", ( + assert-css: ( ".sidebar .block.fn a", {"color": |fn|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.fn a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.fn a" + assert-css: ( ".sidebar .block.fn a:hover", {"color": |fn_hover|, "background-color": |fn_hover_background|}, - )), + ) // Type definition - ("assert-css", ( + assert-css: ( ".sidebar .block.type a", {"color": |type|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.type a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.type a" + assert-css: ( ".sidebar .block.type a:hover", {"color": |type_hover|, "background-color": |type_hover_background|}, - )), + ) // Keyword - ("assert-css", ( + assert-css: ( ".sidebar .block.keyword a", {"color": |keyword|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.keyword a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.keyword a" + assert-css: ( ".sidebar .block.keyword a:hover", {"color": |keyword_hover|, "background-color": |keyword_hover_background|}, - )), - ] + ) + } ) call-function: ( diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml index 38d01f7f612a5..d5f4b619629e3 100644 --- a/src/test/rustdoc-gui/sidebar-mobile.goml +++ b/src/test/rustdoc-gui/sidebar-mobile.goml @@ -58,17 +58,17 @@ show-text: true define-function: ( "check-colors", (theme, color, background), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("reload"), + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + reload: // Open the sidebar menu. - ("click", ".sidebar-menu-toggle"), - ("assert-css", (".sidebar", { + click: ".sidebar-menu-toggle" + assert-css: (".sidebar", { "background-color": |background|, "color": |color|, - })), - ], + }) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index df4506e111964..d74d9420389f0 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -35,88 +35,88 @@ define-function: ( theme, color, color_hover, background, background_hover, background_toggle, background_toggle_hover, ), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for-css", ("#src-sidebar-toggle", {"visibility": "visible"})), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"}) + assert-css: ( "#source-sidebar details[open] > .files a.selected", {"color": |color_hover|, "background-color": |background|}, - )), + ) // Without hover or focus. - ("assert-css", ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})), + assert-css: ("#src-sidebar-toggle > button", {"background-color": |background_toggle|}) // With focus. - ("focus", "#src-sidebar-toggle > button"), - ("assert-css", ( + focus: "#src-sidebar-toggle > button" + assert-css: ( "#src-sidebar-toggle > button:focus", {"background-color": |background_toggle_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#src-sidebar-toggle > button"), - ("assert-css", ( + move-cursor-to: "#src-sidebar-toggle > button" + assert-css: ( "#src-sidebar-toggle > button:hover", {"background-color": |background_toggle_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar details[open] > .files a:not(.selected)", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar details[open] > .files a:not(.selected)"), - ("wait-for-css", ( + focus: "#source-sidebar details[open] > .files a:not(.selected)" + wait-for-css: ( "#source-sidebar details[open] > .files a:not(.selected):focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar details[open] > .files a:not(.selected)"), - ("assert-css", ( + move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" + assert-css: ( "#source-sidebar details[open] > .files a:not(.selected):hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar .dir-entry summary", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar .dir-entry summary"), - ("wait-for-css", ( + focus: "#source-sidebar .dir-entry summary" + wait-for-css: ( "#source-sidebar .dir-entry summary:focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar .dir-entry summary"), - ("assert-css", ( + move-cursor-to: "#source-sidebar .dir-entry summary" + assert-css: ( "#source-sidebar .dir-entry summary:hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar details[open] > .folders > details > summary", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar details[open] > .folders > details > summary"), - ("wait-for-css", ( + focus: "#source-sidebar details[open] > .folders > details > summary" + wait-for-css: ( "#source-sidebar details[open] > .folders > details > summary:focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar details[open] > .folders > details > summary"), - ("assert-css", ( + move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" + assert-css: ( "#source-sidebar details[open] > .folders > details > summary:hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ], + ) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 6bc07fbae04da..3ee83d6f475ac 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -7,43 +7,43 @@ show-text: true define-function: ( "check-colors", (theme, color, background_color), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".source .sidebar", { - "color": |color|, - "background-color": |background_color| - }, ALL)), - ], + assert-css: (".source .sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL) + }, ) call-function: ( - "check-colors", - { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background_color": "rgb(20, 25, 31)", - } + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } ) call-function: ( - "check-colors", - { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background_color": "rgb(80, 80, 80)", - } + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } ) call-function: ( - "check-colors", - { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background_color": "rgb(245, 245, 245)", - } + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } ) // Next, desktop mode layout. diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index bfd7567a22424..9db7f59695bb2 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -7,43 +7,43 @@ show-text: true define-function: ( "check-colors", (theme, color, background_color), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".sidebar", { - "color": |color|, - "background-color": |background_color| - }, ALL)), - ], + assert-css: (".sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL) + }, ) call-function: ( - "check-colors", - { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background_color": "rgb(20, 25, 31)", - } + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } ) call-function: ( - "check-colors", - { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background_color": "rgb(80, 80, 80)", - } + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } ) call-function: ( - "check-colors", - { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background_color": "rgb(245, 245, 245)", - } + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } ) local-storage: {"rustdoc-theme": "light"} diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index e0397890519bb..7c35119e6959d 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -22,20 +22,20 @@ assert-attribute-false: (".src-line-numbers > a:nth-child(7)", {"class": "line-h define-function: ( "check-colors", (theme, color, background_color, highlight_color, highlight_background_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".src-line-numbers > a:not(.line-highlighted)", {"color": |color|, "background-color": |background_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".src-line-numbers > a.line-highlighted", {"color": |highlight_color|, "background-color": |highlight_background_color|}, ALL, - )), - ], + ) + }, ) call-function: ("check-colors", { @@ -124,28 +124,28 @@ store-property: ( define-function: ( "check-sidebar-dir-entry", (x, y), - [ - ("assert", "details:first-of-type.dir-entry[open] > summary::marker"), - ("assert-css", ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})), + block { + assert: "details:first-of-type.dir-entry[open] > summary::marker" + assert-css: ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"}) // This check ensures that the summary is only one line. - ("assert-property", ( + assert-property: ( "#source-sidebar > details:first-of-type.dir-entry[open] > summary", {"offsetHeight": |link_height|} - )), - ("assert-position", ( + ) + assert-position: ( "#source-sidebar > details:first-of-type.dir-entry[open] > summary", {"x": |x|, "y": |y|} - )), - ("assert-property", ( + ) + assert-property: ( "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", {"offsetHeight": |link_height|} - )), - ("assert-position", ( + ) + assert-position: ( "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", // left margin {"x": |x| + 27, "y": |y| + |link_height|} - )), - ] + ) + } ) store-property: ( source_sidebar_title_height, diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml index aaed8440a40bd..50ba1ba62dbfa 100644 --- a/src/test/rustdoc-gui/stab-badge.goml +++ b/src/test/rustdoc-gui/stab-badge.goml @@ -2,40 +2,40 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" show-text: true define-function: ( - "check-badge", - (theme, background, color), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), - ("assert", (".docblock .stab")), - ("assert", (".item-table .stab")), - ("assert-css", (".stab", { - "border-radius": "3px", - "color": |color|, - "background-color": |background|, - })), - ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"), - ("assert", (".item-info .stab")), - ("assert-css", (".stab", { - "border-radius": "3px", - "color": |color|, - "background-color": |background|, - })), - ] + "check-badge", + (theme, background, color), + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" + assert: ".docblock .stab" + assert: ".item-table .stab" + assert-css: (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + }) + goto: "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html" + assert: (".item-info .stab") + assert-css: (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + }) + }, ) call-function: ("check-badge", { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background": "rgb(49, 69, 89)", + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background": "rgb(49, 69, 89)", }) call-function: ("check-badge", { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background": "rgb(49, 69, 89)", + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background": "rgb(49, 69, 89)", }) call-function: ("check-badge", { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background": "rgb(255, 245, 214)", + "theme": "light", + "color": "rgb(0, 0, 0)", + "background": "rgb(255, 245, 214)", }) diff --git a/src/test/rustdoc-gui/target.goml b/src/test/rustdoc-gui/target.goml index 3e5c30dc7eafe..ca393ee58917d 100644 --- a/src/test/rustdoc-gui/target.goml +++ b/src/test/rustdoc-gui/target.goml @@ -8,14 +8,14 @@ assert: "#method\.a_method:target" define-function: ( "check-style", (theme, background, border), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ("#method\.a_method:target", { + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ("#method\.a_method:target", { "background-color": |background|, "border-right": "3px solid " + |border|, - })), - ], + }) + }, ) call-function: ("check-style", { diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index 45bb8daf1f20c..89ce78e3aab4b 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -50,24 +50,24 @@ show-text: true define-function: ( "check-color", (theme, filter), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("details.rustdoc-toggle > summary::before", { + assert-css: ("details.rustdoc-toggle > summary::before", { "opacity": "0.5", "filter": |filter|, - }, ALL)), - ("move-cursor-to", "details.rustdoc-toggle summary"), - ("assert-css", ("details.rustdoc-toggle > summary:hover::before", { + }, ALL) + move-cursor-to: "details.rustdoc-toggle summary" + assert-css: ("details.rustdoc-toggle > summary:hover::before", { "opacity": "1", "filter": |filter|, - })), + }) // moving the cursor somewhere else to not mess with next function calls. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + }, ) call-function: ("check-color", {"theme": "ayu", "filter": "invert(1)"}) diff --git a/src/test/rustdoc-gui/unsafe-fn.goml b/src/test/rustdoc-gui/unsafe-fn.goml index 5e43b85fce084..d3a672ddde6e4 100644 --- a/src/test/rustdoc-gui/unsafe-fn.goml +++ b/src/test/rustdoc-gui/unsafe-fn.goml @@ -14,13 +14,13 @@ define-function: ( // `theme` is the theme being tested. // `color` is the expected color of the `` element. (theme, color), - [ + block { // Set the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", (".item-left sup", {"color": |color|})), - ], + reload: + assert-css: (".item-left sup", {"color": |color|}) + }, ) call-function: ("sup-check", ("dark", "rgb(221, 221, 221)")) diff --git a/src/test/rustdoc/src-links.rs b/src/test/rustdoc/src-links.rs index 353ce10243e00..7a6c733d464ce 100644 --- a/src/test/rustdoc/src-links.rs +++ b/src/test/rustdoc/src-links.rs @@ -7,6 +7,11 @@ #[path = "src-links/mod.rs"] pub mod qux; +// @has src/foo/src-links.rs.html +// @has foo/fizz/index.html '//a/@href' '../src/foo/src-links/fizz.rs.html' +#[path = "src-links/../src-links/fizz.rs"] +pub mod fizz; + // @has foo/bar/index.html '//a/@href' '../../src/foo/src-links.rs.html' pub mod bar { diff --git a/src/test/rustdoc/src-links/fizz.rs b/src/test/rustdoc/src-links/fizz.rs new file mode 100644 index 0000000000000..d2b76b1cec859 --- /dev/null +++ b/src/test/rustdoc/src-links/fizz.rs @@ -0,0 +1 @@ +pub struct Buzz; diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs new file mode 100644 index 0000000000000..fdc9d78990590 --- /dev/null +++ b/src/tools/tidy/src/error_codes.rs @@ -0,0 +1,381 @@ +//! Tidy check to ensure error codes are properly documented and tested. +//! +//! Overview of check: +//! +//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`. +//! +//! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`. +//! - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check) +//! - Note that other stylistic conventions for markdown files are checked in the `style.rs` tidy check. +//! +//! 3. We check that the error code has a UI test in `src/test/ui/error-codes/`. +//! - We ensure that there is both a `Exxxx.rs` file and a corresponding `Exxxx.stderr` file. +//! - We also ensure that the error code is used in the tests. +//! - *Currently*, it is possible to opt-out of this check with the `EXEMPTED_FROM_TEST` constant. +//! +//! 4. We check that the error code is actually emitted by the compiler. +//! - This is done by searching `compiler/` with a regex. +//! +//! This tidy check was merged and refactored from two others. See #PR_NUM for information about linting changes that occurred during this refactor. + +use std::{ffi::OsStr, fs, path::Path}; + +use regex::Regex; + +use crate::walk::{filter_dirs, walk, walk_many}; + +const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs"; +const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/"; +const ERROR_TESTS_PATH: &str = "src/test/ui/error-codes/"; + +// Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested. +const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"]; + +// Error codes that don't yet have a UI test. This list will eventually be removed. +const IGNORE_UI_TEST_CHECK: &[&str] = &[ + "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", + "E0729", "E0789", +]; + +macro_rules! verbose_print { + ($verbose:expr, $($fmt:tt)*) => { + if $verbose { + println!("{}", format_args!($($fmt)*)); + } + }; +} + +pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut bool) { + let mut errors = Vec::new(); + + // Stage 1: create list + let error_codes = extract_error_codes(root_path, &mut errors, verbose); + println!("Found {} error codes", error_codes.len()); + println!("Highest error code: `{}`", error_codes.iter().max().unwrap()); + + // Stage 2: check list has docs + let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose); + + // Stage 3: check list has UI tests + check_error_codes_tests(root_path, &error_codes, &mut errors, verbose); + + // Stage 4: check list is emitted by compiler + check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose); + + // Print any errors. + for error in errors { + tidy_error!(bad, "{}", error); + } +} + +/// Stage 1: Parses a list of error codes from `error_codes.rs`. +fn extract_error_codes(root_path: &Path, errors: &mut Vec, verbose: bool) -> Vec { + let path = root_path.join(Path::new(ERROR_CODES_PATH)); + let file = + fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}")); + + let mut error_codes = Vec::new(); + let mut reached_undocumented_codes = false; + + for line in file.lines() { + let line = line.trim(); + + if !reached_undocumented_codes && line.starts_with('E') { + let split_line = line.split_once(':'); + + // Extract the error code from the line, emitting a fatal error if it is not in a correct format. + let err_code = if let Some(err_code) = split_line { + err_code.0.to_owned() + } else { + errors.push(format!( + "Expected a line with the format `Exxxx: include_str!(\"..\")`, but got \"{}\" \ + without a `:` delimiter", + line, + )); + continue; + }; + + // If this is a duplicate of another error code, emit a fatal error. + if error_codes.contains(&err_code) { + errors.push(format!("Found duplicate error code: `{}`", err_code)); + continue; + } + + // Ensure that the line references the correct markdown file. + let expected_filename = format!(" include_str!(\"./error_codes/{}.md\"),", err_code); + if expected_filename != split_line.unwrap().1 { + errors.push(format!( + "Error code `{}` expected to reference docs with `{}` but instead found `{}` in \ + `compiler/rustc_error_codes/src/error_codes.rs`", + err_code, + expected_filename, + split_line.unwrap().1, + )); + continue; + } + + error_codes.push(err_code); + } else if reached_undocumented_codes && line.starts_with('E') { + let err_code = match line.split_once(',') { + None => line, + Some((err_code, _)) => err_code, + } + .to_string(); + + verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code); + + if error_codes.contains(&err_code) { + errors.push(format!("Found duplicate error code: `{}`", err_code)); + } + + error_codes.push(err_code); + } else if line == ";" { + // Once we reach the undocumented error codes, adapt to different syntax. + reached_undocumented_codes = true; + } + } + + error_codes +} + +/// Stage 2: Checks that long-form error code explanations exist and have doctests. +fn check_error_codes_docs( + root_path: &Path, + error_codes: &[String], + errors: &mut Vec, + verbose: bool, +) -> Vec { + let docs_path = root_path.join(Path::new(ERROR_DOCS_PATH)); + + let mut no_longer_emitted_codes = Vec::new(); + + walk(&docs_path, &mut |_| false, &mut |entry, contents| { + let path = entry.path(); + + // Error if the file isn't markdown. + if path.extension() != Some(OsStr::new("md")) { + errors.push(format!( + "Found unexpected non-markdown file in error code docs directory: {}", + path.display() + )); + return; + } + + // Make sure that the file is referenced in `error_codes.rs` + let filename = path.file_name().unwrap().to_str().unwrap().split_once('.'); + let err_code = filename.unwrap().0; // `unwrap` is ok because we know the filename is in the correct format. + + if error_codes.iter().all(|e| e != err_code) { + errors.push(format!( + "Found valid file `{}` in error code docs directory without corresponding \ + entry in `error_code.rs`", + path.display() + )); + return; + } + + let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = + check_explanation_has_doctest(&contents, &err_code); + if emit_ignore_warning { + verbose_print!( + verbose, + "warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \ + `IGNORE_DOCTEST_CHECK` constant instead." + ); + } + if emit_no_longer_warning { + no_longer_emitted_codes.push(err_code.to_owned()); + verbose_print!( + verbose, + "warning: Error code `{err_code}` is no longer emitted and should be removed entirely." + ); + } + if !found_code_example { + verbose_print!( + verbose, + "warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \ + (even if untested)." + ); + } + + let test_ignored = IGNORE_DOCTEST_CHECK.contains(&&err_code); + + // Check that the explanation has a doctest, and if it shouldn't, that it doesn't + if !found_proper_doctest && !test_ignored { + errors.push(format!( + "`{}` doesn't use its own error code in compile_fail example", + path.display(), + )); + } else if found_proper_doctest && test_ignored { + errors.push(format!( + "`{}` has a compile_fail doctest with its own error code, it shouldn't \ + be listed in `IGNORE_DOCTEST_CHECK`", + path.display(), + )); + } + }); + + no_longer_emitted_codes +} + +/// This function returns a tuple indicating whether the provided explanation: +/// a) has a code example, tested or not. +/// b) has a valid doctest +fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bool, bool, bool) { + let mut found_code_example = false; + let mut found_proper_doctest = false; + + let mut emit_ignore_warning = false; + let mut emit_no_longer_warning = false; + + for line in explanation.lines() { + let line = line.trim(); + + if line.starts_with("```") { + found_code_example = true; + + // Check for the `rustdoc` doctest headers. + if line.contains("compile_fail") && line.contains(err_code) { + found_proper_doctest = true; + } + + if line.contains("ignore") { + emit_ignore_warning = true; + found_proper_doctest = true; + } + } else if line + .starts_with("#### Note: this error code is no longer emitted by the compiler") + { + emit_no_longer_warning = true; + found_code_example = true; + found_proper_doctest = true; + } + } + + (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) +} + +// Stage 3: Checks that each error code has a UI test in the correct directory +fn check_error_codes_tests( + root_path: &Path, + error_codes: &[String], + errors: &mut Vec, + verbose: bool, +) { + let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH)); + + for code in error_codes { + let test_path = tests_path.join(format!("{}.stderr", code)); + + if !test_path.exists() && !IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { + verbose_print!( + verbose, + "warning: Error code `{code}` needs to have at least one UI test in the `src/test/ui/error-codes/` directory`!" + ); + continue; + } + if IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { + if test_path.exists() { + errors.push(format!( + "Error code `{code}` has a UI test in `src/test/ui/error-codes/{code}.rs`, it shouldn't be listed in `EXEMPTED_FROM_TEST`!" + )); + } + continue; + } + + let file = match fs::read_to_string(&test_path) { + Ok(file) => file, + Err(err) => { + verbose_print!( + verbose, + "warning: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}", + test_path.display() + ); + continue; + } + }; + + let mut found_code = false; + + for line in file.lines() { + let s = line.trim(); + // Assuming the line starts with `error[E`, we can substring the error code out. + if s.starts_with("error[E") { + if &s[6..11] == code { + found_code = true; + break; + } + }; + } + + if !found_code { + verbose_print!( + verbose, + "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!" + ); + } + } +} + +/// Stage 4: Search `compiler/` and ensure that every error code is actually used by the compiler and that no undocumented error codes exist. +fn check_error_codes_used( + search_paths: &[&Path], + error_codes: &[String], + errors: &mut Vec, + no_longer_emitted: &[String], + verbose: bool, +) { + // We want error codes which match the following cases: + // + // * foo(a, E0111, a) + // * foo(a, E0111) + // * foo(E0111, a) + // * #[error = "E0111"] + let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); + + let mut found_codes = Vec::new(); + + walk_many(search_paths, &mut filter_dirs, &mut |entry, contents| { + let path = entry.path(); + + // Return early if we aren't looking at a source file. + if path.extension() != Some(OsStr::new("rs")) { + return; + } + + for line in contents.lines() { + // We want to avoid parsing error codes in comments. + if line.trim_start().starts_with("//") { + continue; + } + + for cap in regex.captures_iter(line) { + if let Some(error_code) = cap.get(1) { + let error_code = error_code.as_str().to_owned(); + + if !error_codes.contains(&error_code) { + // This error code isn't properly defined, we must error. + errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/error_codes.rs`.", error_code)); + continue; + } + + // This error code can now be marked as used. + found_codes.push(error_code); + } + } + } + }); + + for code in error_codes { + if !found_codes.contains(code) && !no_longer_emitted.contains(code) { + errors.push(format!("Error code `{code}` exists, but is not emitted by the compiler!")) + } + + if found_codes.contains(code) && no_longer_emitted.contains(code) { + verbose_print!( + verbose, + "warning: Error code `{code}` is used when it's marked as \"no longer emitted\"" + ); + } + } +} diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs deleted file mode 100644 index 3f060e437aca7..0000000000000 --- a/src/tools/tidy/src/error_codes_check.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Checks that all error codes have at least one test to prevent having error -//! codes that are silently not thrown by the compiler anymore. - -use crate::walk::{filter_dirs, walk}; -use std::collections::{HashMap, HashSet}; -use std::ffi::OsStr; -use std::fs::read_to_string; -use std::path::Path; - -use regex::Regex; - -// A few of those error codes can't be tested but all the others can and *should* be tested! -const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0313", "E0461", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", - "E0789", -]; - -// Some error codes don't have any tests apparently... -const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0729"]; - -// If the file path contains any of these, we don't want to try to extract error codes from it. -// -// We need to declare each path in the windows version (with backslash). -const PATHS_TO_IGNORE_FOR_EXTRACTION: &[&str] = - &["src/test/", "src\\test\\", "src/doc/", "src\\doc\\", "src/tools/", "src\\tools\\"]; - -#[derive(Default, Debug)] -struct ErrorCodeStatus { - has_test: bool, - has_explanation: bool, - is_used: bool, -} - -fn check_error_code_explanation( - f: &str, - error_codes: &mut HashMap, - err_code: String, -) -> bool { - let mut invalid_compile_fail_format = false; - let mut found_error_code = false; - - for line in f.lines() { - let s = line.trim(); - if s.starts_with("```") { - if s.contains("compile_fail") && s.contains('E') { - if !found_error_code { - error_codes.get_mut(&err_code).map(|x| x.has_test = true); - found_error_code = true; - } - } else if s.contains("compile-fail") { - invalid_compile_fail_format = true; - } - } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { - if !found_error_code { - error_codes.get_mut(&err_code).map(|x| x.has_test = true); - found_error_code = true; - } - } - } - invalid_compile_fail_format -} - -fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { - let mut ignore_found = false; - - for line in f.lines() { - let s = line.trim(); - if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { - return true; - } - if s.starts_with("```") { - if s.contains("compile_fail") && s.contains(err_code) { - return true; - } else if s.contains("ignore") { - // It's very likely that we can't actually make it fail compilation... - ignore_found = true; - } - } - } - ignore_found -} - -fn extract_error_codes( - f: &str, - error_codes: &mut HashMap, - path: &Path, - errors: &mut Vec, -) { - let mut reached_no_explanation = false; - - for line in f.lines() { - let s = line.trim(); - if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") { - let err_code = s - .split_once(':') - .expect( - format!( - "Expected a line with the format `E0xxx: include_str!(\"..\")`, but got {} \ - without a `:` delimiter", - s, - ) - .as_str(), - ) - .0 - .to_owned(); - error_codes.entry(err_code.clone()).or_default().has_explanation = true; - - // Now we extract the tests from the markdown file! - let md_file_name = match s.split_once("include_str!(\"") { - None => continue, - Some((_, md)) => match md.split_once("\")") { - None => continue, - Some((file_name, _)) => file_name, - }, - }; - - let Some(parent) = path.parent() else { - continue; - }; - - let path = parent - .join(md_file_name) - .canonicalize() - .expect("failed to canonicalize error explanation file path"); - - match read_to_string(&path) { - Ok(content) => { - let has_test = check_if_error_code_is_test_in_explanation(&content, &err_code); - if !has_test && !IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) { - errors.push(format!( - "`{}` doesn't use its own error code in compile_fail example", - path.display(), - )); - } else if has_test && IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) { - errors.push(format!( - "`{}` has a compile_fail example with its own error code, it shouldn't \ - be listed in IGNORE_EXPLANATION_CHECK!", - path.display(), - )); - } - if check_error_code_explanation(&content, error_codes, err_code) { - errors.push(format!( - "`{}` uses invalid tag `compile-fail` instead of `compile_fail`", - path.display(), - )); - } - } - Err(e) => { - eprintln!("Couldn't read `{}`: {}", path.display(), e); - } - } - } else if reached_no_explanation && s.starts_with('E') { - let err_code = match s.split_once(',') { - None => s, - Some((err_code, _)) => err_code, - } - .to_string(); - if !error_codes.contains_key(&err_code) { - // this check should *never* fail! - error_codes.insert(err_code, ErrorCodeStatus::default()); - } - } else if s == ";" { - reached_no_explanation = true; - } - } -} - -fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap) { - for line in f.lines() { - let s = line.trim(); - if s.starts_with("error[E") || s.starts_with("warning[E") { - let err_code = match s.split_once(']') { - None => continue, - Some((err_code, _)) => match err_code.split_once('[') { - None => continue, - Some((_, err_code)) => err_code, - }, - }; - error_codes.entry(err_code.to_owned()).or_default().has_test = true; - } - } -} - -fn extract_error_codes_from_source( - f: &str, - error_codes: &mut HashMap, - regex: &Regex, -) { - for line in f.lines() { - if line.trim_start().starts_with("//") { - continue; - } - for cap in regex.captures_iter(line) { - if let Some(error_code) = cap.get(1) { - error_codes.entry(error_code.as_str().to_owned()).or_default().is_used = true; - } - } - } -} - -pub fn check(paths: &[&Path], bad: &mut bool) { - let mut errors = Vec::new(); - let mut found_explanations = 0; - let mut found_tests = 0; - let mut error_codes: HashMap = HashMap::new(); - let mut explanations: HashSet = HashSet::new(); - // We want error codes which match the following cases: - // - // * foo(a, E0111, a) - // * foo(a, E0111) - // * foo(E0111, a) - // * #[error = "E0111"] - let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); - - for path in paths { - walk(path, &mut filter_dirs, &mut |entry, contents| { - let file_name = entry.file_name(); - let entry_path = entry.path(); - - if file_name == "error_codes.rs" { - extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors); - found_explanations += 1; - } else if entry_path.extension() == Some(OsStr::new("stderr")) { - extract_error_codes_from_tests(contents, &mut error_codes); - found_tests += 1; - } else if entry_path.extension() == Some(OsStr::new("rs")) { - let path = entry.path().to_string_lossy(); - if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) { - extract_error_codes_from_source(contents, &mut error_codes, ®ex); - } - } else if entry_path - .parent() - .and_then(|p| p.file_name()) - .map(|p| p == "error_codes") - .unwrap_or(false) - && entry_path.extension() == Some(OsStr::new("md")) - { - explanations.insert(file_name.to_str().unwrap().replace(".md", "")); - } - }); - } - if found_explanations == 0 { - tidy_error!(bad, "No error code explanation was tested!"); - } - if found_tests == 0 { - tidy_error!(bad, "No error code was found in compilation errors!"); - } - if explanations.is_empty() { - tidy_error!(bad, "No error code explanation was found!"); - } - if errors.is_empty() { - for (err_code, error_status) in &error_codes { - if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { - errors.push(format!("Error code {err_code} needs to have at least one UI test!")); - } else if error_status.has_test && EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { - errors.push(format!( - "Error code {} has a UI test, it shouldn't be listed into EXEMPTED_FROM_TEST!", - err_code - )); - } - if !error_status.is_used && !error_status.has_explanation { - errors.push(format!( - "Error code {} isn't used and doesn't have an error explanation, it should be \ - commented in error_codes.rs file", - err_code - )); - } - } - } - if errors.is_empty() { - // Checking if local constants need to be cleaned. - for err_code in EXEMPTED_FROM_TEST { - match error_codes.get(err_code.to_owned()) { - Some(status) => { - if status.has_test { - errors.push(format!( - "{} error code has a test and therefore should be \ - removed from the `EXEMPTED_FROM_TEST` constant", - err_code - )); - } - } - None => errors.push(format!( - "{} error code isn't used anymore and therefore should be removed \ - from `EXEMPTED_FROM_TEST` constant", - err_code - )), - } - } - } - if errors.is_empty() { - for explanation in explanations { - if !error_codes.contains_key(&explanation) { - errors.push(format!( - "{} error code explanation should be listed in `error_codes.rs`", - explanation - )); - } - } - } - errors.sort(); - for err in &errors { - tidy_error!(bad, "{err}"); - } -} diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs deleted file mode 100644 index fe5fd72b91a49..0000000000000 --- a/src/tools/tidy/src/errors.rs +++ /dev/null @@ -1,77 +0,0 @@ -//! Tidy check to verify the validity of long error diagnostic codes. -//! -//! This ensures that error codes are used at most once and also prints out some -//! statistics about the error codes. - -use crate::walk::{filter_dirs, walk}; -use std::collections::HashMap; -use std::path::Path; - -pub fn check(path: &Path, bad: &mut bool) { - let mut map: HashMap<_, Vec<_>> = HashMap::new(); - walk( - path, - &mut |path| filter_dirs(path) || path.ends_with("src/test"), - &mut |entry, contents| { - let file = entry.path(); - let filename = file.file_name().unwrap().to_string_lossy(); - if filename != "error_codes.rs" { - return; - } - - // In the `register_long_diagnostics!` macro, entries look like this: - // - // ``` - // EXXXX: r##" - // - // "##, - // ``` - // - // and these long messages often have error codes themselves inside - // them, but we don't want to report duplicates in these cases. This - // variable keeps track of whether we're currently inside one of these - // long diagnostic messages. - let mut inside_long_diag = false; - for (num, line) in contents.lines().enumerate() { - if inside_long_diag { - inside_long_diag = !line.contains("\"##"); - continue; - } - - let mut search = line; - while let Some(i) = search.find('E') { - search = &search[i + 1..]; - let code = if search.len() > 4 { search[..4].parse::() } else { continue }; - let code = match code { - Ok(n) => n, - Err(..) => continue, - }; - map.entry(code).or_default().push((file.to_owned(), num + 1, line.to_owned())); - break; - } - - inside_long_diag = line.contains("r##\""); - } - }, - ); - - let mut max = 0; - for (&code, entries) in map.iter() { - if code > max { - max = code; - } - if entries.len() == 1 { - continue; - } - - tidy_error!(bad, "duplicate error code: {}", code); - for &(ref file, line_num, ref line) in entries.iter() { - tidy_error!(bad, "{}:{}: {}", file.display(), line_num, line); - } - } - - if !*bad { - println!("* {} error codes", map.len()); - println!("* highest error code: E{:04}", max); - } -} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 4075f2616b0fd..15c641d748c8e 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -56,8 +56,7 @@ pub mod bins; pub mod debug_artifacts; pub mod deps; pub mod edition; -pub mod error_codes_check; -pub mod errors; +pub mod error_codes; pub mod extdeps; pub mod features; pub mod mir_opt_tests; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 7bb8ddc6949ef..a5685ba7c942c 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -27,6 +27,7 @@ fn main() { let src_path = root_path.join("src"); let library_path = root_path.join("library"); let compiler_path = root_path.join("compiler"); + let librustdoc_path = src_path.join("librustdoc"); let args: Vec = env::args().skip(1).collect(); @@ -79,8 +80,7 @@ fn main() { check!(mir_opt_tests, &src_path, bless); // Checks that only make sense for the compiler. - check!(errors, &compiler_path); - check!(error_codes_check, &[&src_path, &compiler_path]); + check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); // Checks that only make sense for the std libs. check!(pal, &library_path);