Let there be color!

I've contributed to KDevelop in the past, on the Python plugin, and so far working on the Rust plugin, my impressions from back then were pretty much spot-on. KDevelop has one of the most well thought-out codebases I've seen. Specifically, KDevPlatform abstracts over different programming languages incredibly well and makes writing a new language plugin a very pleasant experience.

The Declaration-Use Chain

The Declaration-Use Chain stands at the core of this. It's a simple enough concept: there are things in the language which are declared somewhere and used in other places. Declarations are a generalization of programming language constructs: structs, struct fields, functions, methods, locals, etc. Declarations can open contexts and any declarations in a child context are valid in that context only. For example, functions open a new context for declarations inside the function body. Uses are, well, what you'd expect: instances where these language constructs are used.

Obviously, there's some details I skipped here, but the beauty in all of this is that KDevelop can figure out a lot of things for you if it simply has access to this information.

The Rust Compiler

The Rust compiler is also really well designed in that it allows accessing the internals such as the syntax parsing library. It's not necessarily the nicest thing, as the internals are intentionally marked unstable, but given that a lot of other tools for working with Rust source code like RLS also depend on compiler-internal libraries, I think this is an acceptable compromise.

These will likely stabilise over time, especially given the amount of effort being put into the save-analysis API. Speaking of which, one thing missing that would be very useful is to be able to get the full span of declarations that have an internal context (e.g. the span that covers the body of a function).

My main effort on the Rust side is trying to expose a C API to the compiler structures that is more independent from the compiler internals themselves. Think libclang. I think something like this would make adding support in other IDEs easier. I'm currently looking into hooking into the various stages of the compiler in order to get both the pre- and post-expansion AST, as well as type information inferred by the compiler (though I'll likely try to implement this myself first for the learning experience :)).

Building the DU Chain for Rust code

And now the fun part: how these fit together. Here is a before and after:

 

Much better. 

Going forward

There are things still missing here; as you may have noticed, uses are not highlighted. I have to admit, I fell about a week and a half behind schedule due to a university group project which was more time consuming than I initially expected as well as my attempt to think through how to best expose certain things as a C API from Rust before writing a significant amount of code. Thankfully, I accounted for some delays like this in my original timeline, so this should be recoverable from.

Right now, I'm aiming to finish adding the missing elements of the DU Chain by the end of this week and then I'll start looking into code completion. 

Comments

  1. Hm, I don't quite understand how DU interacts with highlighting here... Does KDevelop automatically apply highlighting as soon as you classify some nodes as declarations? In IntelliJ, we apply highlighting manually, by switching on the syntax node type, which does not interact with IJ Ds (PsiNamedElement) and Us (PsiReference): https://github.com/intellij-rust/intellij-rust/blob/master/src/main/kotlin/org/rust/ide/annotator/RsHighlightingAnnotator.kt#L77-L108.

    ReplyDelete
    Replies
    1. Yeah, the highlighting is done automatically by KDevelop based on how the declarations are classified. I think it's quite a nice approach.

      Delete
  2. Nice work, Emma! I think this is impressive progress, especially for the short time you've been on the project.

    ReplyDelete
  3. Neat ! Looking forward to your next updates.

    ReplyDelete
  4. It's also interesting that even such minimal language model on the IDE side allows to implement features, not available via LSP. For example, on the screenshots we can see that semantic highlighting (coloring different local variables in different colors) already works! And you can't implement it on top of the current LSP API.

    ReplyDelete

Post a Comment

Popular Posts