Skip to content

Conversation

@vbfox
Copy link
Contributor

@vbfox vbfox commented Mar 22, 2020

This PR proposes 2 new assists, inspired by the identical ones in jetbrains C# IDEs

  • Remove separators that remove all '_' from a number literal
  • Separate number by thousands/bytes/nibbles with separator

thousands

hex

I also did a few technical changes around the assist code:

  • Add add_assists that has the same syntax as adding a group but without assigning a group to the returned assists.
  • Add find_covering_node_at_offset to avoid cases where the selection start inside a number literal but ends further (like at the end of the file) triggering the assist.
  • Test helpers to allow testing AssistHandler implementations that can return multiple assists

Remarks/Questions:

  • I didn't set the cursor position explicitly as doing it right inside the code would complexify it greatly. At least on VSCode the final position is very good (And the LSP doesn't have the cursor position in TextEdit AFAIK), I suspect there is a diff algorithm applied somewhere to do a best guess of the cursor position. If specifying the cursor position is needed I'd prefer to PR an a similar feature in rust-analyzer than implementing it manually in analyzers.
  • After implementing it I remarked that jetbrains version add a '_' character between the prefix and the digits for cases where there is a prefix (binary, hex) like 0x_FF00_FF00 I don't have an opinion about it but if anyone has a preference...
  • There is no separator insertion for octal numbers

Note: I plan to add also PR the conversion between bases at some point.

This add 2 assists
* Remove separators that remove all '_' from a number literal
* Separate number by thousands/bytes/nibbles with separator
r#"fn f() { let x = <|>0b001_0101_000_101_010; }"#,
r#"fn f() { let x = <|>0b00101010_00101010; }"#,
)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of tests :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure all the combinations are useful in the end they are essentially the same tests applied to all supported representations, can remove some if needed :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think it might make sense to remove some of the boilerplate here with a table driven test:

for (before, after) in [("0b001_0101_000_101_010", "0b00101010_00101010") ... ] 

Copy link
Contributor

@Veetaha Veetaha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very nice!

From PR suggestion

Co-Authored-By: Veetaha <[email protected]>
Copy link
Contributor

@matklad matklad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't set the cursor position explicitly

Yeah, I think most of the assists shouldn't actually specify cursor position. We currently over-specify it, because our bulit-in diffing is imprecise and because (I think) VS Code used to not be so good at determining the cursor position afterwards.

To be clear, there are absolutelly assists where we want to place cursor smarter than the default (add derive, for example), but most of the boring transformations should be fine as is.

r#"fn f() { let x = <|>0b001_0101_000_101_010; }"#,
r#"fn f() { let x = <|>0b00101010_00101010; }"#,
)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think it might make sense to remove some of the boilerplate here with a table driven test:

for (before, after) in [("0b001_0101_000_101_010", "0b00101010_00101010") ... ] 

}

#[derive(Clone, Debug)]
struct NumberLiteral {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty and general-purpose utility, so I think it's should live in ra_synax. I think the right API would be as follows:

  • add pub struct IntNumber(SyntaxToken); to tokens.rs
  • suffix/preffix methods could return Option<&str> then. I think ideally we might want even fn suffix_range() -> Option<TextRange>, fn suffix_text() -> Option<&str>, but its ok to not add anything beyond this PR.
  • ideally, duplicaiton with LiteralKind should be removed. Perhaps it could return an enum of tokens, instead of a lowered enum? But that, again, is probably out of scope of this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main theme of the API we want is that, as long as possible, we should just give "views" into existing syntax nodes and tokens, rather than converting them into a POD rust types. Sort of the opposite of what you'd do in a traditional compiler.

}
}

pub(crate) struct AssistVec<'a> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, this API looks good to me!

str.replace("_", "")
}

pub(crate) fn remove_digit_separators(ctx: AssistCtx) -> Option<Assist> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put pub(crate) functions on top, and add "doc comments" to them (see other assists). These comments then go into auto-generated docs. No need to document every assist, but at least a single example would be useful.

@matklad
Copy link
Contributor

matklad commented Apr 21, 2020

ping @vbfox , in case this just accidently fell of from your radar :)

@matklad
Copy link
Contributor

matklad commented May 5, 2020

closing due to inactivity, but feel free to reopen!

@matklad matklad closed this May 5, 2020
bors bot added a commit that referenced this pull request Dec 13, 2021
10998: Add number representation assists r=Veykril a=errx

Reimplemented assists from this PR #3683 with current APIs.
![image](https://user-images.githubusercontent.com/462486/145726792-47700215-26f2-4fdc-9520-63d1487901e5.png)
![image](https://user-images.githubusercontent.com/462486/145726802-f528a2f7-9159-41d3-b459-fc3fae033e60.png)


I've decided not to add options about size of the groups so behaviour is similar to clippy's. 
Minimal number length is also taken from clippy.


Co-authored-by: Oleg Matrokhin <[email protected]>
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Jul 16, 2024
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.

4 participants