Skip to content

Re-export rowan types

Aleksey Kladov requested to merge matklad/rnix:re-export into master

That way, consumers of the library wouldn't have to add rowan to their Cargo.toml, which makes upgrading rowan easier.

This also makes the API easier to use, because rnix becomes one stop shop to import all of the types.

I also would like to use this PR as a discussion of more general wrapping from https://github.com/rust-analyzer/rowan/pull/19 :-)

The position I want to argue for, given my current understanding, is that we should wrap rowan types in rnix-specific types, like rust-analyzer does. It might be that I am wrong, and the better approach is to make rowan API more flexible and pluggable, to make it easy to just use types from rowan directly!

I used to hate all kinds of boilerplate with a passion, but my opinion became more nuanced after I've worked with a couple of large projects. There are two kids of boilerplate:

  • duplication of bits of logic everywhere
  • forwarding duplication, when one API wraps the other API

My conclusion so far is that the first kind is almost always bad and should be eliminated as fast as possible. The second kind, though, can often be used as a tool to reduce or hide dependencies. A good example here is composition vs inheritance in OO languages. Composition is very boilerplaty: you have to forward methods, and you need to explicitly access the field, while with inheritance you just inherit from the base class, and voila, you can just call the stuff with zero boilerplate! The flip side of inheritance is of course fragile base class problem: base and derived class become tightly coupled, and base class becomes the public interface of the derived class.

Another good example of boilerplate code which I don't feel bad about is Rust's ops::Add/AddAssign and friends. You need to write a ton of impls to override all operators, which is more code than in C++ or Python. On the other hand, this is kind of boilerplate which is devoid of logic (actual addition is implemented once), so it's super-trivial to write and easy to maintain, because it never changes.

In case of rnix, the wrapping of SyntaxNode, SyntaxElement, and SyntaxToken has the following benefits:

  • we can write custom Debug/Display impls
  • we can write custom inherent methods for SyntaxNode
  • we can keep implementation of rowan really simple, because it doesn't need to be generic

So, what do you think about adding something like this to rnix? If you are fine with it, I'll be glad to do the actual work :-)

Merge request reports