Are you happy with the current state of Rust syntax highlighting?

Bikeshedding code appearance is just part of my nature, so I suppose it's only natural that I tried to make lots of tweaks when I first started learning Rust. In truth, I don't have much firsthand insight into the community, but my impression of the state of affairs was something along these lines:

  • The primary focus of the core team was shipping an amazing language, so a TextMate grammar was developed, but it was not desireable for it to be a big time sink for those involved.

  • People were sufficiently happy with the grammar that was provided, so making incremental improvements to it was not a major focus.

  • The long-term goal was to ship semantic highlighting, which is now becoming available, so there is little enthusiasm to tweak regex-based grammars at this point.

Some things that I've noticed, as semantic highlighting gains popularity across languages:

  • Semantic highlighting only addresses a minority of tokens on the page. Often, the semantic highlighting system relies on the underlying regex-based grammar to handle scopes for punctuation, operators, etc.

  • Semantic highlighting tends to favor correctness over nuance. For example, many semantic highlighting systems show function declarations in the same color as function calls. The AST provides a greater guarantee that they will be highlighted correctly, but removes these types of distinctions even if the underlying TextMate grammar previously supplied them.

In any event, I wanted to tweak my theme, so for my own purposes I simply wrote a new regex-based grammar that met my needs. I am using VS Code, so I published the grammar as an extension, and then tweaked my Yarra Valley theme to use it:

At the moment I'm happy, but I wondered if the community had any interest in using the grammar to tweak other themes, or using it in other editors. VS Code is currently upstreaming the grammars supplied with Atom, and prefers changes be made on the Atom side first. The main Rust VS Code extension appears to just fall back to the built-in grammar, and the Rust Analyzer extension appears to be shipping the same grammar that is already used by Atom and VS Code.

Should I leave things as they are? Or should I try to get this upstreamed elsewhere (editors, RLS/RA)? Please let me know if there is any interest, or other feedback. Now back to learning Rust :slight_smile:

3 Likes

Yes.

3 Likes

Rust-analyzer has semantic highlighting based on the parsed ast. It shows mutable variables with an underscore. It knows about the format! syntax. It has a token type for unresolved identifiers. It marks dereferences of raw pointers with an unsafe attribute.

That’s not true for rust-analyzer: it colors every token semantically.

For example, many semantic highlighting systems show function declarations in the same color as function calls.

In rust analyzer, declarations get „declaration“ tag, so a theme can color declarations and usages differently. But by default they indeed use the same color.

That hasn't been my experience. If I have an expression like:

if t_type == std::any::TypeId::of::<Option<Ms>>() {
//...
}

I only see semantic tokens being applied to a fraction of the elements.

if (keyword)
t_type (none)
== (operator)
std (none)
:: (punctuation)
any (none)
:: (punctuation)
TypeId (none)
:: (punctuation)
of (none)
< (punctuation)
Option (none)
< (punctuation)
Ms (none)
>>() { (punctuation)

So if I want to theme the variable, namespaces, types, it appears that all of those are falling back to the TextMate scopes. Am I missing something?

The best way to check that is "Inspect Editor Tokens and Scopes" action

4 Likes

That's exactly what I'm doing...

Clearly Rust Analyzer is not running properly (at all?) in my setup. Although if that's the case, I'm not sure where the existing semantic scopes are coming from. I've disabled all other Rust extensions.

Will troubleshoot a bit...

Looks like the issue was a conflict between my global semantic highlighting settings and the Rust-specific settings. I will set up the semantic scopes for my theme and see how that looks. Thanks for your time, @matklad.

1 Like

BTW, if you ever unsatisfied with semantic scopes rust-analyzer provides, the code is relatively easy to hack on: https://github.com/rust-analyzer/rust-analyzer/blob/2edf15aede0a9663e6fc512d2e0bf3e8df3fb3c0/crates/ide/src/syntax_highlighting.rs :wink:

2 Likes

I use CLion, so not sure if this is relevant for you, but sometimes I wish it would distinguish between owned types and (non-mutable) references (borrows):

fn main() {
  let v = Vec::new();
  foo(&v);
}

fn foo(v: &Vec) {
  bar(v); // <--- It looks like bar is consuming v, but it isn't.
}

fn bar(v: &Vec) {
}

I haven't actually thought this through, maybe it's not possible/not as helpful as I think.

Playing with the scopes in Rust Analyzer, it appears that it does a limited amount of this, such as distinguishing selfKeyword:rust from selfKeyword.mutable:rust.

At the moment I am being crushed under a large number of unresolvedReference scopes—both types and functions—so I haven't gotten that far in customizing my theme for semantic. Will need to figure out why that's happening first.

Rust-analyzer has the Consuming attribute for this:
https://github.com/rust-analyzer/rust-analyzer/blob/a61178d2186b8d9ca324231ab03368819be0ff6e/crates/ide/src/syntax_highlighting.rs#L553

1 Like

I won't discuss about syntax highlighting in general, but I will point out that it is annoying when (too) many syntax highlighters are not aware of all the syntactic possibilities of the language they want to highlight / colorize.

For instance, I had to move away from Sublime Text, since it does not support the optional leading pipe for match arms patterns:

  • Screenshot 2020-09-28 at 17.12.19

Even https://docs.rs "Source code" section suffers from this :weary::

4 Likes

Yes ..... I'm pretty much used to the current highlighting

Rust macro makes it possible to embed another language inside Rust (such as HTML, XML, SQL, JSX-like DSL , etc.). It would be cool if it is highlighted as well (I don't know how it can be achieved though)

For this, we have to let the editor (not the language server, but the editor itself, which will then call another language server) know, what kind of language we have inside macro. And note that its syntax might not be the same as the "non-embedded" one, due to, for example, type ascriptions.

In VS Code, this would typically be handled using the embedded language API. Unfortunately that approach only works for that particular editor, as @Cerber-Ursi pointed out.

Yes, IntelliJ Rust plugin is amazing and I'm endlessly thankful to the authors.

The VS Code project is currently considering this grammar as the new default builtin grammar for Rust (microsoft/vscode#108254). This would replace the old Atom grammar which does not seem maintained right now.

1 Like

The current plan is to merge the grammar from Rust Syntax into VS Code Insiders for a couple months, after which it would be merged into Stable if feedback is positive. However, I'm not sure how soon the PR mentioned by @jonasbb will be merged. Thanks to the kindness of the Rust Analyzer team, I have been able to merge it there in the interim, which makes the VS Code PR a bit less pressing.

I have updated my Yarra Valley theme to work with Rust Analyzer's semantic scopes, so users now have both options.

3 Likes