From 2792b56a92eec4a88b2d625d4584074c3918ef6f Mon Sep 17 00:00:00 2001 From: kennytm Date: Wed, 15 Nov 2017 17:31:23 +0800 Subject: [PATCH] Support `extern type` in rustdoc. Fixes #45640. --- src/librustdoc/clean/inline.rs | 5 ++++ src/librustdoc/html/render.rs | 31 ++++++++++++++++++++-- src/librustdoc/html/static/main.js | 4 ++- src/librustdoc/html/static/styles/main.css | 2 ++ src/test/rustdoc/foreigntype.rs | 28 +++++++++++++++++++ 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/foreigntype.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9fb9437e1bc9a..4c518167e088d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -77,6 +77,11 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) ret.extend(build_impls(cx, did)); clean::EnumItem(build_enum(cx, did)) } + Def::TyForeign(did) => { + record_extern_fqn(cx, did, clean::TypeKind::Foreign); + ret.extend(build_impls(cx, did)); + clean::ForeignTypeItem + } // Never inline enum variants but leave them shown as reexports. Def::Variant(..) => return None, // Assume that enum variants and struct types are reexported next to diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 69eaf24289bfc..27a27c71bc9da 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1257,7 +1257,7 @@ impl DocFolder for Cache { clean::FunctionItem(..) | clean::ModuleItem(..) | clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | clean::ConstantItem(..) | clean::StaticItem(..) | - clean::UnionItem(..) + clean::UnionItem(..) | clean::ForeignTypeItem if !self.stripped_mod => { // Reexported items mean that the same id can show up twice // in the rustdoc ast that we're looking at. We know, @@ -1292,7 +1292,7 @@ impl DocFolder for Cache { // Maintain the parent stack let orig_parent_is_trait_impl = self.parent_is_trait_impl; let parent_pushed = match item.inner { - clean::TraitItem(..) | clean::EnumItem(..) | + clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem | clean::StructItem(..) | clean::UnionItem(..) => { self.parent_stack.push(item.def_id); self.parent_is_trait_impl = false; @@ -1711,6 +1711,7 @@ impl<'a> fmt::Display for Item<'a> { clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, clean::ConstantItem(..) => write!(fmt, "Constant ")?, + clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, _ => { // We don't generate pages for any other type. unreachable!(); @@ -1775,6 +1776,7 @@ impl<'a> fmt::Display for Item<'a> { clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(fmt, self.cx, self.item, i), clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), + clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), _ => { // We don't generate pages for any other type. unreachable!(); @@ -3429,6 +3431,21 @@ fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } +fn item_foreign_type(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item) -> fmt::Result { + writeln!(w, "
extern {{")?;
+    render_attributes(w, it)?;
+    write!(
+        w,
+        "    {}type {};\n}}
", + VisSpace(&it.visibility), + it.name.as_ref().unwrap(), + )?; + + document(w, cx, it)?; + + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) +} + impl<'a> fmt::Display for Sidebar<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let cx = self.cx; @@ -3446,6 +3463,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::UnionItem(..) => write!(fmt, "Union ")?, clean::EnumItem(..) => write!(fmt, "Enum ")?, clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, + clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, clean::ModuleItem(..) => if it.is_crate() { write!(fmt, "Crate ")?; } else { @@ -3474,6 +3492,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?, clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?, clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?, + clean::ForeignTypeItem => sidebar_foreign_type(fmt, it)?, _ => (), } } @@ -3897,6 +3916,14 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item, Ok(()) } +fn sidebar_foreign_type(fmt: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { + let sidebar = sidebar_assoc_items(it); + if !sidebar.is_empty() { + write!(fmt, "
{}
", sidebar)?; + } + Ok(()) +} + impl<'a> fmt::Display for Source<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let Source(s) = *self; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 8d0faf261f6c9..3350a9f73876f 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -37,7 +37,8 @@ "associatedtype", "constant", "associatedconstant", - "union"]; + "union", + "foreigntype"]; // On the search screen, so you remain on the last tab you opened. // @@ -1445,6 +1446,7 @@ block("trait", "Traits"); block("fn", "Functions"); block("type", "Type Definitions"); + block("foreigntype", "Foreign Types"); } window.initSidebarItems = initSidebarItems; diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 4a4ca15170a46..cb19034bf0612 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -104,6 +104,7 @@ pre { .content .highlighted.method, .content .highlighted.tymethod { background-color: #c6afb3; } .content .highlighted.type { background-color: #ffc891; } +.content .highlighted.foreigntype { background-color: #f5c4ff; } .content .highlighted.macro { background-color: #8ce488; } .content .highlighted.constant, .content .highlighted.static { background-color: #c3e0ff; } @@ -112,6 +113,7 @@ pre { .content span.enum, .content a.enum, .block a.current.enum { color: #508157; } .content span.struct, .content a.struct, .block a.current.struct { color: #df3600; } .content span.type, .content a.type, .block a.current.type { color: #ba5d00; } +.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; } .content span.macro, .content a.macro, .block a.current.macro { color: #068000; } .content span.union, .content a.union, .block a.current.union { color: #767b27; } .content span.constant, .content a.constant, .block a.current.constant, diff --git a/src/test/rustdoc/foreigntype.rs b/src/test/rustdoc/foreigntype.rs new file mode 100644 index 0000000000000..06447ffaa753d --- /dev/null +++ b/src/test/rustdoc/foreigntype.rs @@ -0,0 +1,28 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(extern_types)] + +extern { + // @has foreigntype/foreigntype.ExtType.html + pub type ExtType; +} + +impl ExtType { + // @has - '//a[@class="fnname"]' 'do_something' + pub fn do_something(&self) {} +} + +pub trait Trait {} + +// @has foreigntype/trait.Trait.html '//a[@class="foreigntype"]' 'ExtType' +impl Trait for ExtType {} + +// @has foreigntype/index.html '//a[@class="foreigntype"]' 'ExtType'