mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Extend add impl
This commit is contained in:
parent
147578f0fe
commit
8d82d1551e
5 changed files with 85 additions and 25 deletions
|
@ -1,4 +1,7 @@
|
||||||
use {TextUnit, EditBuilder, Edit};
|
use std::{
|
||||||
|
fmt::{self, Write},
|
||||||
|
};
|
||||||
|
|
||||||
use libsyntax2::{
|
use libsyntax2::{
|
||||||
ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner, ParsedFile},
|
ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner, ParsedFile},
|
||||||
SyntaxKind::COMMA,
|
SyntaxKind::COMMA,
|
||||||
|
@ -9,6 +12,8 @@ use libsyntax2::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use {TextUnit, EditBuilder, Edit};
|
||||||
|
|
||||||
pub struct ActionResult {
|
pub struct ActionResult {
|
||||||
pub edit: Edit,
|
pub edit: Edit,
|
||||||
pub cursor_position: Option<TextUnit>,
|
pub cursor_position: Option<TextUnit>,
|
||||||
|
@ -63,27 +68,31 @@ pub fn add_impl<'a>(file: &'a ParsedFile, offset: TextUnit) -> Option<impl FnOnc
|
||||||
let name = nominal.name()?;
|
let name = nominal.name()?;
|
||||||
|
|
||||||
Some(move || {
|
Some(move || {
|
||||||
// let type_params = nominal.type_param_list();
|
let type_params = nominal.type_param_list();
|
||||||
// let type_args = match type_params {
|
|
||||||
// None => String::new(),
|
|
||||||
// Some(params) => {
|
|
||||||
// let mut buf = String::new();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
let mut edit = EditBuilder::new();
|
let mut edit = EditBuilder::new();
|
||||||
let start_offset = nominal.syntax().range().end();
|
let start_offset = nominal.syntax().range().end();
|
||||||
edit.insert(
|
let mut buf = String::new();
|
||||||
start_offset,
|
buf.push_str("\n\nimpl");
|
||||||
format!(
|
if let Some(type_params) = type_params {
|
||||||
"\n\nimpl {} {{\n\n}}",
|
buf.push_display(&type_params.syntax().text());
|
||||||
name.text(),
|
}
|
||||||
)
|
buf.push_str(" ");
|
||||||
);
|
buf.push_str(name.text().as_str());
|
||||||
|
if let Some(type_params) = type_params {
|
||||||
|
comma_list(
|
||||||
|
&mut buf, "<", ">",
|
||||||
|
type_params.type_params()
|
||||||
|
.filter_map(|it| it.name())
|
||||||
|
.map(|it| it.text())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
buf.push_str(" {\n");
|
||||||
|
let offset = start_offset + TextUnit::of_str(&buf);
|
||||||
|
buf.push_str("\n}");
|
||||||
|
edit.insert(start_offset, buf);
|
||||||
ActionResult {
|
ActionResult {
|
||||||
edit: edit.finish(),
|
edit: edit.finish(),
|
||||||
cursor_position: Some(
|
cursor_position: Some(offset),
|
||||||
start_offset + TextUnit::of_str("\n\nimpl {\n") + name.syntax().range().len()
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -104,3 +113,26 @@ pub fn find_node<'a, N: AstNode<'a>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) {
|
||||||
|
buf.push_str(bra);
|
||||||
|
let mut first = true;
|
||||||
|
for item in items {
|
||||||
|
if !first {
|
||||||
|
first = false;
|
||||||
|
buf.push_str(", ");
|
||||||
|
}
|
||||||
|
write!(buf, "{}", item).unwrap();
|
||||||
|
}
|
||||||
|
buf.push_str(ket);
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PushDisplay {
|
||||||
|
fn push_display<T: fmt::Display>(&mut self, item: &T);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PushDisplay for String {
|
||||||
|
fn push_display<T: fmt::Display>(&mut self, item: &T) {
|
||||||
|
use std::fmt::Write;
|
||||||
|
write!(self, "{}", item).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -151,11 +151,11 @@ fn test_add_impl() {
|
||||||
"struct Foo {}\n\nimpl Foo {\n<|>\n}\n",
|
"struct Foo {}\n\nimpl Foo {\n<|>\n}\n",
|
||||||
|file, off| add_impl(file, off).map(|f| f()),
|
|file, off| add_impl(file, off).map(|f| f()),
|
||||||
);
|
);
|
||||||
// check_action(
|
check_action(
|
||||||
// "struct Foo<T: Clone> {<|>}",
|
"struct Foo<T: Clone> {<|>}",
|
||||||
// "struct Foo<T: Clone> {}\nimpl<T: Clone> Foo<T> {\n<|>\n}",
|
"struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}",
|
||||||
// |file, off| add_impl(file, off).map(|f| f()),
|
|file, off| add_impl(file, off).map(|f| f()),
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -580,6 +580,25 @@ impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {}
|
||||||
impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {}
|
impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {}
|
||||||
impl<'a> TypeDef<'a> {}
|
impl<'a> TypeDef<'a> {}
|
||||||
|
|
||||||
|
// TypeParam
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct TypeParam<'a> {
|
||||||
|
syntax: SyntaxNodeRef<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AstNode<'a> for TypeParam<'a> {
|
||||||
|
fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
|
||||||
|
match syntax.kind() {
|
||||||
|
TYPE_PARAM => Some(TypeParam { syntax }),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ast::NameOwner<'a> for TypeParam<'a> {}
|
||||||
|
impl<'a> TypeParam<'a> {}
|
||||||
|
|
||||||
// TypeParamList
|
// TypeParamList
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct TypeParamList<'a> {
|
pub struct TypeParamList<'a> {
|
||||||
|
@ -596,7 +615,11 @@ impl<'a> AstNode<'a> for TypeParamList<'a> {
|
||||||
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
|
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TypeParamList<'a> {}
|
impl<'a> TypeParamList<'a> {
|
||||||
|
pub fn type_params(self) -> impl Iterator<Item = TypeParam<'a>> + 'a {
|
||||||
|
super::children(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TypeRef
|
// TypeRef
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
|
@ -310,7 +310,8 @@ Grammar(
|
||||||
"NameRef": (),
|
"NameRef": (),
|
||||||
"Attr": ( options: [ ["value", "TokenTree"] ] ),
|
"Attr": ( options: [ ["value", "TokenTree"] ] ),
|
||||||
"TokenTree": (),
|
"TokenTree": (),
|
||||||
"TypeParamList": (),
|
"TypeParamList": ( collections: [ ["type_params", "TypeParam" ] ]),
|
||||||
|
"TypeParam": ( traits: ["NameOwner"]),
|
||||||
"WhereClause": (),
|
"WhereClause": (),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -110,6 +110,7 @@ pub fn handle_code_action(
|
||||||
let actions = &[
|
let actions = &[
|
||||||
(ActionId::FlipComma, libeditor::flip_comma(&file, offset).is_some()),
|
(ActionId::FlipComma, libeditor::flip_comma(&file, offset).is_some()),
|
||||||
(ActionId::AddDerive, libeditor::add_derive(&file, offset).is_some()),
|
(ActionId::AddDerive, libeditor::add_derive(&file, offset).is_some()),
|
||||||
|
(ActionId::AddImpl, libeditor::add_impl(&file, offset).is_some()),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (id, edit) in actions {
|
for (id, edit) in actions {
|
||||||
|
@ -218,6 +219,7 @@ pub fn handle_execute_command(
|
||||||
let action_result = match arg.id {
|
let action_result = match arg.id {
|
||||||
ActionId::FlipComma => libeditor::flip_comma(&file, arg.offset).map(|f| f()),
|
ActionId::FlipComma => libeditor::flip_comma(&file, arg.offset).map(|f| f()),
|
||||||
ActionId::AddDerive => libeditor::add_derive(&file, arg.offset).map(|f| f()),
|
ActionId::AddDerive => libeditor::add_derive(&file, arg.offset).map(|f| f()),
|
||||||
|
ActionId::AddImpl => libeditor::add_impl(&file, arg.offset).map(|f| f()),
|
||||||
}.ok_or_else(|| format_err!("command not applicable"))?;
|
}.ok_or_else(|| format_err!("command not applicable"))?;
|
||||||
let line_index = world.analysis().file_line_index(file_id)?;
|
let line_index = world.analysis().file_line_index(file_id)?;
|
||||||
let mut changes = HashMap::new();
|
let mut changes = HashMap::new();
|
||||||
|
@ -259,6 +261,7 @@ fn apply_code_action_cmd(id: ActionId, doc: TextDocumentIdentifier, offset: Text
|
||||||
enum ActionId {
|
enum ActionId {
|
||||||
FlipComma,
|
FlipComma,
|
||||||
AddDerive,
|
AddDerive,
|
||||||
|
AddImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActionId {
|
impl ActionId {
|
||||||
|
@ -266,6 +269,7 @@ impl ActionId {
|
||||||
match *self {
|
match *self {
|
||||||
ActionId::FlipComma => "Flip `,`",
|
ActionId::FlipComma => "Flip `,`",
|
||||||
ActionId::AddDerive => "Add `#[derive]`",
|
ActionId::AddDerive => "Add `#[derive]`",
|
||||||
|
ActionId::AddImpl => "Add impl",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue