diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index b21defaedc313..2e32ce31ecae0 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -355,7 +355,38 @@ $ rustdoc src/lib.rs --edition 2018 $ rustdoc --test src/lib.rs --edition 2018 ``` -This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with +This flag allows `rustdoc` to treat your rust code as the given edition. It will compile doctests with the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015` (the first edition). +## `--theme`: add a theme to the documentation output + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --theme /path/to/your/custom-theme.css +``` + +`rustdoc`'s default output includes two themes: `light` (the default) and +`dark`. This flag allows you to add custom themes to the output. Giving a CSS +file to this flag adds it to your documentation as an additional theme choice. +The theme's name is determined by its filename; a theme file named +`custom-theme.css` will add a theme named `custom-theme` to the documentation. + +## `--check-theme`: verify custom themes against the default theme + +Using this flag looks like this: + +```bash +$ rustdoc --check-theme /path/to/your/custom-theme.css +``` + +While `rustdoc`'s HTML output is more-or-less consistent between versions, there +is no guarantee that a theme file will have the same effect. The `--theme` flag +will still allow you to add the theme to your documentation, but to ensure that +your theme works as expected, you can use this flag to verify that it implements +the same CSS rules as the official `light` theme. + +`--check-theme` is a separate mode in `rustdoc`. When `rustdoc` sees the +`--check-theme` flag, it discards all other flags and only performs the CSS rule +comparison operation. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index f8be04a1087bf..a48526d39fd0a 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -294,30 +294,6 @@ some consideration for their stability, and names that end in a number). Giving `rustdoc` will disable this sorting and instead make it print the items in the order they appear in the source. -### `--themes`: provide additional themes - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --themes theme.css -``` - -Giving this flag to `rustdoc` will make it copy your theme into the generated crate docs and enable -it in the theme selector. Note that `rustdoc` will reject your theme file if it doesn't style -everything the "light" theme does. See `--theme-checker` below for details. - -### `--theme-checker`: verify theme CSS for validity - -Using this flag looks like this: - -```bash -$ rustdoc -Z unstable-options --theme-checker theme.css -``` - -Before including your theme in crate docs, `rustdoc` will compare all the CSS rules it contains -against the "light" theme included by default. Using this flag will allow you to see which rules are -missing if `rustdoc` rejects your theme. - ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs Using this flag looks like this: diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 428cecf13a3b0..105a71b72902c 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -350,6 +350,7 @@ E0635: include_str!("./error_codes/E0635.md"), E0636: include_str!("./error_codes/E0636.md"), E0638: include_str!("./error_codes/E0638.md"), E0639: include_str!("./error_codes/E0639.md"), +E0641: include_str!("./error_codes/E0641.md"), E0642: include_str!("./error_codes/E0642.md"), E0643: include_str!("./error_codes/E0643.md"), E0644: include_str!("./error_codes/E0644.md"), @@ -584,7 +585,6 @@ E0744: include_str!("./error_codes/E0744.md"), E0634, // type has conflicting packed representaton hints E0637, // "'_" is not a valid lifetime bound E0640, // infer outlives requirements - E0641, // cannot cast to/from a pointer with an unknown kind // E0645, // trait aliases not finished E0657, // `impl Trait` can only capture lifetimes bound at the fn level E0667, // `impl Trait` in projections diff --git a/src/librustc_error_codes/error_codes/E0641.md b/src/librustc_error_codes/error_codes/E0641.md new file mode 100644 index 0000000000000..e39bebce1fea6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0641.md @@ -0,0 +1,19 @@ +Attempted to cast to/from a pointer with an unknown kind. + +Erroneous code examples: + +```compile_fail,E0641 +let b = 0 as *const _; // error +``` + +Must give information for type of pointer that is being cast from/to if the +type cannot be inferred. + +``` +// Creating a pointer from reference: type can be inferred +let a = &(String::from("Hello world!")) as *const _; // Ok + +let b = 0 as *const i32; // Ok + +let c: *const i32 = 0 as *const _; // Ok +``` \ No newline at end of file diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 3e1c57182b9f5..cdb1a1f6997c9 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; @@ -281,12 +282,12 @@ impl Options { // check for deprecated options check_deprecated_options(&matches, &diag); - let to_check = matches.opt_strs("theme-checker"); + let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes()); let mut errors = 0; - println!("rustdoc: [theme-checker] Starting tests!"); + println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)"); for theme_file in to_check.iter() { print!(" - Checking \"{}\"...", theme_file); let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag); @@ -357,23 +358,35 @@ impl Options { } let mut themes = Vec::new(); - if matches.opt_present("themes") { + if matches.opt_present("theme") { let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes()); - for (theme_file, theme_s) in matches.opt_strs("themes") + for (theme_file, theme_s) in matches.opt_strs("theme") .iter() .map(|s| (PathBuf::from(&s), s.to_owned())) { if !theme_file.is_file() { - diag.struct_err("option --themes arguments must all be files").emit(); + diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)) + .help("arguments to --theme must be files") + .emit(); return Err(1); } - let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag); - if !success || !ret.is_empty() { - diag.struct_err(&format!("invalid theme: \"{}\"", theme_s)) - .help("check what's wrong with the --theme-checker option") + if theme_file.extension() != Some(OsStr::new("css")) { + diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)) .emit(); return Err(1); } + let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag); + if !success { + diag.struct_err(&format!("error loading theme file: \"{}\"", theme_s)).emit(); + return Err(1); + } else if !ret.is_empty() { + diag.struct_warn(&format!("theme file \"{}\" is missing CSS rules from the \ + default theme", theme_s)) + .warn("the theme may appear incorrect when loaded") + .help(&format!("to see what rules are missing, call `rustdoc \ + --check-theme \"{}\"`", theme_s)) + .emit(); + } themes.push(theme_file); } } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 697dee0216e3b..8249e69e9a74f 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use crate::externalfiles::ExternalHtml; +use crate::html::escape::Escape; use crate::html::render::ensure_trailing_slash; use crate::html::format::{Buffer, Print}; @@ -166,10 +167,11 @@ pub fn render( themes = themes.iter() .filter_map(|t| t.file_stem()) .filter_map(|t| t.to_str()) - .map(|t| format!(r#""#, - static_root_path, - t, - page.resource_suffix)) + .map(|t| format!(r#""#, + Escape(&format!("{}{}{}", + static_root_path, + t, + page.resource_suffix)))) .collect::(), suffix=page.resource_suffix, static_extra_scripts=page.static_extra_scripts.iter().map(|e| { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9ff1e1d31197d..fc4dc52f127df 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -680,9 +680,7 @@ impl LangString { seen_rust_tags = !seen_other_tags || seen_rust_tags; data.no_run = true; } - x if allow_error_code_check && x.starts_with("edition") => { - // allow_error_code_check is true if we're on nightly, which - // is needed for edition support + x if x.starts_with("edition") => { data.edition = x[7..].parse::().ok(); } x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9a87bcc10db8e..1207c5e3bc58d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -633,19 +633,16 @@ function handleThemeButtonsBlur(e) {{ themePicker.onclick = switchThemeButtonState; themePicker.onblur = handleThemeButtonsBlur; -[{}].forEach(function(item) {{ +{}.forEach(function(item) {{ var but = document.createElement('button'); - but.innerHTML = item; + but.textContent = item; but.onclick = function(el) {{ switchTheme(currentTheme, mainTheme, item, true); }}; but.onblur = handleThemeButtonsBlur; themes.appendChild(but); }});"#, - themes.iter() - .map(|s| format!("\"{}\"", s)) - .collect::>() - .join(",")); + as_json(&themes)); write(cx.dst.join(&format!("theme{}.js", cx.shared.resource_suffix)), theme_js.as_bytes() )?; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 752b93f2ac5e3..197efb7cac80d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -396,38 +396,51 @@ function getSearchElement() { document.onkeypress = handleShortcut; document.onkeydown = handleShortcut; - document.onclick = function(ev) { - if (hasClass(ev.target, "collapse-toggle")) { - collapseDocs(ev.target, "toggle"); - } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { - collapseDocs(ev.target.parentNode, "toggle"); - } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { - var prev_id = 0; - var set_fragment = function(name) { - if (browserSupportsHistoryApi()) { - history.replaceState(null, null, "#" + name); - highlightSourceLines(); - } else { - location.replace("#" + name); - } - }; + var handleSourceHighlight = (function() { + var prev_line_id = 0; - var cur_id = parseInt(ev.target.id, 10); + var set_fragment = function(name) { + var x = window.scrollX, + y = window.scrollY; + if (browserSupportsHistoryApi()) { + history.replaceState(null, null, "#" + name); + highlightSourceLines(); + } else { + location.replace("#" + name); + } + // Prevent jumps when selecting one or many lines + window.scrollTo(x, y); + }; + + return function(ev) { + var cur_line_id = parseInt(ev.target.id, 10); + ev.preventDefault(); - if (ev.shiftKey && prev_id) { - if (prev_id > cur_id) { - var tmp = prev_id; - prev_id = cur_id; - cur_id = tmp; + if (ev.shiftKey && prev_line_id) { + // Swap selection if needed + if (prev_line_id > cur_line_id) { + var tmp = prev_line_id; + prev_line_id = cur_line_id; + cur_line_id = tmp; } - set_fragment(prev_id + "-" + cur_id); + set_fragment(prev_line_id + "-" + cur_line_id); } else { - prev_id = cur_id; + prev_line_id = cur_line_id; - set_fragment(cur_id); + set_fragment(cur_line_id); } + } + })(); + + document.onclick = function(ev) { + if (hasClass(ev.target, "collapse-toggle")) { + collapseDocs(ev.target, "toggle"); + } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { + collapseDocs(ev.target.parentNode, "toggle"); + } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { + handleSourceHighlight(ev); } else if (hasClass(getHelpElement(), "hidden") === false) { var help = getHelpElement(); var is_inside_help_popup = ev.target !== help && help.contains(ev.target); diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 3a2c24b1a967f..9fc1d76185fb7 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -59,7 +59,7 @@ pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico"); /// The built-in themes given to every documentation site. pub mod themes { /// The "light" theme, selected by default when no setting is available. Used as the basis for - /// the `--theme-checker` functionality. + /// the `--check-theme` functionality. pub static LIGHT: &'static str = include_str!("static/themes/light.css"); /// The "dark" theme. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8bfaf98f0867e..277475f6fffd8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -252,13 +252,13 @@ fn opts() -> Vec { o.optflag("", "sort-modules-by-appearance", "sort modules by where they appear in the \ program, rather than alphabetically") }), - unstable("themes", |o| { - o.optmulti("", "themes", + stable("theme", |o| { + o.optmulti("", "theme", "additional themes which will be added to the generated docs", "FILES") }), - unstable("theme-checker", |o| { - o.optmulti("", "theme-checker", + stable("check-theme", |o| { + o.optmulti("", "check-theme", "check if given theme is valid", "FILES") }), diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 7037a146c50ab..1be85f4a91d0e 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -273,6 +273,7 @@ pub fn test_theme_against>( diag: &Handler, ) -> (bool, Vec) { let data = try_something!(fs::read(f), diag, (false, vec![])); + let paths = load_css_paths(&data); let mut ret = vec![]; get_differences(against, &paths, &mut ret); diff --git a/src/test/run-make-fulldeps/rustdoc-themes/Makefile b/src/test/run-make-fulldeps/rustdoc-themes/Makefile new file mode 100644 index 0000000000000..f5a471e66e573 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-themes/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# Test that rustdoc will properly load in a theme file and display it in the theme selector. + +OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes" + +all: + cp $(S)/src/librustdoc/html/static/themes/light.css $(TMPDIR)/test.css + $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css + $(HTMLDOCCK) $(OUTPUT_DIR) foo.rs diff --git a/src/test/run-make-fulldeps/rustdoc-themes/foo.rs b/src/test/run-make-fulldeps/rustdoc-themes/foo.rs new file mode 100644 index 0000000000000..58efaf7d5a05a --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-themes/foo.rs @@ -0,0 +1,4 @@ +// @has test.css +// @has foo/struct.Foo.html +// @has - '//link[@rel="stylesheet"]/@href' '../test.css' +pub struct Foo; diff --git a/src/test/rustdoc/edition-flag.rs b/src/test/rustdoc/edition-flag.rs index ddbc2be651d90..e54c7d2969bfe 100644 --- a/src/test/rustdoc/edition-flag.rs +++ b/src/test/rustdoc/edition-flag.rs @@ -1,4 +1,4 @@ -// compile-flags:--test -Z unstable-options +// compile-flags:--test // edition:2018 /// ```rust diff --git a/src/test/ui/issues/issue-45730.stderr b/src/test/ui/issues/issue-45730.stderr index 4fc1e3835f7ad..3c400d6eefaa8 100644 --- a/src/test/ui/issues/issue-45730.stderr +++ b/src/test/ui/issues/issue-45730.stderr @@ -30,3 +30,4 @@ LL | let x = 0 as *const i32 as *const _ as *mut _; error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0641`. diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr index 01e59f8f022fd..081038c573acf 100644 --- a/src/test/ui/order-dependent-cast-inference.stderr +++ b/src/test/ui/order-dependent-cast-inference.stderr @@ -10,3 +10,4 @@ LL | let mut y = 0 as *const _; error: aborting due to previous error +For more information about this error, try `rustc --explain E0641`. diff --git a/src/tools/rustdoc-themes/main.rs b/src/tools/rustdoc-themes/main.rs index 616b5444832c1..a549b0d0efaac 100644 --- a/src/tools/rustdoc-themes/main.rs +++ b/src/tools/rustdoc-themes/main.rs @@ -38,9 +38,11 @@ fn main() { eprintln!("No theme found in \"{}\"...", themes_folder); exit(1); } + let arg_name = "--check-theme".to_owned(); let status = Command::new(rustdoc_bin) - .args(&["-Z", "unstable-options", "--theme-checker"]) - .args(&themes) + .args(&themes.iter() + .flat_map(|t| vec![&arg_name, t].into_iter()) + .collect::>()) .status() .expect("failed to execute child"); if !status.success() {