Skip to content

Commit e614fd4

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#43918 - mystor:rustdoc-pound, r=QuietMisdreavus
Don't highlight # which does not start an attribute in rustdoc Currently when we highlight some macros for rustdoc (e.g. `quote!` from https://github.com/dtolnay/quote), we get really bad syntax highlighting, because we assume that every token between a `#` character and the next `]` in the source must be an attribute. This patch improves that highlighting behavior to instead only highlight after finding the `[` token after the `#` token. (NOTE: I've only run this patch against https://github.com/nrc/rustdoc-highlight so if it doesn't build on travis that's why - I don't have a recent rustc build on this laptop) I'm guessing r? @steveklabnik
2 parents 0f2bbed + 2f19383 commit e614fd4

File tree

2 files changed

+49
-17
lines changed

2 files changed

+49
-17
lines changed

src/librustdoc/html/highlight.rs

+43-15
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ impl<'a> Classifier<'a> {
172172
}
173173
}
174174

175+
/// Gets the next token out of the lexer, emitting fatal errors if lexing fails.
176+
fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
177+
match self.lexer.try_next_token() {
178+
Ok(tas) => Ok(tas),
179+
Err(_) => {
180+
self.lexer.emit_fatal_errors();
181+
self.lexer.sess.span_diagnostic
182+
.struct_warn("Backing out of syntax highlighting")
183+
.note("You probably did not intend to render this as a rust code-block")
184+
.emit();
185+
Err(io::Error::new(io::ErrorKind::Other, ""))
186+
}
187+
}
188+
}
189+
175190
/// Exhausts the `lexer` writing the output into `out`.
176191
///
177192
/// The general structure for this method is to iterate over each token,
@@ -183,18 +198,7 @@ impl<'a> Classifier<'a> {
183198
out: &mut W)
184199
-> io::Result<()> {
185200
loop {
186-
let next = match self.lexer.try_next_token() {
187-
Ok(tas) => tas,
188-
Err(_) => {
189-
self.lexer.emit_fatal_errors();
190-
self.lexer.sess.span_diagnostic
191-
.struct_warn("Backing out of syntax highlighting")
192-
.note("You probably did not intend to render this as a rust code-block")
193-
.emit();
194-
return Err(io::Error::new(io::ErrorKind::Other, ""));
195-
}
196-
};
197-
201+
let next = self.try_next_token()?;
198202
if next.tok == token::Eof {
199203
break;
200204
}
@@ -255,13 +259,37 @@ impl<'a> Classifier<'a> {
255259
}
256260
}
257261

258-
// This is the start of an attribute. We're going to want to
262+
// This might be the start of an attribute. We're going to want to
259263
// continue highlighting it as an attribute until the ending ']' is
260264
// seen, so skip out early. Down below we terminate the attribute
261265
// span when we see the ']'.
262266
token::Pound => {
263-
self.in_attribute = true;
264-
out.enter_span(Class::Attribute)?;
267+
// We can't be sure that our # begins an attribute (it could
268+
// just be appearing in a macro) until we read either `#![` or
269+
// `#[` from the input stream.
270+
//
271+
// We don't want to start highlighting as an attribute until
272+
// we're confident there is going to be a ] coming up, as
273+
// otherwise # tokens in macros highlight the rest of the input
274+
// as an attribute.
275+
276+
// Case 1: #![inner_attribute]
277+
if self.lexer.peek().tok == token::Not {
278+
self.try_next_token()?; // NOTE: consumes `!` token!
279+
if self.lexer.peek().tok == token::OpenDelim(token::Bracket) {
280+
self.in_attribute = true;
281+
out.enter_span(Class::Attribute)?;
282+
}
283+
out.string("#", Class::None, None)?;
284+
out.string("!", Class::None, None)?;
285+
return Ok(());
286+
}
287+
288+
// Case 2: #[outer_attribute]
289+
if self.lexer.peek().tok == token::OpenDelim(token::Bracket) {
290+
self.in_attribute = true;
291+
out.enter_span(Class::Attribute)?;
292+
}
265293
out.string("#", Class::None, None)?;
266294
return Ok(());
267295
}

src/test/rustdoc/issue-41783.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@
1212
// @!has - 'space'
1313
// @!has - 'comment'
1414
// @has - '# <span class="ident">single'
15-
// @has - '#<span class="attribute"># <span class="ident">double</span>'
16-
// @has - '#<span class="attribute">#<span class="attribute"># <span class="ident">triple</span>'
15+
// @has - '## <span class="ident">double</span>'
16+
// @has - '### <span class="ident">triple</span>'
17+
// @has - '<span class="attribute">#[<span class="ident">outer</span>]</span>'
18+
// @has - '<span class="attribute">#![<span class="ident">inner</span>]</span>'
1719

1820
/// ```no_run
1921
/// # # space
2022
/// # comment
2123
/// ## single
2224
/// ### double
2325
/// #### triple
26+
/// ##[outer]
27+
/// ##![inner]
2428
/// ```
2529
pub struct Foo;

0 commit comments

Comments
 (0)