Skip to content

Commit 0650f77

Browse files
committed
internal: remove one more immutable tree
1 parent ab528e8 commit 0650f77

File tree

7 files changed

+57
-56
lines changed

7 files changed

+57
-56
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ide_db/src/helpers/merge_imports.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
use std::cmp::Ordering;
33

44
use itertools::{EitherOrBoth, Itertools};
5-
use syntax::ast::{
6-
self, edit::AstNodeEdit, make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner,
5+
use syntax::{
6+
ast::{self, make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner},
7+
ted,
78
};
89

910
/// What type of merges are allowed.
@@ -65,7 +66,7 @@ pub fn try_merge_trees(
6566
} else {
6667
(lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix))
6768
};
68-
recursive_merge(&lhs, &rhs, merge)
69+
recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update())
6970
}
7071

7172
/// Recursively "zips" together lhs and rhs.
@@ -78,7 +79,8 @@ fn recursive_merge(
7879
.use_tree_list()
7980
.into_iter()
8081
.flat_map(|list| list.use_trees())
81-
// we use Option here to early return from this function(this is not the same as a `filter` op)
82+
// We use Option here to early return from this function(this is not the
83+
// same as a `filter` op).
8284
.map(|tree| match merge.is_tree_allowed(&tree) {
8385
true => Some(tree),
8486
false => None,
@@ -111,8 +113,10 @@ fn recursive_merge(
111113
let tree_is_self = |tree: ast::UseTree| {
112114
tree.path().as_ref().map(path_is_self).unwrap_or(false)
113115
};
114-
// check if only one of the two trees has a tree list, and whether that then contains `self` or not.
115-
// If this is the case we can skip this iteration since the path without the list is already included in the other one via `self`
116+
// Check if only one of the two trees has a tree list, and
117+
// whether that then contains `self` or not. If this is the
118+
// case we can skip this iteration since the path without
119+
// the list is already included in the other one via `self`.
116120
let tree_contains_self = |tree: &ast::UseTree| {
117121
tree.use_tree_list()
118122
.map(|tree_list| tree_list.use_trees().any(tree_is_self))
@@ -127,9 +131,11 @@ fn recursive_merge(
127131
_ => (),
128132
}
129133

130-
// glob imports arent part of the use-tree lists so we need to special handle them here as well
131-
// this special handling is only required for when we merge a module import into a glob import of said module
132-
// see the `merge_self_glob` or `merge_mod_into_glob` tests
134+
// Glob imports aren't part of the use-tree lists so we need
135+
// to special handle them here as well this special handling
136+
// is only required for when we merge a module import into a
137+
// glob import of said module see the `merge_self_glob` or
138+
// `merge_mod_into_glob` tests.
133139
if lhs_t.star_token().is_some() || rhs_t.star_token().is_some() {
134140
*lhs_t = make::use_tree(
135141
make::path_unqualified(make::path_segment_self()),
@@ -165,11 +171,11 @@ fn recursive_merge(
165171
}
166172
}
167173

168-
Some(if let Some(old) = lhs.use_tree_list() {
169-
lhs.replace_descendant(old, make::use_tree_list(use_trees)).clone_for_update()
170-
} else {
171-
lhs.clone()
172-
})
174+
let lhs = lhs.clone_subtree().clone_for_update();
175+
if let Some(old) = lhs.use_tree_list() {
176+
ted::replace(old.syntax(), make::use_tree_list(use_trees).syntax().clone_for_update());
177+
}
178+
ast::UseTree::cast(lhs.syntax().clone_subtree())
173179
}
174180

175181
/// Traverses both paths until they differ, returning the common prefix of both.

crates/syntax/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ doctest = false
1313
[dependencies]
1414
cov-mark = { version = "1.1", features = ["thread-local"] }
1515
itertools = "0.10.0"
16-
rowan = "=0.13.0-pre.5"
16+
rowan = "=0.13.0-pre.6"
1717
rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" }
1818
rustc-hash = "1.1.0"
1919
arrayvec = "0.7"

crates/syntax/src/algo.rs

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ enum InsertPos {
337337
}
338338

339339
#[derive(Default)]
340-
pub struct SyntaxRewriter<'a> {
340+
pub(crate) struct SyntaxRewriter<'a> {
341341
//FIXME: add debug_assertions that all elements are in fact from the same file.
342342
replacements: FxHashMap<SyntaxElement, Replacement>,
343343
insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
@@ -354,13 +354,13 @@ impl fmt::Debug for SyntaxRewriter<'_> {
354354
}
355355

356356
impl SyntaxRewriter<'_> {
357-
pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
357+
pub(crate) fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
358358
let what = what.clone().into();
359359
let replacement = Replacement::Single(with.clone().into());
360360
self.replacements.insert(what, replacement);
361361
}
362362

363-
pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
363+
pub(crate) fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
364364
let _p = profile::span("rewrite");
365365

366366
if self.replacements.is_empty() && self.insertions.is_empty() {
@@ -370,37 +370,10 @@ impl SyntaxRewriter<'_> {
370370
with_green(node, green)
371371
}
372372

373-
pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
373+
pub(crate) fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
374374
N::cast(self.rewrite(node.syntax())).unwrap()
375375
}
376376

377-
/// Returns a node that encompasses all replacements to be done by this rewriter.
378-
///
379-
/// Passing the returned node to `rewrite` will apply all replacements queued up in `self`.
380-
///
381-
/// Returns `None` when there are no replacements.
382-
pub fn rewrite_root(&self) -> Option<SyntaxNode> {
383-
let _p = profile::span("rewrite_root");
384-
fn element_to_node_or_parent(element: &SyntaxElement) -> Option<SyntaxNode> {
385-
match element {
386-
SyntaxElement::Node(it) => Some(it.clone()),
387-
SyntaxElement::Token(it) => it.parent(),
388-
}
389-
}
390-
391-
self.replacements
392-
.keys()
393-
.filter_map(element_to_node_or_parent)
394-
.chain(self.insertions.keys().filter_map(|pos| match pos {
395-
InsertPos::FirstChildOf(it) => Some(it.clone()),
396-
InsertPos::After(it) => element_to_node_or_parent(it),
397-
}))
398-
// If we only have one replacement/insertion, we must return its parent node, since `rewrite` does
399-
// not replace the node passed to it.
400-
.map(|it| it.parent().unwrap_or(it))
401-
.fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
402-
}
403-
404377
fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> {
405378
self.replacements.get(element).cloned()
406379
}

crates/syntax/src/ast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ pub trait AstNode {
4747
{
4848
Self::cast(self.syntax().clone_for_update()).unwrap()
4949
}
50+
fn clone_subtree(&self) -> Self
51+
where
52+
Self: Sized,
53+
{
54+
Self::cast(self.syntax().clone_subtree()).unwrap()
55+
}
5056
}
5157

5258
/// Like `AstNode`, but wraps tokens rather than interior nodes.

crates/syntax/src/ast/make.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use itertools::Itertools;
1313
use stdx::{format_to, never};
1414

15-
use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
15+
use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxToken};
1616

1717
/// While the parent module defines basic atomic "constructors", the `ext`
1818
/// module defines shortcuts for common things.
@@ -601,17 +601,11 @@ fn ast_from_text<N: AstNode>(text: &str) -> N {
601601
panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text)
602602
}
603603
};
604-
let node = node.syntax().clone();
605-
let node = unroot(node);
606-
let node = N::cast(node).unwrap();
604+
let node = node.clone_subtree();
607605
assert_eq!(node.syntax().text_range().start(), 0.into());
608606
node
609607
}
610608

