diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-03 09:23:44 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-03 09:23:44 +0100 |
commit | 77462bba621b0e85f3f04bbcebd2a065a875ac02 (patch) | |
tree | c86a14f9389a183fc574a89d6364fdfa4771bb91 /crates/ra_syntax/src | |
parent | 2cee8531c5236ae7d66717bea604f1224c23ea56 (diff) | |
parent | 10667753c71242c75e70e7b8c46486f37685c186 (diff) |
Merge #3746
3746: Add create_function assist r=flodiebold a=TimoFreiberg
The function part of #3639, creating methods will come later
- [X] Function arguments
- [X] Function call arguments
- [x] Method call arguments
- [x] Literal arguments
- [x] Variable reference arguments
- [X] Migrate to `ast::make` API
Done, but there are some ugly spots.
Issues to handle in another PR:
- function reference arguments: Their type isn't printed properly right now.
The "insert explicit type" assist has the same issue and this is probably a relatively rare usecase.
- generating proper names for all kinds of argument expressions (if, loop, ...?)
Without this, it's totally possible for the assist to generate invalid argument names.
I think the assist it's already helpful enough to be shipped as it is, at least for me the main usecase involves passing in named references.
Besides, the Rust tooling ecosystem is immature enough that some janky behaviour in a new assist probably won't scare anyone off.
- select the generated placeholder body so it's a bit easier to overwrite it
- create method (`self.foo<|>(..)` or `some_foo.foo<|>(..)`) instead of create_function.
The main difference would be finding (or creating) the impl block and inserting the `self` argument correctly
- more specific default arg names for literals.
So far, every generated argument whose name can't be taken from the call site is called `arg` (with a number suffix if necessary).
- creating functions in another module of the same crate.
E.g. when typing `some_mod::foo<|>(...)` when in `lib.rs`, I'd want to have `foo` generated in `some_mod.rs` and jump there.
Issues: the mod could exist in `some_mod.rs`, in `lib.rs` as `mod some_mod`, or inside another mod but be imported via `use other_mod::some_mod`.
- refer to arguments of the generated function with a qualified path if the types aren't imported yet
(alternative: run autoimport. i think starting with a qualified path is cleaner and there's already an assist to replace a qualified path with an import and an unqualified path)
- add type arguments of the arguments to the generated function
- Autocomplete functions with information from unresolved calls (see https://github.com/rust-analyzer/rust-analyzer/pull/3746#issuecomment-605281323)
Issues: see https://github.com/rust-analyzer/rust-analyzer/pull/3746#issuecomment-605282542. The unresolved call could be anywhere. But just offering this autocompletion for unresolved calls in the same module would already be cool.
Co-authored-by: Timo Freiberg <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index c49cf9a3b..f39559e9e 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -270,6 +270,31 @@ pub fn unreachable_macro_call() -> ast::MacroCall { | |||
270 | ast_from_text(&format!("unreachable!()")) | 270 | ast_from_text(&format!("unreachable!()")) |
271 | } | 271 | } |
272 | 272 | ||
273 | pub fn param(name: String, ty: String) -> ast::Param { | ||
274 | ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) | ||
275 | } | ||
276 | |||
277 | pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList { | ||
278 | let args = pats.into_iter().join(", "); | ||
279 | ast_from_text(&format!("fn f({}) {{ }}", args)) | ||
280 | } | ||
281 | |||
282 | pub fn fn_def( | ||
283 | fn_name: ast::Name, | ||
284 | type_params: Option<ast::TypeParamList>, | ||
285 | params: ast::ParamList, | ||
286 | body: ast::BlockExpr, | ||
287 | ) -> ast::FnDef { | ||
288 | let type_params = | ||
289 | if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; | ||
290 | ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body)) | ||
291 | } | ||
292 | |||
293 | pub fn add_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { | ||
294 | let newlines = "\n".repeat(amount_of_newlines); | ||
295 | ast_from_text(&format!("{}{}", newlines, t.syntax())) | ||
296 | } | ||
297 | |||
273 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 298 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
274 | let parse = SourceFile::parse(text); | 299 | let parse = SourceFile::parse(text); |
275 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 300 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |