From e3598c6e9fa1a9088038a0ff4cb95a391d6821ae Mon Sep 17 00:00:00 2001 From: djrenren Date: Thu, 18 Jul 2019 11:54:24 -0700 Subject: [PATCH] Fix lexing of attributes and doc comments in Rust lexer (#957) A bug was causing files starting with attributes and doc comments to produce incorrect error nodes. This commit fixes that bug while also allowing attributes to occur in positions other than the start of a line, bringing it in line with Rust's grammar. --- lib/rouge/lexers/rust.rb | 19 +++++++++++-------- spec/visual/samples/rust | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/rouge/lexers/rust.rb b/lib/rouge/lexers/rust.rb index 4ecff63bc1..c80c3086ca 100644 --- a/lib/rouge/lexers/rust.rb +++ b/lib/rouge/lexers/rust.rb @@ -49,6 +49,7 @@ def macro_closed? start { @macro_delims = { ']' => 0, ')' => 0, '}' => 0 } + push :bol } delim_map = { '[' => ']', '(' => ')', '{' => '}' } @@ -60,20 +61,21 @@ def macro_closed? )x size = /8|16|32|64/ - state :start_line do + # Although not officially part of Rust, the rustdoc tool allows code in + # comments to begin with `#`. Code like this will be evaluated but not + # included in the HTML output produced by rustdoc. So that code intended + # for these comments can be higlighted with Rouge, the Rust lexer needs + # to check if the beginning of the line begins with a `# `. + state :bol do mixin :whitespace - rule %r/\s+/, Text - rule %r/#\[/ do - token Name::Decorator; push :attribute - end + rule %r/#\s[^\n]*/, Comment::Special rule(//) { pop! } - rule %r/#\s[^\n]*/, Comment::Preproc end state :attribute do mixin :whitespace mixin :has_literals - rule %r/[(,)=]/, Name::Decorator + rule %r/[(,)=:]/, Name::Decorator rule %r/\]/, Name::Decorator, :pop! rule id, Name::Decorator end @@ -85,8 +87,9 @@ def macro_closed? end state :root do - rule %r/\n/, Text, :start_line + rule %r/\n/, Text, :bol mixin :whitespace + rule %r/#!?\[/, Name::Decorator, :attribute rule %r/\b(?:#{Rust.keywords.join('|')})\b/, Keyword mixin :has_literals diff --git a/spec/visual/samples/rust b/spec/visual/samples/rust index 7f57c304e6..5b8c33cbeb 100644 --- a/spec/visual/samples/rust +++ b/spec/visual/samples/rust @@ -1,3 +1,4 @@ +#![test(a::b)] fn f() { let a = String::new("hello"); let b: &str = a;