[Feature Request] Code Actions: Generate setters that return `&mut Self`
Hello,
I think it will be extremely useful to auto-generate setters that return a mutable reference to self.
We could use them to chain together setter operations, and simplify our code.
I specifically use them to construct objects, or to only partially modify objects.
Also, chaining together operations is pretty comfy.
For a struct such as this:
struct Student {
age: usize,
books: usize,
}
We would use it to construct objects as:
let me = *Student::new()
.set_age(30)
.set_books(300);
Or only partially modify objects as:
let me = &mut students[i];
me.set_age(40);
The current code actions only generate setters that don't return anything.
To make this chaining feature work, the setters obviously need to return a &mut Self. As in,
pub fn set_age(&mut self, age: usize) -> &mut Self {
self.age = age;
self
}
I think this feature would be extremely useful.
Thanks!
This seems rather specific, in the general case a setter is just a plain setter, and your wanted behavior is wanted one a case by case basis usually so I don't think we'd want to do anything special here. You should be able to just put a self at the end of the generated function though and have the type mismatch diagnostic quickfix be able to fill out the return type (if we aren't offering that yet we ought to).
It is a specific case of setters, but if implemented, it can also improve user's productivity.
Adding -> &mut Self as a return type to all setters, then returning self, is little bit tedious.
I am able to use a neovim macro to do it in two keystrokes. So, it's not a problem for me.
However, it might be tedious for other users, who use vscode, or other IDEs.
This feature seems important enough to be implemented as a separate code action.
I see this method being useful as a simplified version of a Builder Pattern
Rust doesn't support function overloading, and it's non-trivial to create different functions to construct objects in different ways.
It's easier to just construct a default object, and modify it in place.
In my proprietary code, I used this method for constructing a complex node object for a Octree graph structure.
pub fn add_leaf_node(
&mut self,
ilevel: usize,
iparent: usize,
pos: [f64; 3],
width: f64,
) -> Result<()> {
let inode = self.inext();
let node = OctreeNode::new()
.set_origin(pos)
.set_width(width)
.set_inode(inode)
.set_ilevel(ilevel)
.set_iparent(iparent)
.mov();
self.tree.push(node);
Ok(())
}
Thanks @asukaminato0721
Initially I didn't think derive_builder would be what I was looking for, but I think it is better to use derive macros to auto-generate all of the getters and setters for our structs.
derive_builder doesn't completely suit my specific use case, but I can take inspiration from their code to build something of my own.
That would reduce code bloat, and development time.
I think this feature could be nice to have, but ideally it should take mut self as proposed by https://matklad.github.io/2022/05/29/builder-lite.html
pub fn with_material(mut self, material: Material) -> Self {
self.material = Some(material);
self
}