From a525e830a62272d21fbb0fb1c20bfa865791512d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 17:57:12 +0300 Subject: add new editing API, suitable for modifying several nodes at once --- crates/ra_syntax/Cargo.toml | 1 + crates/ra_syntax/src/algo.rs | 32 ++++++++++++++++++++++++++++++++ crates/ra_syntax/src/ast/extensions.rs | 9 +++++++++ 3 files changed, 42 insertions(+) (limited to 'crates/ra_syntax') diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index d3a8b516a..724c38e17 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/rust-analyzer/rust-analyzer" itertools = "0.8.0" rowan = "0.6.1" rustc_lexer = "0.1.0" +rustc-hash = "1.0.1" # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here # to reduce number of compilations diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index 7ee5aa85b..f0ed96a17 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs @@ -3,6 +3,7 @@ pub mod visit; use std::ops::RangeInclusive; use itertools::Itertools; +use rustc_hash::FxHashMap; use crate::{ AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, @@ -123,6 +124,37 @@ pub fn replace_children( with_children(parent, new_children) } +/// Replaces descendants in the node, according to the mapping. +/// +/// This is a type-unsafe low-level editing API, if you need to use it, prefer +/// to create a type-safe abstraction on top of it instead. +pub fn replace_descendants( + parent: &SyntaxNode, + map: &FxHashMap, +) -> SyntaxNode { + // FIXME: this could be made much faster. + let new_children = parent.children_with_tokens().map(|it| go(map, it)).collect::>(); + return with_children(parent, new_children); + + fn go( + map: &FxHashMap, + element: SyntaxElement, + ) -> NodeOrToken { + if let Some(replacement) = map.get(&element) { + return match replacement { + NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()), + NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), + }; + } + match element { + NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), + NodeOrToken::Node(it) => { + NodeOrToken::Node(replace_descendants(&it, map).green().clone()) + } + } + } +} + fn with_children( parent: &SyntaxNode, new_children: Box<[NodeOrToken]>, diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index d3a375f87..5f7e9f5b1 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -373,6 +373,15 @@ impl ast::LifetimeParam { } } +impl ast::TypeParam { + pub fn colon_token(&self) -> Option { + self.syntax() + .children_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == T![:]) + } +} + impl ast::WherePred { pub fn lifetime_token(&self) -> Option { self.syntax() -- cgit v1.2.3