internal: add add_tabstop_{before,after}_token
This commit is contained in:
parent
db0add1ce9
commit
4de7cbe04c
@ -9,7 +9,10 @@ use crate::SnippetCap;
|
|||||||
use base_db::{AnchoredPathBuf, FileId};
|
use base_db::{AnchoredPathBuf, FileId};
|
||||||
use nohash_hasher::IntMap;
|
use nohash_hasher::IntMap;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use syntax::{algo, ast, ted, AstNode, SyntaxNode, SyntaxNodePtr, TextRange, TextSize};
|
use syntax::{
|
||||||
|
algo, ast, ted, AstNode, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
|
||||||
|
TextSize,
|
||||||
|
};
|
||||||
use text_edit::{TextEdit, TextEditBuilder};
|
use text_edit::{TextEdit, TextEditBuilder};
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
@ -237,19 +240,31 @@ impl SourceChangeBuilder {
|
|||||||
/// Adds a tabstop snippet to place the cursor before `node`
|
/// Adds a tabstop snippet to place the cursor before `node`
|
||||||
pub fn add_tabstop_before(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
pub fn add_tabstop_before(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
||||||
assert!(node.syntax().parent().is_some());
|
assert!(node.syntax().parent().is_some());
|
||||||
self.add_snippet(PlaceSnippet::Before(node.syntax().clone()));
|
self.add_snippet(PlaceSnippet::Before(node.syntax().clone().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a tabstop snippet to place the cursor after `node`
|
/// Adds a tabstop snippet to place the cursor after `node`
|
||||||
pub fn add_tabstop_after(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
pub fn add_tabstop_after(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
||||||
assert!(node.syntax().parent().is_some());
|
assert!(node.syntax().parent().is_some());
|
||||||
self.add_snippet(PlaceSnippet::After(node.syntax().clone()));
|
self.add_snippet(PlaceSnippet::After(node.syntax().clone().into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a tabstop snippet to place the cursor before `token`
|
||||||
|
pub fn add_tabstop_before_token(&mut self, _cap: SnippetCap, token: SyntaxToken) {
|
||||||
|
assert!(token.parent().is_some());
|
||||||
|
self.add_snippet(PlaceSnippet::Before(token.clone().into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a tabstop snippet to place the cursor after `token`
|
||||||
|
pub fn add_tabstop_after_token(&mut self, _cap: SnippetCap, token: SyntaxToken) {
|
||||||
|
assert!(token.parent().is_some());
|
||||||
|
self.add_snippet(PlaceSnippet::After(token.clone().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a snippet to move the cursor selected over `node`
|
/// Adds a snippet to move the cursor selected over `node`
|
||||||
pub fn add_placeholder_snippet(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
pub fn add_placeholder_snippet(&mut self, _cap: SnippetCap, node: impl AstNode) {
|
||||||
assert!(node.syntax().parent().is_some());
|
assert!(node.syntax().parent().is_some());
|
||||||
self.add_snippet(PlaceSnippet::Over(node.syntax().clone()))
|
self.add_snippet(PlaceSnippet::Over(node.syntax().clone().into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_snippet(&mut self, snippet: PlaceSnippet) {
|
fn add_snippet(&mut self, snippet: PlaceSnippet) {
|
||||||
@ -282,38 +297,40 @@ impl From<FileSystemEdit> for SourceChange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum PlaceSnippet {
|
enum PlaceSnippet {
|
||||||
/// Place a tabstop before a node
|
/// Place a tabstop before an element
|
||||||
Before(SyntaxNode),
|
Before(SyntaxElement),
|
||||||
/// Place a tabstop before a node
|
/// Place a tabstop before an element
|
||||||
After(SyntaxNode),
|
After(SyntaxElement),
|
||||||
/// Place a placeholder snippet in place of the node
|
/// Place a placeholder snippet in place of the element
|
||||||
Over(SyntaxNode),
|
Over(SyntaxElement),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlaceSnippet {
|
impl PlaceSnippet {
|
||||||
/// Places the snippet before or over a node with the given tab stop index
|
/// Places the snippet before or over an element with the given tab stop index
|
||||||
fn place(self, order: usize) {
|
fn place(self, order: usize) {
|
||||||
// ensure the target node is still attached
|
// ensure the target element is still attached
|
||||||
match &self {
|
match &self {
|
||||||
PlaceSnippet::Before(node) | PlaceSnippet::After(node) | PlaceSnippet::Over(node) => {
|
PlaceSnippet::Before(element)
|
||||||
// node should still be in the tree, but if it isn't
|
| PlaceSnippet::After(element)
|
||||||
|
| PlaceSnippet::Over(element) => {
|
||||||
|
// element should still be in the tree, but if it isn't
|
||||||
// then it's okay to just ignore this place
|
// then it's okay to just ignore this place
|
||||||
if stdx::never!(node.parent().is_none()) {
|
if stdx::never!(element.parent().is_none()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
PlaceSnippet::Before(node) => {
|
PlaceSnippet::Before(element) => {
|
||||||
ted::insert_raw(ted::Position::before(&node), Self::make_tab_stop(order));
|
ted::insert_raw(ted::Position::before(&element), Self::make_tab_stop(order));
|
||||||
}
|
}
|
||||||
PlaceSnippet::After(node) => {
|
PlaceSnippet::After(element) => {
|
||||||
ted::insert_raw(ted::Position::after(&node), Self::make_tab_stop(order));
|
ted::insert_raw(ted::Position::after(&element), Self::make_tab_stop(order));
|
||||||
}
|
}
|
||||||
PlaceSnippet::Over(node) => {
|
PlaceSnippet::Over(element) => {
|
||||||
let position = ted::Position::before(&node);
|
let position = ted::Position::before(&element);
|
||||||
node.detach();
|
element.detach();
|
||||||
|
|
||||||
let snippet = ast::SourceFile::parse(&format!("${{{order}:_}}"))
|
let snippet = ast::SourceFile::parse(&format!("${{{order}:_}}"))
|
||||||
.syntax_node()
|
.syntax_node()
|
||||||
@ -321,7 +338,7 @@ impl PlaceSnippet {
|
|||||||
|
|
||||||
let placeholder =
|
let placeholder =
|
||||||
snippet.descendants().find_map(ast::UnderscoreExpr::cast).unwrap();
|
snippet.descendants().find_map(ast::UnderscoreExpr::cast).unwrap();
|
||||||
ted::replace(placeholder.syntax(), node);
|
ted::replace(placeholder.syntax(), element);
|
||||||
|
|
||||||
ted::insert_raw(position, snippet);
|
ted::insert_raw(position, snippet);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user