Skip to content

Commit f5e9bda

Browse files
committed
doc comments: Less attribute mimicking
1 parent 12307b3 commit f5e9bda

File tree

9 files changed

+79
-94
lines changed

9 files changed

+79
-94
lines changed

src/librustc_lint/builtin.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ pub struct MissingDoc {
295295
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
296296

297297
fn has_doc(attr: &ast::Attribute) -> bool {
298+
if attr.is_doc_comment() {
299+
return true;
300+
}
301+
298302
if !attr.check_name(sym::doc) {
299303
return false;
300304
}
@@ -751,7 +755,7 @@ impl UnusedDocComment {
751755

752756
let span = sugared_span.take().unwrap_or_else(|| attr.span);
753757

754-
if attr.check_name(sym::doc) {
758+
if attr.is_doc_comment() || attr.check_name(sym::doc) {
755759
let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment");
756760

757761
err.span_label(

src/librustc_lint/unused.rs

+4
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
296296
fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
297297
debug!("checking attribute: {:?}", attr);
298298

299+
if attr.is_doc_comment() {
300+
return;
301+
}
302+
299303
let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name));
300304

301305
if let Some(&&(name, ty, ..)) = attr_info {

src/librustc_parse/validate_attr.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ use crate::parse_in;
44

55
use rustc_errors::{PResult, Applicability};
66
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
7-
use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
8-
use syntax::attr::mk_name_value_item_str;
7+
use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
98
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
109
use syntax::tokenstream::DelimSpan;
1110
use syntax::sess::ParseSess;
1211
use syntax_pos::{Symbol, sym};
1312

1413
pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
14+
if attr.is_doc_comment() {
15+
return;
16+
}
17+
1518
let attr_info =
1619
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
1720

@@ -28,25 +31,21 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
2831
}
2932

3033
pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
31-
Ok(match attr.kind {
32-
AttrKind::Normal(ref item) => MetaItem {
33-
span: attr.span,
34-
path: item.path.clone(),
35-
kind: match &attr.get_normal_item().args {
36-
MacArgs::Empty => MetaItemKind::Word,
37-
MacArgs::Eq(_, t) => {
38-
let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
39-
MetaItemKind::NameValue(v)
40-
}
41-
MacArgs::Delimited(dspan, delim, t) => {
42-
check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
43-
let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
44-
MetaItemKind::List(nmis)
45-
}
34+
let item = attr.get_normal_item();
35+
Ok(MetaItem {
36+
span: attr.span,
37+
path: item.path.clone(),
38+
kind: match &item.args {
39+
MacArgs::Empty => MetaItemKind::Word,
40+
MacArgs::Eq(_, t) => {
41+
let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
42+
MetaItemKind::NameValue(v)
43+
}
44+
MacArgs::Delimited(dspan, delim, t) => {
45+
check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
46+
let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
47+
MetaItemKind::List(nmis)
4648
}
47-
},
48-
AttrKind::DocComment(comment) => {
49-
mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
5049
}
5150
})
5251
}

src/librustc_save_analysis/lib.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -883,15 +883,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
883883
let mut result = String::new();
884884

885885
for attr in attrs {
886-
if attr.check_name(sym::doc) {
887-
if let Some(val) = attr.value_str() {
888-
if attr.is_doc_comment() {
889-
result.push_str(&strip_doc_comment_decoration(&val.as_str()));
890-
} else {
891-
result.push_str(&val.as_str());
892-
}
893-
result.push('\n');
894-
} else if let Some(meta_list) = attr.meta_item_list() {
886+
if let Some(val) = attr.doc_str() {
887+
if attr.is_doc_comment() {
888+
result.push_str(&strip_doc_comment_decoration(&val.as_str()));
889+
} else {
890+
result.push_str(&val.as_str());
891+
}
892+
result.push('\n');
893+
} else if attr.check_name(sym::doc) {
894+
if let Some(meta_list) = attr.meta_item_list() {
895895
meta_list.into_iter()
896896
.filter(|it| it.check_name(sym::include))
897897
.filter_map(|it| it.meta_item_list().map(|l| l.to_owned()))

src/librustdoc/clean/types.rs

+21-46
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use rustc::ty::layout::VariantIdx;
1717
use rustc::util::nodemap::{FxHashMap, FxHashSet};
1818
use rustc_index::vec::IndexVec;
1919
use rustc_target::spec::abi::Abi;
20-
use syntax::ast::{self, Attribute, AttrStyle, AttrKind, Ident};
20+
use syntax::ast::{self, AttrStyle, Ident};
2121
use syntax::attr;
22-
use syntax::util::comments;
22+
use syntax::util::comments::strip_doc_comment_decoration;
2323
use syntax::source_map::DUMMY_SP;
2424
use syntax_pos::hygiene::MacroKind;
2525
use syntax_pos::symbol::{Symbol, sym};
@@ -507,51 +507,26 @@ impl Attributes {
507507
let mut cfg = Cfg::True;
508508
let mut doc_line = 0;
509509

510-
/// If `attr` is a doc comment, strips the leading and (if present)
511-
/// trailing comments symbols, e.g. `///`, `/**`, and `*/`. Otherwise,
512-
/// returns `attr` unchanged.
513-
pub fn with_doc_comment_markers_stripped<T>(
514-
attr: &Attribute,
515-
f: impl FnOnce(&Attribute) -> T,
516-
) -> T {
517-
match attr.kind {
518-
AttrKind::Normal(_) => {
519-
f(attr)
520-
}
521-
AttrKind::DocComment(comment) => {
522-
let comment =
523-
Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str()));
524-
f(&Attribute {
525-
kind: AttrKind::DocComment(comment),
526-
id: attr.id,
527-
style: attr.style,
528-
span: attr.span,
529-
})
530-
}
531-
}
532-
}
533-
534510
let other_attrs = attrs.iter().filter_map(|attr| {
535-
with_doc_comment_markers_stripped(attr, |attr| {
536-
if attr.check_name(sym::doc) {
537-
if let Some(mi) = attr.meta() {
538-
if let Some(value) = mi.value_str() {
539-
// Extracted #[doc = "..."]
540-
let value = value.to_string();
541-
let line = doc_line;
542-
doc_line += value.lines().count();
511+
if let Some(value) = attr.doc_str() {
512+
let (value, mk_fragment): (_, fn(_, _, _) -> _) = if attr.is_doc_comment() {
513+
(strip_doc_comment_decoration(&value.as_str()), DocFragment::SugaredDoc)
514+
} else {
515+
(value.to_string(), DocFragment::RawDoc)
516+
};
543517

544-
if attr.is_doc_comment() {
545-
doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
546-
} else {
547-
doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
548-
}
518+
let line = doc_line;
519+
doc_line += value.lines().count();
520+
doc_strings.push(mk_fragment(line, attr.span, value));
549521

550-
if sp.is_none() {
551-
sp = Some(attr.span);
552-
}
553-
return None;
554-
} else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
522+
if sp.is_none() {
523+
sp = Some(attr.span);
524+
}
525+
None
526+
} else {
527+
if attr.check_name(sym::doc) {
528+
if let Some(mi) = attr.meta() {
529+
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
555530
// Extracted #[doc(cfg(...))]
556531
match Cfg::parse(cfg_mi) {
557532
Ok(new_cfg) => cfg &= new_cfg,
@@ -570,7 +545,7 @@ impl Attributes {
570545
}
571546
}
572547
Some(attr.clone())
573-
})
548+
}
574549
}).collect();
575550

576551
// treat #[target_feature(enable = "feat")] attributes as if they were
@@ -589,7 +564,7 @@ impl Attributes {
589564
}
590565

591566
let inner_docs = attrs.iter()
592-
.filter(|a| a.check_name(sym::doc))
567+
.filter(|a| a.doc_str().is_some())
593568
.next()
594569
.map_or(true, |a| a.style == AttrStyle::Inner);
595570

src/libsyntax/ast.rs

-4
Original file line numberDiff line numberDiff line change
@@ -2362,10 +2362,6 @@ pub enum AttrKind {
23622362
/// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
23632363
/// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
23642364
/// variant (which is much less compact and thus more expensive).
2365-
///
2366-
/// Note: `self.has_name(sym::doc)` and `self.check_name(sym::doc)` succeed
2367-
/// for this variant, but this may change in the future.
2368-
/// ```
23692365
DocComment(Symbol),
23702366
}
23712367

src/libsyntax/attr/builtin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_macros::HashStable_Generic;
1616
use rustc_error_codes::*;
1717

1818
pub fn is_builtin_attr(attr: &Attribute) -> bool {
19+
attr.is_doc_comment() ||
1920
attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
2021
}
2122

src/libsyntax/attr/mod.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl Attribute {
144144
pub fn has_name(&self, name: Symbol) -> bool {
145145
match self.kind {
146146
AttrKind::Normal(ref item) => item.path == name,
147-
AttrKind::DocComment(_) => name == sym::doc,
147+
AttrKind::DocComment(_) => false,
148148
}
149149
}
150150

@@ -168,7 +168,7 @@ impl Attribute {
168168
None
169169
}
170170
}
171-
AttrKind::DocComment(_) => Some(Ident::new(sym::doc, self.span)),
171+
AttrKind::DocComment(_) => None,
172172
}
173173
}
174174
pub fn name_or_empty(&self) -> Symbol {
@@ -180,7 +180,7 @@ impl Attribute {
180180
AttrKind::Normal(ref item) => {
181181
item.meta(self.span).and_then(|meta| meta.value_str())
182182
}
183-
AttrKind::DocComment(comment) => Some(comment),
183+
AttrKind::DocComment(..) => None,
184184
}
185185
}
186186

@@ -294,26 +294,34 @@ impl Attribute {
294294
}
295295
}
296296

297+
pub fn doc_str(&self) -> Option<Symbol> {
298+
match self.kind {
299+
AttrKind::DocComment(symbol) => Some(symbol),
300+
AttrKind::Normal(ref item) if item.path == sym::doc =>
301+
item.meta(self.span).and_then(|meta| meta.value_str()),
302+
_ => None,
303+
}
304+
}
305+
297306
pub fn get_normal_item(&self) -> &AttrItem {
298307
match self.kind {
299308
AttrKind::Normal(ref item) => item,
300-
AttrKind::DocComment(_) => panic!("unexpected sugared doc"),
309+
AttrKind::DocComment(_) => panic!("unexpected doc comment"),
301310
}
302311
}
303312

304313
pub fn unwrap_normal_item(self) -> AttrItem {
305314
match self.kind {
306315
AttrKind::Normal(item) => item,
307-
AttrKind::DocComment(_) => panic!("unexpected sugared doc"),
316+
AttrKind::DocComment(_) => panic!("unexpected doc comment"),
308317
}
309318
}
310319

311320
/// Extracts the MetaItem from inside this Attribute.
312321
pub fn meta(&self) -> Option<MetaItem> {
313322
match self.kind {
314323
AttrKind::Normal(ref item) => item.meta(self.span),
315-
AttrKind::DocComment(comment) =>
316-
Some(mk_name_value_item_str(Ident::new(sym::doc, self.span), comment, self.span)),
324+
AttrKind::DocComment(..) => None,
317325
}
318326
}
319327
}

src/libsyntax_expand/parse/tests.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_pa
22

33
use rustc_parse::new_parser_from_source_str;
44
use syntax::ast::{self, Name, PatKind};
5-
use syntax::attr::first_attr_value_str_by_name;
65
use syntax::sess::ParseSess;
76
use syntax::token::{self, Token};
87
use syntax::print::pprust::item_to_string;
98
use syntax::ptr::P;
109
use syntax::source_map::FilePathMapping;
11-
use syntax::symbol::{kw, sym};
10+
use syntax::symbol::{kw, sym, Symbol};
1211
use syntax::tokenstream::{DelimSpan, TokenTree, TokenStream};
1312
use syntax::visit;
1413
use syntax::with_default_globals;
@@ -238,22 +237,21 @@ let mut fflags: c_int = wb();
238237
let source = "/// doc comment\r\nfn foo() {}".to_string();
239238
let item = parse_item_from_source_str(name_1, source, &sess)
240239
.unwrap().unwrap();
241-
let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap();
240+
let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
242241
assert_eq!(doc.as_str(), "/// doc comment");
243242

244243
let name_2 = FileName::Custom("crlf_source_2".to_string());
245244
let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
246245
let item = parse_item_from_source_str(name_2, source, &sess)
247246
.unwrap().unwrap();
248-
let docs = item.attrs.iter().filter(|a| a.has_name(sym::doc))
249-
.map(|a| a.value_str().unwrap().to_string()).collect::<Vec<_>>();
250-
let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
247+
let docs = item.attrs.iter().filter_map(|at| at.doc_str()).collect::<Vec<_>>();
248+
let b: &[_] = &[Symbol::intern("/// doc comment"), Symbol::intern("/// line 2")];
251249
assert_eq!(&docs[..], b);
252250

253251
let name_3 = FileName::Custom("clrf_source_3".to_string());
254252
let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string();
255253
let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap();
256-
let doc = first_attr_value_str_by_name(&item.attrs, sym::doc).unwrap();
254+
let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
257255
assert_eq!(doc.as_str(), "/** doc comment\n * with CRLF */");
258256
});
259257
}

0 commit comments

Comments
 (0)