From d5785108ed8edd959a7b292152b137ef0bf3273b Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Mon, 20 Mar 2017 18:03:11 -0400 Subject: [PATCH] Fix following removal of Attribute.value Since rust-lang/rust#40346 has now been merged, Attribute no longer has a .value field. Instead, we must follow the token stream and modify the tokens directly. For Docstring attributes, there should only be one token, the docstring value. --- src/plugins/src/lib.rs | 54 +++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/plugins/src/lib.rs b/src/plugins/src/lib.rs index 99a9eb89..056f7d95 100644 --- a/src/plugins/src/lib.rs +++ b/src/plugins/src/lib.rs @@ -7,16 +7,13 @@ extern crate syntax; use itertools::Itertools; use rustc_plugin::Registry; use syntax::ast::{self, Ident, TraitRef, Ty, TyKind}; -use syntax::ast::LitKind::Str; -use syntax::ast::MetaItemKind::NameValue; -use syntax::codemap::Spanned; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::quote::rt::Span; -use syntax::parse::{self, token, PResult}; +use syntax::parse::{self, token, str_lit, PResult}; use syntax::parse::parser::{Parser, PathStyle}; use syntax::symbol::Symbol; use syntax::ptr::P; -use syntax::tokenstream::TokenTree; +use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::util::small_vector::SmallVector; fn snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box { @@ -43,15 +40,44 @@ fn snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box = item.attrs + .drain(..) + .map(|mut attr| { + if !attr.is_sugared_doc { + return attr; + } + + // Getting at the underlying doc comment is surprisingly painful. + // The call-chain goes something like: + // + // - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L283 + // - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1067 + // - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1196 + // - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L399 + // - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L268 + // + // Note that a docstring (i.e., something with is_sugared_doc) *always* has exactly two + // tokens: an Eq followed by a Literal, where the Literal contains a Str_. We therefore + // match against that, modifying the inner Str with our modified Symbol. + let mut tokens = attr.tokens.clone().into_trees(); + if let Some(tt @ TokenTree::Token(_, token::Eq)) = tokens.next() { + let mut docstr = tokens.next().expect("Docstrings must have literal docstring"); + if let TokenTree::Token(_, token::Literal(token::Str_(ref mut doc), _)) = docstr { + *doc = Symbol::intern(&str_lit(&doc.as_str()).replace("{}", &old_ident)); + } else { + unreachable!(); + } + attr.tokens = TokenStream::concat(vec![tt.into(), docstr.into()]); + } else { + unreachable!(); + } + + attr + }) + .collect(); + item.attrs.extend(attrs.into_iter()); MacEager::trait_items(SmallVector::one(item)) }