Auto merge of #107989 - matthiaskrgr:rollup-jklrd5g, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #107340 (rustdoc: merge doctest tooltip with notable traits tooltip) - #107838 (Introduce `-Zterminal-urls` to use OSC8 for error codes) - #107922 (Print disk usage in PGO CI script) - #107931 (Intern span when length is MAX_LEN with parent.) - #107935 (rustc_ast: Merge impls and reorder methods for attributes and meta items) - #107986 (layout: deal with placeholders, ICE on bound types) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0b439b119b
33 changed files with 713 additions and 651 deletions
|
@ -40,310 +40,6 @@ impl MarkedAttrs {
|
|||
}
|
||||
}
|
||||
|
||||
impl NestedMetaItem {
|
||||
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
|
||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||
match self {
|
||||
NestedMetaItem::MetaItem(item) => Some(item),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s.
|
||||
pub fn lit(&self) -> Option<&MetaItemLit> {
|
||||
match self {
|
||||
NestedMetaItem::Lit(lit) => Some(lit),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this list item is a MetaItem with a name of `name`.
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
|
||||
}
|
||||
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.ident())
|
||||
}
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
/// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
|
||||
/// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.value_str())
|
||||
}
|
||||
|
||||
/// Returns a name and single literal value tuple of the `MetaItem`.
|
||||
pub fn name_value_literal(&self) -> Option<(Symbol, &MetaItemLit)> {
|
||||
self.meta_item().and_then(|meta_item| {
|
||||
meta_item.meta_item_list().and_then(|meta_item_list| {
|
||||
if meta_item_list.len() == 1
|
||||
&& let Some(ident) = meta_item.ident()
|
||||
&& let Some(lit) = meta_item_list[0].lit()
|
||||
{
|
||||
return Some((ident.name, lit));
|
||||
}
|
||||
None
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets a list of inner meta items from a list `MetaItem` type.
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
|
||||
}
|
||||
|
||||
/// Returns `true` if the variant is `MetaItem`.
|
||||
pub fn is_meta_item(&self) -> bool {
|
||||
self.meta_item().is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
|
||||
pub fn is_word(&self) -> bool {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.is_word())
|
||||
}
|
||||
|
||||
/// See [`MetaItem::name_value_literal_span`].
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
self.meta_item()?.name_value_literal_span()
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
#[inline]
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.path == name,
|
||||
AttrKind::DocComment(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
Some(ident.ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.value_str(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta_item_list(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
if let AttrKind::Normal(normal) = &self.kind {
|
||||
matches!(normal.item.args, AttrArgs::Empty)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MetaItem {
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
|
||||
}
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
/// ```text
|
||||
/// Example:
|
||||
/// #[attribute(name = "value")]
|
||||
/// ^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn name_value_literal(&self) -> Option<&MetaItemLit> {
|
||||
match &self.kind {
|
||||
MetaItemKind::NameValue(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
self.kind.value_str()
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
match &self.kind {
|
||||
MetaItemKind::List(l) => Some(&**l),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
matches!(self.kind, MetaItemKind::Word)
|
||||
}
|
||||
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
self.path == name
|
||||
}
|
||||
|
||||
/// This is used in case you want the value span instead of the whole attribute. Example:
|
||||
///
|
||||
/// ```text
|
||||
/// #[doc(alias = "foo")]
|
||||
/// ```
|
||||
///
|
||||
/// In here, it'll return a span for `"foo"`.
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
Some(self.name_value_literal()?.span)
|
||||
}
|
||||
}
|
||||
|
||||
impl AttrArgsEq {
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match self {
|
||||
AttrArgsEq::Ast(expr) => match expr.kind {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrArgsEq::Hir(lit) => lit.kind.str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AttrItem {
|
||||
pub fn span(&self) -> Span {
|
||||
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
|
||||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
MetaItemKind::from_attr_args(&self.args)
|
||||
}
|
||||
|
||||
fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
|
||||
match &self.args {
|
||||
AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
|
||||
MetaItemKind::list_from_tokens(args.tokens.clone())
|
||||
}
|
||||
AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.args {
|
||||
AttrArgs::Eq(_, args) => args.value_str(),
|
||||
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
match self.kind {
|
||||
AttrKind::Normal(..) => false,
|
||||
AttrKind::DocComment(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
|
||||
normal.item.value_str().map(|s| (s, CommentKind::Line))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some("doc")`.
|
||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(.., data) => Some(*data),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn may_have_doc_links(&self) -> bool {
|
||||
self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
|
||||
}
|
||||
|
||||
pub fn get_normal_item(&self) -> &AttrItem {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => &normal.item,
|
||||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_normal_item(self) -> AttrItem {
|
||||
match self.kind {
|
||||
AttrKind::Normal(normal) => normal.into_inner().item,
|
||||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the MetaItem from inside this Attribute.
|
||||
pub fn meta(&self) -> Option<MetaItem> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta(self.span),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta_kind(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokens(&self) -> TokenStream {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream(),
|
||||
&AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
|
||||
Token::new(token::DocComment(comment_kind, self.style, data), self.span),
|
||||
Spacing::Alone,
|
||||
)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -381,93 +77,236 @@ impl AttrIdGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
path: Path,
|
||||
args: AttrArgs,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||
}
|
||||
impl Attribute {
|
||||
pub fn get_normal_item(&self) -> &AttrItem {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => &normal.item,
|
||||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(
|
||||
g: &AttrIdGenerator,
|
||||
item: AttrItem,
|
||||
tokens: Option<LazyAttrTokenStream>,
|
||||
style: AttrStyle,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
|
||||
id: g.mk_attr_id(),
|
||||
style,
|
||||
span,
|
||||
pub fn unwrap_normal_item(self) -> AttrItem {
|
||||
match self.kind {
|
||||
AttrKind::Normal(normal) => normal.into_inner().item,
|
||||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
match self.kind {
|
||||
AttrKind::Normal(..) => false,
|
||||
AttrKind::DocComment(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
Some(ident.ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.path == name,
|
||||
AttrKind::DocComment(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
if let AttrKind::Normal(normal) = &self.kind {
|
||||
matches!(normal.item.args, AttrArgs::Empty)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta_item_list(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.value_str(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
|
||||
normal.item.value_str().map(|s| (s, CommentKind::Line))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some("doc")`.
|
||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(.., data) => Some(*data),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn may_have_doc_links(&self) -> bool {
|
||||
self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
|
||||
}
|
||||
|
||||
/// Extracts the MetaItem from inside this Attribute.
|
||||
pub fn meta(&self) -> Option<MetaItem> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta(self.span),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta_kind(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokens(&self) -> TokenStream {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream(),
|
||||
&AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
|
||||
Token::new(token::DocComment(comment_kind, self.style, data), self.span),
|
||||
Spacing::Alone,
|
||||
)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Empty;
|
||||
mk_attr(g, style, path, args, span)
|
||||
impl AttrItem {
|
||||
pub fn span(&self) -> Span {
|
||||
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
|
||||
}
|
||||
|
||||
fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
|
||||
match &self.args {
|
||||
AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
|
||||
MetaItemKind::list_from_tokens(args.tokens.clone())
|
||||
}
|
||||
AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.args {
|
||||
AttrArgs::Eq(_, args) => args.value_str(),
|
||||
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
MetaItemKind::from_attr_args(&self.args)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_name_value_str(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
name: Symbol,
|
||||
val: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
|
||||
let expr = P(Expr {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: ExprKind::Lit(lit),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||
mk_attr(g, style, path, args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_nested_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
outer: Symbol,
|
||||
inner: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let inner_tokens = TokenStream::new(vec![TokenTree::Token(
|
||||
Token::from_ast_ident(Ident::new(inner, span)),
|
||||
Spacing::Alone,
|
||||
)]);
|
||||
let outer_ident = Ident::new(outer, span);
|
||||
let path = Path::from_ident(outer_ident);
|
||||
let attr_args = AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(span),
|
||||
delim: MacDelimiter::Parenthesis,
|
||||
tokens: inner_tokens,
|
||||
});
|
||||
mk_attr(g, style, path, attr_args, span)
|
||||
}
|
||||
|
||||
pub fn mk_doc_comment(
|
||||
g: &AttrIdGenerator,
|
||||
comment_kind: CommentKind,
|
||||
style: AttrStyle,
|
||||
data: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
|
||||
}
|
||||
|
||||
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
||||
items.iter().any(|item| item.has_name(name))
|
||||
impl AttrArgsEq {
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match self {
|
||||
AttrArgsEq::Ast(expr) => match expr.kind {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrArgsEq::Hir(lit) => lit.kind.str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MetaItem {
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
|
||||
}
|
||||
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
self.path == name
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
matches!(self.kind, MetaItemKind::Word)
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
match &self.kind {
|
||||
MetaItemKind::List(l) => Some(&**l),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// ```text
|
||||
/// Example:
|
||||
/// #[attribute(name = "value")]
|
||||
/// ^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn name_value_literal(&self) -> Option<&MetaItemLit> {
|
||||
match &self.kind {
|
||||
MetaItemKind::NameValue(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// This is used in case you want the value span instead of the whole attribute. Example:
|
||||
///
|
||||
/// ```text
|
||||
/// #[doc(alias = "foo")]
|
||||
/// ```
|
||||
///
|
||||
/// In here, it'll return a span for `"foo"`.
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
Some(self.name_value_literal()?.span)
|
||||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
self.kind.value_str()
|
||||
}
|
||||
|
||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
|
||||
where
|
||||
I: Iterator<Item = TokenTree>,
|
||||
|
@ -564,6 +403,24 @@ impl MetaItemKind {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_tokens(
|
||||
tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
|
||||
) -> Option<MetaItemKind> {
|
||||
match tokens.peek() {
|
||||
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
|
||||
let inner_tokens = inner_tokens.clone();
|
||||
tokens.next();
|
||||
MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
|
||||
}
|
||||
Some(TokenTree::Delimited(..)) => None,
|
||||
Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
|
||||
tokens.next();
|
||||
MetaItemKind::name_value_from_tokens(tokens)
|
||||
}
|
||||
_ => Some(MetaItemKind::Word),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_attr_args(args: &AttrArgs) -> Option<MetaItemKind> {
|
||||
match args {
|
||||
AttrArgs::Empty => Some(MetaItemKind::Word),
|
||||
|
@ -585,24 +442,6 @@ impl MetaItemKind {
|
|||
AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_tokens(
|
||||
tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
|
||||
) -> Option<MetaItemKind> {
|
||||
match tokens.peek() {
|
||||
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
|
||||
let inner_tokens = inner_tokens.clone();
|
||||
tokens.next();
|
||||
MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
|
||||
}
|
||||
Some(TokenTree::Delimited(..)) => None,
|
||||
Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
|
||||
tokens.next();
|
||||
MetaItemKind::name_value_from_tokens(tokens)
|
||||
}
|
||||
_ => Some(MetaItemKind::Word),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NestedMetaItem {
|
||||
|
@ -613,6 +452,77 @@ impl NestedMetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.ident())
|
||||
}
|
||||
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
/// Returns `true` if this list item is a MetaItem with a name of `name`.
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
|
||||
pub fn is_word(&self) -> bool {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.is_word())
|
||||
}
|
||||
|
||||
/// Gets a list of inner meta items from a list `MetaItem` type.
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
|
||||
}
|
||||
|
||||
/// Returns a name and single literal value tuple of the `MetaItem`.
|
||||
pub fn name_value_literal(&self) -> Option<(Symbol, &MetaItemLit)> {
|
||||
self.meta_item().and_then(|meta_item| {
|
||||
meta_item.meta_item_list().and_then(|meta_item_list| {
|
||||
if meta_item_list.len() == 1
|
||||
&& let Some(ident) = meta_item.ident()
|
||||
&& let Some(lit) = meta_item_list[0].lit()
|
||||
{
|
||||
return Some((ident.name, lit));
|
||||
}
|
||||
None
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// See [`MetaItem::name_value_literal_span`].
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
self.meta_item()?.name_value_literal_span()
|
||||
}
|
||||
|
||||
/// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
|
||||
/// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.value_str())
|
||||
}
|
||||
|
||||
/// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s.
|
||||
pub fn lit(&self) -> Option<&MetaItemLit> {
|
||||
match self {
|
||||
NestedMetaItem::Lit(lit) => Some(lit),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
|
||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||
match self {
|
||||
NestedMetaItem::MetaItem(item) => Some(item),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the variant is `MetaItem`.
|
||||
pub fn is_meta_item(&self) -> bool {
|
||||
self.meta_item().is_some()
|
||||
}
|
||||
|
||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
|
||||
where
|
||||
I: Iterator<Item = TokenTree>,
|
||||
|
@ -634,3 +544,89 @@ impl NestedMetaItem {
|
|||
MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_doc_comment(
|
||||
g: &AttrIdGenerator,
|
||||
comment_kind: CommentKind,
|
||||
style: AttrStyle,
|
||||
data: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
|
||||
}
|
||||
|
||||
pub fn mk_attr(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
path: Path,
|
||||
args: AttrArgs,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(
|
||||
g: &AttrIdGenerator,
|
||||
item: AttrItem,
|
||||
tokens: Option<LazyAttrTokenStream>,
|
||||
style: AttrStyle,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
|
||||
id: g.mk_attr_id(),
|
||||
style,
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Empty;
|
||||
mk_attr(g, style, path, args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_nested_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
outer: Symbol,
|
||||
inner: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let inner_tokens = TokenStream::new(vec![TokenTree::Token(
|
||||
Token::from_ast_ident(Ident::new(inner, span)),
|
||||
Spacing::Alone,
|
||||
)]);
|
||||
let outer_ident = Ident::new(outer, span);
|
||||
let path = Path::from_ident(outer_ident);
|
||||
let attr_args = AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(span),
|
||||
delim: MacDelimiter::Parenthesis,
|
||||
tokens: inner_tokens,
|
||||
});
|
||||
mk_attr(g, style, path, attr_args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_name_value_str(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
name: Symbol,
|
||||
val: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
|
||||
let expr = P(Expr {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: ExprKind::Lit(lit),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||
mk_attr(g, style, path, args, span)
|
||||
}
|
||||
|
||||
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
||||
items.iter().any(|item| item.has_name(name))
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
|
|||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::SeqCst;
|
||||
use rustc_errors::registry::{InvalidErrorCode, Registry};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult, TerminalUrl};
|
||||
use rustc_feature::find_gated_cfg;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
|
||||
|
@ -1191,6 +1191,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
));
|
||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use crate::translation::{to_fluent_args, Translate};
|
|||
use crate::{
|
||||
diagnostic::DiagnosticLocation, CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage,
|
||||
FluentBundle, Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
|
||||
SubstitutionHighlight, SuggestionStyle,
|
||||
SubstitutionHighlight, SuggestionStyle, TerminalUrl,
|
||||
};
|
||||
use rustc_lint_defs::pluralize;
|
||||
|
||||
|
@ -66,6 +66,7 @@ impl HumanReadableErrorType {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> EmitterWriter {
|
||||
let (short, color_config) = self.unzip();
|
||||
let color = color_config.suggests_using_colors();
|
||||
|
@ -80,6 +81,7 @@ impl HumanReadableErrorType {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -652,6 +654,7 @@ pub struct EmitterWriter {
|
|||
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -672,6 +675,7 @@ impl EmitterWriter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> EmitterWriter {
|
||||
let dst = Destination::from_stderr(color_config);
|
||||
EmitterWriter {
|
||||
|
@ -685,6 +689,7 @@ impl EmitterWriter {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -699,6 +704,7 @@ impl EmitterWriter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> EmitterWriter {
|
||||
EmitterWriter {
|
||||
dst: Raw(dst, colored),
|
||||
|
@ -711,6 +717,7 @@ impl EmitterWriter {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1378,7 +1385,13 @@ impl EmitterWriter {
|
|||
// only render error codes, not lint codes
|
||||
if let Some(DiagnosticId::Error(ref code)) = *code {
|
||||
buffer.append(0, "[", Style::Level(*level));
|
||||
buffer.append(0, code, Style::Level(*level));
|
||||
let code = if let TerminalUrl::Yes = self.terminal_url {
|
||||
let path = "https://doc.rust-lang.org/error_codes";
|
||||
format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
|
||||
} else {
|
||||
code.clone()
|
||||
};
|
||||
buffer.append(0, &code, Style::Level(*level));
|
||||
buffer.append(0, "]", Style::Level(*level));
|
||||
label_width += 2 + code.len();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::translation::{to_fluent_args, Translate};
|
|||
use crate::DiagnosticId;
|
||||
use crate::{
|
||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
|
||||
TerminalUrl,
|
||||
};
|
||||
use rustc_lint_defs::Applicability;
|
||||
|
||||
|
@ -47,6 +48,7 @@ pub struct JsonEmitter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
}
|
||||
|
||||
impl JsonEmitter {
|
||||
|
@ -60,6 +62,7 @@ impl JsonEmitter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
JsonEmitter {
|
||||
dst: Box::new(io::BufWriter::new(io::stderr())),
|
||||
|
@ -73,6 +76,7 @@ impl JsonEmitter {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +88,7 @@ impl JsonEmitter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
let file_path_mapping = FilePathMapping::empty();
|
||||
JsonEmitter::stderr(
|
||||
|
@ -96,6 +101,7 @@ impl JsonEmitter {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -110,6 +116,7 @@ impl JsonEmitter {
|
|||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
JsonEmitter {
|
||||
dst,
|
||||
|
@ -123,6 +130,7 @@ impl JsonEmitter {
|
|||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,6 +368,7 @@ impl Diagnostic {
|
|||
je.diagnostic_width,
|
||||
je.macro_backtrace,
|
||||
je.track_diagnostics,
|
||||
je.terminal_url,
|
||||
)
|
||||
.ui_testing(je.ui_testing)
|
||||
.emit_diagnostic(diag);
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::json::JsonEmitter;
|
|||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
|
||||
use crate::emitter::{ColorConfig, HumanReadableErrorType};
|
||||
use crate::Handler;
|
||||
use crate::{Handler, TerminalUrl};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use std::str;
|
||||
|
@ -60,6 +60,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
|
||||
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
||||
|
|
|
@ -573,6 +573,7 @@ impl Handler {
|
|||
None,
|
||||
flags.macro_backtrace,
|
||||
flags.track_diagnostics,
|
||||
TerminalUrl::No,
|
||||
));
|
||||
Self::with_emitter_and_flags(emitter, flags)
|
||||
}
|
||||
|
@ -1838,6 +1839,13 @@ pub fn add_elided_lifetime_in_path_suggestion(
|
|||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum TerminalUrl {
|
||||
No,
|
||||
Yes,
|
||||
Auto,
|
||||
}
|
||||
|
||||
/// Useful type to use with `Result<>` indicate that an error has already
|
||||
/// been reported to the user, so no need to continue checking.
|
||||
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_span::{BytePos, Span};
|
|||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::{Handler, MultiSpan, PResult};
|
||||
use rustc_errors::{Handler, MultiSpan, PResult, TerminalUrl};
|
||||
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
@ -152,6 +152,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::early_error;
|
|||
use crate::lint;
|
||||
use crate::search_paths::SearchPath;
|
||||
use crate::utils::NativeLib;
|
||||
use rustc_errors::LanguageIdentifier;
|
||||
use rustc_errors::{LanguageIdentifier, TerminalUrl};
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
|
||||
use rustc_target::spec::{
|
||||
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
|
||||
|
@ -402,6 +402,8 @@ mod desc {
|
|||
pub const parse_code_model: &str = "one of supported code models (`rustc --print code-models`)";
|
||||
pub const parse_tls_model: &str = "one of supported TLS models (`rustc --print tls-models`)";
|
||||
pub const parse_target_feature: &str = parse_string;
|
||||
pub const parse_terminal_url: &str =
|
||||
"either a boolean (`yes`, `no`, `on`, `off`, etc), or `auto`";
|
||||
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
|
||||
pub const parse_split_debuginfo: &str =
|
||||
"one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
|
||||
|
@ -1044,6 +1046,16 @@ mod parse {
|
|||
true
|
||||
}
|
||||
|
||||
pub(crate) fn parse_terminal_url(slot: &mut TerminalUrl, v: Option<&str>) -> bool {
|
||||
*slot = match v {
|
||||
Some("on" | "" | "yes" | "y") | None => TerminalUrl::Yes,
|
||||
Some("off" | "no" | "n") => TerminalUrl::No,
|
||||
Some("auto") => TerminalUrl::Auto,
|
||||
_ => return false,
|
||||
};
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn parse_symbol_mangling_version(
|
||||
slot: &mut Option<SymbolManglingVersion>,
|
||||
v: Option<&str>,
|
||||
|
@ -1675,6 +1687,8 @@ options! {
|
|||
"show extended diagnostic help (default: no)"),
|
||||
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
"the directory the intermediate files are written to"),
|
||||
terminal_urls: TerminalUrl = (TerminalUrl::No, parse_terminal_url, [UNTRACKED],
|
||||
"use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output"),
|
||||
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
|
||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable ThinLTO when possible"),
|
||||
|
|
|
@ -24,6 +24,7 @@ use rustc_errors::registry::Registry;
|
|||
use rustc_errors::{
|
||||
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||
ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted,
|
||||
TerminalUrl,
|
||||
};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::def_id::StableCrateId;
|
||||
|
@ -1273,6 +1274,19 @@ fn default_emitter(
|
|||
) -> Box<dyn Emitter + sync::Send> {
|
||||
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
|
||||
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
|
||||
let terminal_url = match sopts.unstable_opts.terminal_urls {
|
||||
TerminalUrl::Auto => {
|
||||
match (std::env::var("COLORTERM").as_deref(), std::env::var("TERM").as_deref()) {
|
||||
(Ok("truecolor"), Ok("xterm-256color"))
|
||||
if sopts.unstable_features.is_nightly_build() =>
|
||||
{
|
||||
TerminalUrl::Yes
|
||||
}
|
||||
_ => TerminalUrl::No,
|
||||
}
|
||||
}
|
||||
t => t,
|
||||
};
|
||||
match sopts.error_format {
|
||||
config::ErrorOutputType::HumanReadable(kind) => {
|
||||
let (short, color_config) = kind.unzip();
|
||||
|
@ -1297,6 +1311,7 @@ fn default_emitter(
|
|||
sopts.diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
);
|
||||
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
|
||||
}
|
||||
|
@ -1312,6 +1327,7 @@ fn default_emitter(
|
|||
sopts.diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
)
|
||||
.ui_testing(sopts.unstable_opts.ui_testing),
|
||||
),
|
||||
|
@ -1628,6 +1644,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
))
|
||||
}
|
||||
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
|
||||
|
@ -1638,6 +1655,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
)),
|
||||
};
|
||||
rustc_errors::Handler::with_emitter(true, None, emitter)
|
||||
|
|
|
@ -110,11 +110,16 @@ impl Span {
|
|||
// Inline format with parent.
|
||||
let len_or_tag = len_or_tag | PARENT_MASK;
|
||||
let parent2 = parent.local_def_index.as_u32();
|
||||
if ctxt2 == SyntaxContext::root().as_u32() && parent2 <= MAX_CTXT {
|
||||
if ctxt2 == SyntaxContext::root().as_u32()
|
||||
&& parent2 <= MAX_CTXT
|
||||
&& len_or_tag < LEN_TAG
|
||||
{
|
||||
debug_assert_ne!(len_or_tag, LEN_TAG);
|
||||
return Span { base_or_index: base, len_or_tag, ctxt_or_tag: parent2 as u16 };
|
||||
}
|
||||
} else {
|
||||
// Inline format with ctxt.
|
||||
debug_assert_ne!(len_or_tag, LEN_TAG);
|
||||
return Span {
|
||||
base_or_index: base,
|
||||
len_or_tag: len as u16,
|
||||
|
|
|
@ -470,14 +470,11 @@ fn layout_of_uncached<'tcx>(
|
|||
return Err(LayoutError::Unknown(ty));
|
||||
}
|
||||
|
||||
ty::Placeholder(..)
|
||||
| ty::GeneratorWitness(..)
|
||||
| ty::GeneratorWitnessMIR(..)
|
||||
| ty::Infer(_) => {
|
||||
ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
|
||||
bug!("Layout::compute: unexpected type `{}`", ty)
|
||||
}
|
||||
|
||||
ty::Bound(..) | ty::Param(_) | ty::Error(_) => {
|
||||
ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
}
|
||||
})
|
||||
|
|
|
@ -211,7 +211,8 @@ Duration = float
|
|||
TimerSection = Union[Duration, "Timer"]
|
||||
|
||||
|
||||
def iterate_sections(section: TimerSection, name: str, level: int = 0) -> Iterator[Tuple[int, str, Duration]]:
|
||||
def iterate_sections(section: TimerSection, name: str, level: int = 0) -> Iterator[
|
||||
Tuple[int, str, Duration]]:
|
||||
"""
|
||||
Hierarchically iterate the sections of a timer, in a depth-first order.
|
||||
"""
|
||||
|
@ -239,7 +240,7 @@ class Timer:
|
|||
start = get_timestamp()
|
||||
exc = None
|
||||
|
||||
child_timer = Timer(parent_names=self.parent_names + (name, ))
|
||||
child_timer = Timer(parent_names=self.parent_names + (name,))
|
||||
full_name = " > ".join(child_timer.parent_names)
|
||||
try:
|
||||
LOGGER.info(f"Section `{full_name}` starts")
|
||||
|
@ -648,6 +649,16 @@ def print_binary_sizes(pipeline: Pipeline):
|
|||
LOGGER.info(f"Rustc binary size\n{output.getvalue()}")
|
||||
|
||||
|
||||
def print_free_disk_space(pipeline: Pipeline):
|
||||
usage = shutil.disk_usage(pipeline.opt_artifacts())
|
||||
total = usage.total
|
||||
used = usage.used
|
||||
free = usage.free
|
||||
|
||||
logging.info(
|
||||
f"Free disk space: {format_bytes(free)} out of total {format_bytes(total)} ({(used / total) * 100:.2f}% used)")
|
||||
|
||||
|
||||
def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
|
||||
# Clear and prepare tmp directory
|
||||
shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
|
||||
|
@ -666,6 +677,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
|
|||
|
||||
with stage1.section("Gather profiles"):
|
||||
gather_llvm_profiles(pipeline)
|
||||
print_free_disk_space(pipeline)
|
||||
|
||||
clear_llvm_files(pipeline)
|
||||
final_build_args += [
|
||||
|
@ -683,6 +695,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
|
|||
|
||||
with stage2.section("Gather profiles"):
|
||||
gather_rustc_profiles(pipeline)
|
||||
print_free_disk_space(pipeline)
|
||||
|
||||
clear_llvm_files(pipeline)
|
||||
final_build_args += [
|
||||
|
@ -702,6 +715,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
|
|||
with stage3.section("Gather profiles"):
|
||||
gather_llvm_bolt_profiles(pipeline)
|
||||
|
||||
print_free_disk_space(pipeline)
|
||||
clear_llvm_files(pipeline)
|
||||
final_build_args += [
|
||||
"--llvm-bolt-profile-use",
|
||||
|
@ -733,5 +747,6 @@ if __name__ == "__main__":
|
|||
raise e
|
||||
finally:
|
||||
timer.print_stats()
|
||||
print_free_disk_space(pipeline)
|
||||
|
||||
print_binary_sizes(pipeline)
|
||||
|
|
|
@ -4,6 +4,7 @@ use rustc_data_structures::sync::{self, Lrc};
|
|||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||
use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::TerminalUrl;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
|
||||
|
@ -144,6 +145,7 @@ pub(crate) fn new_handler(
|
|||
diagnostic_width,
|
||||
false,
|
||||
unstable_opts.track_diagnostics,
|
||||
TerminalUrl::No,
|
||||
)
|
||||
.ui_testing(unstable_opts.ui_testing),
|
||||
)
|
||||
|
@ -163,6 +165,7 @@ pub(crate) fn new_handler(
|
|||
diagnostic_width,
|
||||
false,
|
||||
unstable_opts.track_diagnostics,
|
||||
TerminalUrl::No,
|
||||
)
|
||||
.ui_testing(unstable_opts.ui_testing),
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError};
|
||||
use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError, TerminalUrl};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
|
||||
use rustc_interface::interface;
|
||||
|
@ -557,6 +557,7 @@ pub(crate) fn make_test(
|
|||
Some(80),
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
)
|
||||
.supports_color();
|
||||
|
||||
|
@ -571,6 +572,7 @@ pub(crate) fn make_test(
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
|
||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||
|
@ -756,6 +758,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
|
||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
||||
|
|
|
@ -96,13 +96,19 @@ fn write_header(out: &mut Buffer, class: &str, extra_content: Option<Buffer>, to
|
|||
);
|
||||
|
||||
if tooltip != Tooltip::None {
|
||||
let edition_code;
|
||||
write!(
|
||||
out,
|
||||
"<div class='tooltip'{}>ⓘ</div>",
|
||||
if let Tooltip::Edition(edition_info) = tooltip {
|
||||
format!(" data-edition=\"{}\"", edition_info)
|
||||
} else {
|
||||
String::new()
|
||||
"<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
|
||||
match tooltip {
|
||||
Tooltip::Ignore => "This example is not tested",
|
||||
Tooltip::CompileFail => "This example deliberately fails to compile",
|
||||
Tooltip::ShouldPanic => "This example panics",
|
||||
Tooltip::Edition(edition) => {
|
||||
edition_code = format!("This example runs with edition {edition}");
|
||||
&edition_code
|
||||
}
|
||||
Tooltip::None => unreachable!(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1310,7 +1310,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
|
|||
if has_notable_trait {
|
||||
cx.types_with_notable_traits.insert(ty.clone());
|
||||
Some(format!(
|
||||
" <a href=\"#\" class=\"notable-traits\" data-ty=\"{ty}\">ⓘ</a>",
|
||||
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
|
||||
ty = Escape(&format!("{:#}", ty.print(cx))),
|
||||
))
|
||||
} else {
|
||||
|
|
|
@ -715,8 +715,8 @@ h2.small-section-header > .anchor {
|
|||
.main-heading a:hover,
|
||||
.example-wrap > pre.rust a:hover,
|
||||
.all-items a:hover,
|
||||
.docblock a:not(.test-arrow):not(.scrape-help):hover,
|
||||
.docblock-short a:not(.test-arrow):not(.scrape-help):hover,
|
||||
.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
|
||||
.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
|
||||
.item-info a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
@ -1109,44 +1109,8 @@ pre.rust .doccomment {
|
|||
display: block;
|
||||
left: -25px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.example-wrap .tooltip:hover::after {
|
||||
padding: 5px 3px 3px 3px;
|
||||
border-radius: 6px;
|
||||
margin-left: 5px;
|
||||
font-size: 1rem;
|
||||
border: 1px solid var(--border-color);
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
top: -2px;
|
||||
z-index: 1;
|
||||
background-color: var(--tooltip-background-color);
|
||||
color: var(--tooltip-color);
|
||||
}
|
||||
|
||||
.example-wrap .tooltip:hover::before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
margin-top: -5px;
|
||||
z-index: 1;
|
||||
border: 5px solid transparent;
|
||||
border-right-color: var(--tooltip-background-color);
|
||||
}
|
||||
|
||||
.example-wrap.ignore .tooltip:hover::after {
|
||||
content: "This example is not tested";
|
||||
}
|
||||
.example-wrap.compile_fail .tooltip:hover::after {
|
||||
content: "This example deliberately fails to compile";
|
||||
}
|
||||
.example-wrap.should_panic .tooltip:hover::after {
|
||||
content: "This example panics";
|
||||
}
|
||||
.example-wrap.edition .tooltip:hover::after {
|
||||
content: "This code runs with edition " attr(data-edition);
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.example-wrap.compile_fail .tooltip,
|
||||
|
@ -1213,7 +1177,7 @@ a.test-arrow:hover {
|
|||
border-right: 3px solid var(--target-border-color);
|
||||
}
|
||||
|
||||
.notable-traits {
|
||||
.code-header a.tooltip {
|
||||
color: inherit;
|
||||
margin-right: 15px;
|
||||
position: relative;
|
||||
|
@ -1222,7 +1186,7 @@ a.test-arrow:hover {
|
|||
/* placeholder thunk so that the mouse can easily travel from "(i)" to popover
|
||||
the resulting "hover tunnel" is a stepped triangle, approximating
|
||||
https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown */
|
||||
.notable-traits:hover::after {
|
||||
a.tooltip:hover::after {
|
||||
position: absolute;
|
||||
top: calc(100% - 10px);
|
||||
left: -15px;
|
||||
|
@ -1231,11 +1195,11 @@ a.test-arrow:hover {
|
|||
content: "\00a0";
|
||||
}
|
||||
|
||||
.notable .content {
|
||||
.popover.tooltip .content {
|
||||
margin: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
.notable .content pre, .notable .content code {
|
||||
.popover.tooltip .content pre, .popover.tooltip .content code {
|
||||
background: transparent;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -1243,7 +1207,7 @@ a.test-arrow:hover {
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.notable .content > h3:first-child {
|
||||
.popover.tooltip .content > h3:first-child {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
|||
--test-arrow-hover-background-color: rgba(57, 175, 215, 0.368);
|
||||
--target-background-color: rgba(255, 236, 164, 0.06);
|
||||
--target-border-color: rgba(255, 180, 76, 0.85);
|
||||
--tooltip-background-color: #314559;
|
||||
--tooltip-color: #c5c5c5;
|
||||
--kbd-color: #c5c5c5;
|
||||
--kbd-background: #314559;
|
||||
--kbd-box-shadow-color: #5c6773;
|
||||
|
|
|
@ -69,8 +69,6 @@
|
|||
--test-arrow-hover-background-color: #4e8bca;
|
||||
--target-background-color: #494a3d;
|
||||
--target-border-color: #bb7410;
|
||||
--tooltip-background-color: #000;
|
||||
--tooltip-color: #fff;
|
||||
--kbd-color: #000;
|
||||
--kbd-background: #fafbfc;
|
||||
--kbd-box-shadow-color: #c6cbd1;
|
||||
|
|
|
@ -69,8 +69,6 @@
|
|||
--test-arrow-hover-background-color: #4e8bca;
|
||||
--target-background-color: #fdffd3;
|
||||
--target-border-color: #ad7c37;
|
||||
--tooltip-background-color: #000;
|
||||
--tooltip-color: #fff;
|
||||
--kbd-color: #000;
|
||||
--kbd-background: #fafbfc;
|
||||
--kbd-box-shadow-color: #c6cbd1;
|
||||
|
|
|
@ -378,7 +378,7 @@ function loadCss(cssUrl) {
|
|||
}
|
||||
ev.preventDefault();
|
||||
searchState.defocus();
|
||||
window.hideAllModals(true); // true = reset focus for notable traits
|
||||
window.hideAllModals(true); // true = reset focus for tooltips
|
||||
}
|
||||
|
||||
function handleShortcut(ev) {
|
||||
|
@ -784,17 +784,17 @@ function loadCss(cssUrl) {
|
|||
// we need to switch away from mobile mode and make the main content area scrollable.
|
||||
hideSidebar();
|
||||
}
|
||||
if (window.CURRENT_NOTABLE_ELEMENT) {
|
||||
// As a workaround to the behavior of `contains: layout` used in doc togglers, the
|
||||
// notable traits popup is positioned using javascript.
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT) {
|
||||
// As a workaround to the behavior of `contains: layout` used in doc togglers,
|
||||
// tooltip popovers are positioned using javascript.
|
||||
//
|
||||
// This means when the window is resized, we need to redo the layout.
|
||||
const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE;
|
||||
const force_visible = base.NOTABLE_FORCE_VISIBLE;
|
||||
hideNotable(false);
|
||||
const base = window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;
|
||||
const force_visible = base.TOOLTIP_FORCE_VISIBLE;
|
||||
hideTooltip(false);
|
||||
if (force_visible) {
|
||||
showNotable(base);
|
||||
base.NOTABLE_FORCE_VISIBLE = true;
|
||||
showTooltip(base);
|
||||
base.TOOLTIP_FORCE_VISIBLE = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -822,27 +822,35 @@ function loadCss(cssUrl) {
|
|||
});
|
||||
});
|
||||
|
||||
function showNotable(e) {
|
||||
if (!window.NOTABLE_TRAITS) {
|
||||
function showTooltip(e) {
|
||||
const notable_ty = e.getAttribute("data-notable-ty");
|
||||
if (!window.NOTABLE_TRAITS && notable_ty) {
|
||||
const data = document.getElementById("notable-traits-data");
|
||||
if (data) {
|
||||
window.NOTABLE_TRAITS = JSON.parse(data.innerText);
|
||||
} else {
|
||||
throw new Error("showNotable() called on page without any notable traits!");
|
||||
throw new Error("showTooltip() called with notable without any notable traits!");
|
||||
}
|
||||
}
|
||||
if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) {
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT && window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE === e) {
|
||||
// Make this function idempotent.
|
||||
return;
|
||||
}
|
||||
window.hideAllModals(false);
|
||||
const ty = e.getAttribute("data-ty");
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.innerHTML = "<div class=\"content\">" + window.NOTABLE_TRAITS[ty] + "</div>";
|
||||
wrapper.className = "notable popover";
|
||||
if (notable_ty) {
|
||||
wrapper.innerHTML = "<div class=\"content\">" +
|
||||
window.NOTABLE_TRAITS[notable_ty] + "</div>";
|
||||
} else if (e.getAttribute("title") !== undefined) {
|
||||
const titleContent = document.createElement("div");
|
||||
titleContent.className = "content";
|
||||
titleContent.appendChild(document.createTextNode(e.getAttribute("title")));
|
||||
wrapper.appendChild(titleContent);
|
||||
}
|
||||
wrapper.className = "tooltip popover";
|
||||
const focusCatcher = document.createElement("div");
|
||||
focusCatcher.setAttribute("tabindex", "0");
|
||||
focusCatcher.onfocus = hideNotable;
|
||||
focusCatcher.onfocus = hideTooltip;
|
||||
wrapper.appendChild(focusCatcher);
|
||||
const pos = e.getBoundingClientRect();
|
||||
// 5px overlap so that the mouse can easily travel from place to place
|
||||
|
@ -864,62 +872,62 @@ function loadCss(cssUrl) {
|
|||
);
|
||||
}
|
||||
wrapper.style.visibility = "";
|
||||
window.CURRENT_NOTABLE_ELEMENT = wrapper;
|
||||
window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e;
|
||||
window.CURRENT_TOOLTIP_ELEMENT = wrapper;
|
||||
window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE = e;
|
||||
wrapper.onpointerleave = function(ev) {
|
||||
// If this is a synthetic touch event, ignore it. A click event will be along shortly.
|
||||
if (ev.pointerType !== "mouse") {
|
||||
return;
|
||||
}
|
||||
if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
|
||||
hideNotable(true);
|
||||
if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
|
||||
hideTooltip(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function notableBlurHandler(event) {
|
||||
if (window.CURRENT_NOTABLE_ELEMENT &&
|
||||
!elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT) &&
|
||||
!elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT) &&
|
||||
!elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE) &&
|
||||
!elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE)
|
||||
function tooltipBlurHandler(event) {
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT &&
|
||||
!elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT) &&
|
||||
!elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT) &&
|
||||
!elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) &&
|
||||
!elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)
|
||||
) {
|
||||
// Work around a difference in the focus behaviour between Firefox, Chrome, and Safari.
|
||||
// When I click the button on an already-opened notable trait popover, Safari
|
||||
// When I click the button on an already-opened tooltip popover, Safari
|
||||
// hides the popover and then immediately shows it again, while everyone else hides it
|
||||
// and it stays hidden.
|
||||
//
|
||||
// To work around this, make sure the click finishes being dispatched before
|
||||
// hiding the popover. Since `hideNotable()` is idempotent, this makes Safari behave
|
||||
// hiding the popover. Since `hideTooltip()` is idempotent, this makes Safari behave
|
||||
// consistently with the other two.
|
||||
setTimeout(() => hideNotable(false), 0);
|
||||
setTimeout(() => hideTooltip(false), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function hideNotable(focus) {
|
||||
if (window.CURRENT_NOTABLE_ELEMENT) {
|
||||
if (window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE) {
|
||||
function hideTooltip(focus) {
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT) {
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE) {
|
||||
if (focus) {
|
||||
window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.focus();
|
||||
window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus();
|
||||
}
|
||||
window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false;
|
||||
window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false;
|
||||
}
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
body.removeChild(window.CURRENT_NOTABLE_ELEMENT);
|
||||
window.CURRENT_NOTABLE_ELEMENT = null;
|
||||
body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
|
||||
window.CURRENT_TOOLTIP_ELEMENT = null;
|
||||
}
|
||||
}
|
||||
|
||||
onEachLazy(document.getElementsByClassName("notable-traits"), e => {
|
||||
onEachLazy(document.getElementsByClassName("tooltip"), e => {
|
||||
e.onclick = function() {
|
||||
this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true;
|
||||
if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) {
|
||||
hideNotable(true);
|
||||
this.TOOLTIP_FORCE_VISIBLE = this.TOOLTIP_FORCE_VISIBLE ? false : true;
|
||||
if (window.CURRENT_TOOLTIP_ELEMENT && !this.TOOLTIP_FORCE_VISIBLE) {
|
||||
hideTooltip(true);
|
||||
} else {
|
||||
showNotable(this);
|
||||
window.CURRENT_NOTABLE_ELEMENT.setAttribute("tabindex", "0");
|
||||
window.CURRENT_NOTABLE_ELEMENT.focus();
|
||||
window.CURRENT_NOTABLE_ELEMENT.onblur = notableBlurHandler;
|
||||
showTooltip(this);
|
||||
window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex", "0");
|
||||
window.CURRENT_TOOLTIP_ELEMENT.focus();
|
||||
window.CURRENT_TOOLTIP_ELEMENT.onblur = tooltipBlurHandler;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -928,16 +936,16 @@ function loadCss(cssUrl) {
|
|||
if (ev.pointerType !== "mouse") {
|
||||
return;
|
||||
}
|
||||
showNotable(this);
|
||||
showTooltip(this);
|
||||
};
|
||||
e.onpointerleave = function(ev) {
|
||||
// If this is a synthetic touch event, ignore it. A click event will be along shortly.
|
||||
if (ev.pointerType !== "mouse") {
|
||||
return;
|
||||
}
|
||||
if (!this.NOTABLE_FORCE_VISIBLE &&
|
||||
!elemIsInParent(ev.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
|
||||
hideNotable(true);
|
||||
if (!this.TOOLTIP_FORCE_VISIBLE &&
|
||||
!elemIsInParent(ev.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT)) {
|
||||
hideTooltip(true);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1039,14 +1047,14 @@ function loadCss(cssUrl) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Hide popover menus, notable trait tooltips, and the sidebar (if applicable).
|
||||
* Hide popover menus, clickable tooltips, and the sidebar (if applicable).
|
||||
*
|
||||
* Pass "true" to reset focus for notable traits.
|
||||
* Pass "true" to reset focus for tooltip popovers.
|
||||
*/
|
||||
window.hideAllModals = function(switchFocus) {
|
||||
hideSidebar();
|
||||
window.hidePopoverMenus();
|
||||
hideNotable(switchFocus);
|
||||
hideTooltip(switchFocus);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_ast::token::CommentKind;
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::{Applicability, Handler, SuggestionStyle};
|
||||
use rustc_errors::{Applicability, Handler, SuggestionStyle, TerminalUrl};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{AnonConst, Expr};
|
||||
|
@ -717,6 +717,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
||||
let sess = ParseSess::with_span_handler(handler, sm);
|
||||
|
|
|
@ -220,6 +220,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
rustc_errors::TerminalUrl::No,
|
||||
));
|
||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use rustc_data_structures::sync::{Lrc, Send};
|
||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
|
||||
use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel, TerminalUrl};
|
||||
use rustc_session::parse::ParseSess as RawParseSess;
|
||||
use rustc_span::{
|
||||
source_map::{FilePathMapping, SourceMap},
|
||||
|
@ -135,6 +135,7 @@ fn default_handler(
|
|||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
))
|
||||
};
|
||||
Handler::with_emitter(
|
||||
|
|
|
@ -30,24 +30,16 @@ define-function: (
|
|||
".docblock .example-wrap.compile_fail",
|
||||
{"border-left": "2px solid rgb(255, 0, 0)"},
|
||||
)
|
||||
assert-css: (
|
||||
".docblock .example-wrap.compile_fail .tooltip::after",
|
||||
{
|
||||
"content": '"This example deliberately fails to compile"',
|
||||
"padding": "5px 3px 3px",
|
||||
"background-color": |background|,
|
||||
"color": |color|,
|
||||
"border": "1px solid " + |border|,
|
||||
},
|
||||
)
|
||||
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)",
|
||||
},
|
||||
click: ".docblock .example-wrap.compile_fail .tooltip"
|
||||
assert-text: (
|
||||
".popover.tooltip",
|
||||
"This example deliberately fails to compile"
|
||||
)
|
||||
assert-css: (".popover.tooltip", {
|
||||
"color": |color|,
|
||||
"background-color": |background|,
|
||||
"border-color": |border|,
|
||||
})
|
||||
|
||||
// should_panic block
|
||||
assert-css: (
|
||||
|
@ -69,24 +61,16 @@ define-function: (
|
|||
".docblock .example-wrap.should_panic",
|
||||
{"border-left": "2px solid rgb(255, 0, 0)"},
|
||||
)
|
||||
assert-css: (
|
||||
".docblock .example-wrap.should_panic .tooltip::after",
|
||||
{
|
||||
"content": '"This example panics"',
|
||||
"padding": "5px 3px 3px",
|
||||
"background-color": |background|,
|
||||
"color": |color|,
|
||||
"border": "1px solid " + |border|,
|
||||
},
|
||||
)
|
||||
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)",
|
||||
},
|
||||
click: ".docblock .example-wrap.should_panic .tooltip"
|
||||
assert-text: (
|
||||
".popover.tooltip",
|
||||
"This example panics"
|
||||
)
|
||||
assert-css: (".popover.tooltip", {
|
||||
"color": |color|,
|
||||
"background-color": |background|,
|
||||
"border-color": |border|,
|
||||
})
|
||||
|
||||
// ignore block
|
||||
assert-css: (
|
||||
|
@ -108,42 +92,36 @@ define-function: (
|
|||
".docblock .example-wrap.ignore",
|
||||
{"border-left": "2px solid rgb(255, 142, 0)"},
|
||||
)
|
||||
assert-css: (
|
||||
".docblock .example-wrap.ignore .tooltip::after",
|
||||
{
|
||||
"content": '"This example is not tested"',
|
||||
"padding": "5px 3px 3px",
|
||||
"background-color": |background|,
|
||||
"color": |color|,
|
||||
"border": "1px solid " + |border|,
|
||||
},
|
||||
)
|
||||
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)",
|
||||
},
|
||||
click: ".docblock .example-wrap.ignore .tooltip"
|
||||
assert-text: (
|
||||
".popover.tooltip",
|
||||
"This example is not tested"
|
||||
)
|
||||
assert-css: (".popover.tooltip", {
|
||||
"color": |color|,
|
||||
"background-color": |background|,
|
||||
"border-color": |border|,
|
||||
})
|
||||
click: ".docblock .example-wrap.ignore .tooltip"
|
||||
assert-false: ".popover.tooltip"
|
||||
},
|
||||
)
|
||||
|
||||
call-function: ("check-colors", {
|
||||
"theme": "ayu",
|
||||
"background": "rgb(49, 69, 89)",
|
||||
"background": "rgb(15, 20, 25)",
|
||||
"color": "rgb(197, 197, 197)",
|
||||
"border": "rgb(92, 103, 115)",
|
||||
})
|
||||
call-function: ("check-colors", {
|
||||
"theme": "dark",
|
||||
"background": "rgb(0, 0, 0)",
|
||||
"color": "rgb(255, 255, 255)",
|
||||
"background": "rgb(53, 53, 53)",
|
||||
"color": "rgb(221, 221, 221)",
|
||||
"border": "rgb(224, 224, 224)",
|
||||
})
|
||||
call-function: ("check-colors", {
|
||||
"theme": "light",
|
||||
"background": "rgb(0, 0, 0)",
|
||||
"color": "rgb(255, 255, 255)",
|
||||
"background": "rgb(255, 255, 255)",
|
||||
"color": "rgb(0, 0, 0)",
|
||||
"border": "rgb(224, 224, 224)",
|
||||
})
|
||||
|
|
|
@ -6,13 +6,13 @@ size: (1100, 600)
|
|||
// Checking they have the same y position.
|
||||
compare-elements-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("y"),
|
||||
)
|
||||
// Checking they don't have the same x position.
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("x"),
|
||||
)
|
||||
// The `i` should be *after* the type.
|
||||
|
@ -21,33 +21,33 @@ assert-position: (
|
|||
{"x": 677},
|
||||
)
|
||||
assert-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
{"x": 955},
|
||||
)
|
||||
// The tooltip should be below the `i`
|
||||
// Also, clicking the tooltip should bring its text into the DOM
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
compare-elements-position-near: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@class='notable popover']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
"//*[@class='tooltip popover']",
|
||||
{"y": 30}
|
||||
)
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@class='notable popover']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
"//*[@class='tooltip popover']",
|
||||
("x")
|
||||
)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
move-cursor-to: "//h1"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
|
||||
// Now only the `i` should be on the next line.
|
||||
size: (1055, 600)
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("y", "x"),
|
||||
)
|
||||
|
||||
|
@ -56,13 +56,13 @@ size: (980, 600)
|
|||
// Checking they have the same y position.
|
||||
compare-elements-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("y"),
|
||||
)
|
||||
// Checking they don't have the same x position.
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("x"),
|
||||
)
|
||||
// The `i` should be *after* the type.
|
||||
|
@ -71,7 +71,7 @@ assert-position: (
|
|||
{"x": 245},
|
||||
)
|
||||
assert-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
{"x": 523},
|
||||
)
|
||||
|
||||
|
@ -80,13 +80,13 @@ size: (650, 600)
|
|||
// Checking they have the same y position.
|
||||
compare-elements-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("y"),
|
||||
)
|
||||
// Checking they don't have the same x position.
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
("x"),
|
||||
)
|
||||
// The `i` should be *after* the type.
|
||||
|
@ -95,29 +95,29 @@ assert-position: (
|
|||
{"x": 15},
|
||||
)
|
||||
assert-position: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
{"x": 293},
|
||||
)
|
||||
// The tooltip should STILL be below `i`
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
compare-elements-position-near: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@class='notable popover']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
"//*[@class='tooltip popover']",
|
||||
{"y": 30}
|
||||
)
|
||||
compare-elements-position-false: (
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
|
||||
"//*[@class='notable popover']",
|
||||
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
|
||||
"//*[@class='tooltip popover']",
|
||||
("x")
|
||||
)
|
||||
assert-position: (
|
||||
"//*[@class='notable popover']",
|
||||
"//*[@class='tooltip popover']",
|
||||
{"x": 0}
|
||||
)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
move-cursor-to: "//h1"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
|
||||
// Now check the colors.
|
||||
define-function: (
|
||||
|
@ -133,26 +133,26 @@ define-function: (
|
|||
// We reload the page so the local storage settings are being used.
|
||||
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='tooltip']"
|
||||
assert-count: (".tooltip.popover", 1)
|
||||
|
||||
assert-css: (
|
||||
".notable.popover h3",
|
||||
".tooltip.popover h3",
|
||||
{"color": |header_color|},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
".notable.popover pre",
|
||||
".tooltip.popover pre",
|
||||
{"color": |content_color|},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
".notable.popover pre a.struct",
|
||||
".tooltip.popover pre a.struct",
|
||||
{"color": |type_color|},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
".notable.popover pre a.trait",
|
||||
".tooltip.popover pre a.trait",
|
||||
{"color": |trait_color|},
|
||||
ALL,
|
||||
)
|
||||
|
@ -195,24 +195,24 @@ call-function: (
|
|||
reload:
|
||||
|
||||
// Check that pressing escape works
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
move-cursor-to: "//*[@class='notable popover']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
move-cursor-to: "//*[@class='tooltip popover']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
press-key: "Escape"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
|
||||
// Check that clicking outside works.
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
click: ".search-input"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
|
||||
// Check that pressing tab over and over works.
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
move-cursor-to: "//*[@class='notable popover']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
move-cursor-to: "//*[@class='tooltip popover']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
press-key: "Tab"
|
||||
press-key: "Tab"
|
||||
press-key: "Tab"
|
||||
|
@ -220,8 +220,8 @@ press-key: "Tab"
|
|||
press-key: "Tab"
|
||||
press-key: "Tab"
|
||||
press-key: "Tab"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
|
||||
// Now we check that the focus isn't given back to the wrong item when opening
|
||||
// another popover.
|
||||
|
@ -231,8 +231,8 @@ click: "#method\.create_an_iterator_from_read .fn"
|
|||
assert-window-property-false: {"scrollY": |scroll|}
|
||||
// Store the new position.
|
||||
store-window-property: (scroll, "scrollY")
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
wait-for: "//*[@class='notable popover']"
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
wait-for: "//*[@class='tooltip popover']"
|
||||
click: "#settings-menu a"
|
||||
click: ".search-input"
|
||||
// We ensure we didn't come back to the previous focused item.
|
||||
|
@ -245,8 +245,8 @@ click: "#method\.create_an_iterator_from_read .fn"
|
|||
assert-window-property-false: {"scrollY": |scroll|}
|
||||
// Store the new position.
|
||||
store-window-property: (scroll, "scrollY")
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
wait-for: "//*[@class='notable popover']"
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
wait-for: "//*[@class='tooltip popover']"
|
||||
click: "#settings-menu a"
|
||||
press-key: "Escape"
|
||||
// We ensure we didn't come back to the previous focused item.
|
||||
|
@ -254,23 +254,23 @@ assert-window-property-false: {"scrollY": |scroll|}
|
|||
|
||||
// Opening the mobile sidebar should close the popover.
|
||||
size: (650, 600)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
click: ".sidebar-menu-toggle"
|
||||
assert: "//*[@class='sidebar shown']"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
|
||||
// Clicking a notable popover should close the sidebar.
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
// Clicking a notable trait tooltip popover should close the sidebar.
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
assert-false: "//*[@class='sidebar shown']"
|
||||
|
||||
// Also check the focus handling for the help button.
|
||||
size: (1100, 600)
|
||||
reload:
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
|
||||
assert-count: ("//*[@class='notable popover']", 1)
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
click: "#help-button a"
|
||||
assert-count: ("//*[@class='notable popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
-Z symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
|
||||
-Z teach=val -- show extended diagnostic help (default: no)
|
||||
-Z temps-dir=val -- the directory the intermediate files are written to
|
||||
-Z terminal-urls=val -- use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output
|
||||
-Z thinlto=val -- enable ThinLTO when possible
|
||||
-Z thir-unsafeck=val -- use the THIR unsafety checker (default: no)
|
||||
-Z threads=val -- use a thread pool with N threads
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// @has foo/fn.bar.html '//*[@class="example-wrap compile_fail"]/*[@class="tooltip"]' "ⓘ"
|
||||
// @has foo/fn.bar.html '//*[@class="example-wrap ignore"]/*[@class="tooltip"]' "ⓘ"
|
||||
// @has foo/fn.bar.html '//*[@class="example-wrap should_panic"]/*[@class="tooltip"]' "ⓘ"
|
||||
// @has foo/fn.bar.html '//*[@data-edition="2018"]' "ⓘ"
|
||||
// @has foo/fn.bar.html '//*[@title="This example runs with edition 2018"]' "ⓘ"
|
||||
|
||||
/// foo
|
||||
///
|
||||
|
|
|
@ -9,7 +9,7 @@ impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
|
|||
#[doc(notable_trait)]
|
||||
pub trait SomeTrait {
|
||||
// @has doc_notable_trait/trait.SomeTrait.html
|
||||
// @has - '//a[@class="notable-traits"]/@data-ty' 'Wrapper<Self>'
|
||||
// @has - '//a[@class="tooltip"]/@data-notable-ty' 'Wrapper<Self>'
|
||||
// @snapshot wrap-me - '//script[@id="notable-traits-data"]'
|
||||
fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
|
||||
Wrapper {
|
||||
|
@ -23,7 +23,7 @@ impl SomeTrait for SomeStruct {}
|
|||
|
||||
impl SomeStruct {
|
||||
// @has doc_notable_trait/struct.SomeStruct.html
|
||||
// @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
|
||||
// @has - '//a[@class="tooltip"]/@data-notable-ty' 'SomeStruct'
|
||||
// @snapshot some-struct-new - '//script[@id="notable-traits-data"]'
|
||||
pub fn new() -> SomeStruct {
|
||||
SomeStruct
|
||||
|
@ -31,7 +31,7 @@ impl SomeStruct {
|
|||
}
|
||||
|
||||
// @has doc_notable_trait/fn.bare_fn.html
|
||||
// @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
|
||||
// @has - '//a[@class="tooltip"]/@data-notable-ty' 'SomeStruct'
|
||||
// @snapshot bare-fn - '//script[@id="notable-traits-data"]'
|
||||
pub fn bare_fn() -> SomeStruct {
|
||||
SomeStruct
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::iter::Iterator;
|
||||
|
||||
// @has foo/struct.Odd.html
|
||||
// @has - '//*[@id="method.new"]//a[@class="notable-traits"]/@data-ty' 'Odd'
|
||||
// @has - '//*[@id="method.new"]//a[@class="tooltip"]/@data-notable-ty' 'Odd'
|
||||
// @snapshot odd - '//script[@id="notable-traits-data"]'
|
||||
pub struct Odd {
|
||||
current: usize,
|
||||
|
|
4
tests/ui/diagnostic-flags/terminal_urls.rs
Normal file
4
tests/ui/diagnostic-flags/terminal_urls.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
// compile-flags: -Zterminal-urls=yes
|
||||
fn main() {
|
||||
let () = 4; //~ ERROR
|
||||
}
|
11
tests/ui/diagnostic-flags/terminal_urls.stderr
Normal file
11
tests/ui/diagnostic-flags/terminal_urls.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[]8;;https://doc.rust-lang.org/error_codes/E0308.htmlE0308]8;;]: mismatched types
|
||||
--> $DIR/terminal_urls.rs:3:9
|
||||
|
|
||||
LL | let () = 4;
|
||||
| ^^ - this expression has type `{integer}`
|
||||
| |
|
||||
| expected integer, found `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
9
tests/ui/span/issue-107353.rs
Normal file
9
tests/ui/span/issue-107353.rs
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue