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

Assist: create field in struct definition #4563

Closed
daboross opened this issue May 22, 2020 · 6 comments · Fixed by #16762
Closed

Assist: create field in struct definition #4563

daboross opened this issue May 22, 2020 · 6 comments · Fixed by #16762
Assignees
Labels
A-assists E-hard E-medium S-actionable Someone could pick this issue up and work on it right now

Comments

@daboross
Copy link

daboross commented May 22, 2020

It'd be cool if rust-analyzer could jump to creating a new field when I reference a field which doesn't exist.

Before:

#[derive(Default)]
struct Config {
    opt1: u32,
    opt2: u32,
}
fn main() {
    let conf = Config::default();
    let my_thing = conf.opt3<I>;
}

After:

#[derive(Default)]
struct Config {
    opt1: u32,
    opt2: u32,
    opt3: <I>,
}
fn main() {
    let conf = Config::default();
    let my_thing = conf.opt3;
}

It'd be cool if rust-analyzer could figure out the type rust expects opt3 to be, and autocomplete that (selecting it after), but I think that's optional. That would be a completion like this:

Before:

#[derive(Default)]
struct Config {
    opt1: u32,
    opt2: u32,
}
fn main() {
    let conf = Config::default();
    let my_float: f32 = conf.opt3<I>;
}

After:

#[derive(Default)]
struct Config {
    opt1: u32,
    opt2: u32,
    opt3: <f32>(type is selected),
}
fn main() {
    let conf = Config::default();
    let my_float: f32 = conf.opt3;
}

My main experience using this has been with IntelliJ's Java support.

Before:
image
After:
image

Let me know if there's anything else I can do to support this feature request.

@daboross daboross changed the title Assist: add missing field to struct definition Assist: create field in struct definition May 22, 2020
@matklad
Copy link
Member

matklad commented May 23, 2020

Yup, we need this. cc @TimoFreiberg who implemented similar feature for functions.

In general, I feel like this shouldn't really be an assist, but a quick-fix for a diagnostic about unreoslved reference. And we should probably have a separate crete_from_usage module to handle all similar cases...

@matklad
Copy link
Member

matklad commented May 23, 2020

Marking both medium and hard:

  • medium because just writing code to do this is not to hard, it's possible to just drop more stuff into ra_assisrs
  • hard because for long-term sustainability we really need an infrastructure here.

@TimoFreiberg
Copy link
Contributor

Sounds like a good plan 👍 I also think this needs some infrastructure.
I wasn't really aware of the differences between assists and quick-fixes until now, so I'm definitely still missing some knowledge about the current state - I'm probably going to try and get some feedback from you or the other experienced team members about any nontrivial designs before I build anything big 😅

@matklad
Copy link
Member

matklad commented May 24, 2020

Yup, so assists and quick fixes are indeed similar things, but annoying different things. Both are code transformation.

QuickFixes are responses for diagnostics. That is, on every change we compute the full set of errors, and than for some errors we produce quick fixes. QuickFixes also can make use of information collected when detecting errors (see, for example, downcasting here).
QuickFixes also should be actual fixes (ie, they should make code more correct).

Assists are just contextual helpers. They are not computed for the whole file, they are always computed at the specified cursor position. They also don't need to fix anything, they can just be potentially useful transformations.

I guess, my original though was that QuickFixes are computed eagerly on change, while assists are computed lazily for cursor position. Now that I think about it, I wonder if it makes sense to compute fixes lazily as well? We can compute them like quick-fixes, but, instead of the current cursor position, we can stuff current diagnostics into the assist context.

bors bot added a commit that referenced this issue Jun 19, 2020
4851: Add quickfix to add a struct field r=TimoFreiberg a=TimoFreiberg

Related to #4563 
I created a quickfix for record literals first because the NoSuchField diagnostic was already there.
To offer that quickfix for FieldExprs with unknown fields I'd need to add a new diagnostic (or create a `NoSuchField` diagnostic for those cases)

I think it'd make sense to make this a snippet completion (to select the generated type), but this would require changing the `Analysis` API and I'd like some feedback before I touch that.

Co-authored-by: Timo Freiberg <timo.freiberg@gmail.com>
@lnicola lnicola added A-assists S-actionable Someone could pick this issue up and work on it right now labels Jan 18, 2021
@flodiebold flodiebold added E-hard and removed E-hard labels Sep 19, 2021
@wyatt-herkamp
Copy link
Contributor

Hey, I would like to claim this issue. I have it partly working. I don't know how to make the caret go to the line that was added so that the user can specify the type?

2024-03-04.19-12-16.mp4

@rustbot claim

@Veykril
Copy link
Member

Veykril commented Mar 5, 2024

You want to look into how r-a handles snippets/SnippetCap, that's what allows moving the cursor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-assists E-hard E-medium S-actionable Someone could pick this issue up and work on it right now
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants