Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getter/setter assists #7617

Merged
merged 1 commit into from
Feb 10, 2021
Merged

Add getter/setter assists #7617

merged 1 commit into from
Feb 10, 2021

Conversation

yoshuawuyts
Copy link
Member

@yoshuawuyts yoshuawuyts commented Feb 9, 2021

This patch makes progress towards the design outlined in #5943, and includes a small refactor which closes #7607. All together this patch does 4 things:

Design Notes

I've chosen to follow the Rust API guidelines on getters as closely as possible. This deliberately leaves "builder pattern"-style setters out of scope.

Also, similar to #7570 this assist generates doc comments. I think this should work well in most cases, and for the few where it doesn't it's probably easily edited. This makes it slightly less correct than the #7570 implementation, but I think this is still useful enough to include for many of the same reasons.

The reason why this PR contains 3 assists, rather than 1, is because each of them is so similar to the others that it felt more noisy to do them separately than all at once. The amount of code added does not necessarily reflect that, but hope that still makes sense.

Examples

Input

struct Person {
    name: String,     // <- cursor on "name"
}

generate getter

struct Person {
    name: String,
}

impl Person {
    /// Get a reference to the person's name.
    fn name(&self) -> &String {
        &self.name
    }
}

generate mut getter

struct Person {
    name: String,
}

impl Person {
    /// Get a mutable reference to the person's name.
    fn name_mut(&mut self) -> &mut String {
        &mut self.name
    }
}

generate setter

struct Person {
    name: String,
}

impl Person {
    /// Set the person's name.
    fn set_name(&mut self, name: String) {
        self.name = name;
    }
}

@Veykril
Copy link
Member

Veykril commented Feb 9, 2021

These do indeed share some common code like looking up the field the cursor is on and such, I wonder if it would make sense to put all of these assists in one module and extract those common bits into small helper functions. @matklad probably has a better eye for this.

@yoshuawuyts
Copy link
Member Author

I wonder if it would make sense to put all of these assists in one module and extract those common bits into small helper functions

About 2/3rds of the file for each of these assists are tests and docs. The few bits which are for a large part just the template generation. I suspect it may be easier to keep them separate and possibly merge later than the other way around. It's unclear how #5943 will be implemented in the future, so at least for now keeping things separate may be the easiest to work with?

Finish implementing `generate_setter` assists

Make `generate_impl_text` util generic

generate getter methods

Fix getter / setter naming

It's now in-line with the Rust API naming guidelines: https://rust-lang.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter

apply clippy

Improve examples
bors bot added a commit that referenced this pull request Feb 10, 2021
7619: Add #[track_caller] to assist tests r=matklad a=yoshuawuyts

This points the source of a failed assertion to the code which called it, rather than the location within the assertion helper method. While working on #7617 I had trouble locating some failing tests, and it was only by adding these attributes during development that I was able to locate them.

This is only applied to test helpers, which means it comes at no runtime cost. And even then: I didn't experience any noticeable performance with this enabled or disabled. Mostly just a more pleasant experience debugging test failures (: 

Co-authored-by: Yoshua Wuyts <[email protected]>
@Veykril
Copy link
Member

Veykril commented Feb 10, 2021

Sounds good to me 👍
bors r+

@bors
Copy link
Contributor

bors bot commented Feb 10, 2021

@bors bors bot merged commit 5e39d7a into rust-lang:master Feb 10, 2021
@yoshuawuyts yoshuawuyts deleted the setter-assist branch February 10, 2021 10:45
@Veykril
Copy link
Member

Veykril commented Feb 10, 2021

0tmem9ZYO3

bors bot added a commit that referenced this pull request Feb 12, 2021
7650: Add `find_impl_block_end` assist helper r=Veykril a=yoshuawuyts

Fixes #7605. This makes it so assists can use helpers to either append a method to the start or the end of an `impl` block. Thanks!

@Veykril if this is merged, perhaps it could be good to update the gif in #7617 (comment) ? -- this should fix the ordering issue when generating multiple methods.

Co-authored-by: Yoshua Wuyts <[email protected]>
@matklad
Copy link
Member

matklad commented Feb 12, 2021

Feels like we generate a bit too much assits here:

image

Let's fold all free into one "generate getter/setter" and use an "assist group" for that. (see, eg, convert_integer_literal)

@Veykril
Copy link
Member

Veykril commented Feb 13, 2021

Gif of the assists after #7662
waQB4WmpGC

@nicraMarcin
Copy link

Hi,
is it possible to generate all fields?

@JonasRothmann
Copy link

JonasRothmann commented Aug 7, 2023

It seems to not work if the impl has a macro

pub struct Account {
  pub id: String,
  pub user_id: String,
  pub provider: String,
}

#[juniper::graphql_object(Context = Context)]
impl Account {
    
    pub fn id(&self) -> &str {
        self.id.as_ref()
    }

    pub fn user_id(&self) -> &str {
        self.user_id.as_ref()
    }
}

When I generate getters/setters it creates a new impl instead of adding to the existing one:

pub struct Account {
  pub id: String,
  pub user_id: String,
  pub provider: String,
}

impl Account {
    pub fn provider(&self) -> &str {
        self.provider.as_ref()
    }
}

#[juniper::graphql_object(Context = Context)]
impl Account {
    
    pub fn id(&self) -> &str {
        self.id.as_ref()
    }

    pub fn user_id(&self) -> &str {
        self.user_id.as_ref()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

generate_enum_match doesn't work with generic params
5 participants