611-
fn unroot(n: SyntaxNode) -> SyntaxNode {
612-
SyntaxNode::new_root(n.green().into())
613-
}
614-
615609
pub fn token(kind: SyntaxKind) -> SyntaxToken {
616610
tokens::SOURCE_FILE
617611
.tree()

docs/dev/style.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,28 @@ match p.current() {
951951

952952
## Documentation
953953

954+
Style inline code comments as proper sentences.
955+
Start with a capital letter, end with a dot.
956+
957+
```rust
958+
// GOOD
959+
960+
// Only simple single segment paths are allowed.
961+
MergeBehavior::Last => {
962+
tree.use_tree_list().is_none() && tree.path().map(path_len) <= Some(1)
963+
}
964+
965+
// BAD
966+
967+
// only simple single segment paths are allowed
968+
MergeBehavior::Last => {
969+
tree.use_tree_list().is_none() && tree.path().map(path_len) <= Some(1)
970+
}
971+
```
972+
973+
**Rationale:** writing a sentence (or maybe even a paragraph) rather just "a comment" creates a more appropriate frame of mind.
974+
It tricks you into writing down more of the context you keep in your head while coding.
975+
954976
For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines.
955977
If the line is too long, you want to split the sentence in two :-)
956978

0 commit comments

Comments
 (0)