aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_assists/src/handlers/merge_imports.rs14
-rw-r--r--crates/ide_db/src/helpers/merge_imports.rs15
-rw-r--r--crates/stdx/src/lib.rs28
-rw-r--r--crates/syntax/src/ast/node_ext.rs23
4 files changed, 74 insertions, 6 deletions
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs
index 31854840c..fc117bd9a 100644
--- a/crates/ide_assists/src/handlers/merge_imports.rs
+++ b/crates/ide_assists/src/handlers/merge_imports.rs
@@ -213,6 +213,20 @@ pub(crate) use std::fmt::{Debug, Display};
213 } 213 }
214 214
215 #[test] 215 #[test]
216 fn merge_pub_in_path_crate() {
217 check_assist(
218 merge_imports,
219 r"
220pub(in this::path) use std::fmt$0::Debug;
221pub(in this::path) use std::fmt::Display;
222",
223 r"
224pub(in this::path) use std::fmt::{Debug, Display};
225",
226 )
227 }
228
229 #[test]
216 fn test_merge_nested() { 230 fn test_merge_nested() {
217 check_assist( 231 check_assist(
218 merge_imports, 232 merge_imports,
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs
index 697e8bcff..0dbabb44f 100644
--- a/crates/ide_db/src/helpers/merge_imports.rs
+++ b/crates/ide_db/src/helpers/merge_imports.rs
@@ -292,9 +292,7 @@ fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering {
292pub fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool { 292pub fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool {
293 match (vis0, vis1) { 293 match (vis0, vis1) {
294 (None, None) => true, 294 (None, None) => true,
295 // FIXME: Don't use the string representation to check for equality 295 (Some(vis0), Some(vis1)) => vis0.is_eq_to(&vis1),
296 // spaces inside of the node would break this comparison
297 (Some(vis0), Some(vis1)) => vis0.to_string() == vis1.to_string(),
298 _ => false, 296 _ => false,
299 } 297 }
300} 298}
@@ -303,9 +301,14 @@ pub fn eq_attrs(
303 attrs0: impl Iterator<Item = ast::Attr>, 301 attrs0: impl Iterator<Item = ast::Attr>,
304 attrs1: impl Iterator<Item = ast::Attr>, 302 attrs1: impl Iterator<Item = ast::Attr>,
305) -> bool { 303) -> bool {
306 let attrs0 = attrs0.map(|attr| attr.to_string()); 304 // FIXME order of attributes should not matter
307 let attrs1 = attrs1.map(|attr| attr.to_string()); 305 let attrs0 = attrs0
308 attrs0.eq(attrs1) 306 .flat_map(|attr| attr.syntax().descendants_with_tokens())
307 .flat_map(|it| it.into_token());
308 let attrs1 = attrs1
309 .flat_map(|attr| attr.syntax().descendants_with_tokens())
310 .flat_map(|it| it.into_token());
311 stdx::iter_eq_by(attrs0, attrs1, |tok, tok2| tok.text() == tok2.text())
309} 312}
310 313
311fn path_is_self(path: &ast::Path) -> bool { 314fn path_is_self(path: &ast::Path) -> bool {
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 340fcacfa..18d5fadb9 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -140,6 +140,34 @@ impl JodChild {
140 } 140 }
141} 141}
142 142
143// feature: iter_order_by
144// Iterator::eq_by
145pub fn iter_eq_by<I, I2, F>(this: I2, other: I, mut eq: F) -> bool
146where
147 I: IntoIterator,
148 I2: IntoIterator,
149 F: FnMut(I2::Item, I::Item) -> bool,
150{
151 let mut other = other.into_iter();
152 let mut this = this.into_iter();
153
154 loop {
155 let x = match this.next() {
156 None => return other.next().is_none(),
157 Some(val) => val,
158 };
159
160 let y = match other.next() {
161 None => return false,
162 Some(val) => val,
163 };
164
165 if !eq(x, y) {
166 return false;
167 }
168 }
169}
170
143#[cfg(test)] 171#[cfg(test)]
144mod tests { 172mod tests {
145 use super::*; 173 use super::*;
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index bef49238f..df8f98b5b 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -608,6 +608,29 @@ impl ast::Visibility {
608 None => VisibilityKind::Pub, 608 None => VisibilityKind::Pub,
609 } 609 }
610 } 610 }
611
612 pub fn is_eq_to(&self, other: &Self) -> bool {
613 match (self.kind(), other.kind()) {
614 (VisibilityKind::In(this), VisibilityKind::In(other)) => {
615 stdx::iter_eq_by(this.segments(), other.segments(), |lhs, rhs| {
616 lhs.kind().zip(rhs.kind()).map_or(false, |it| match it {
617 (PathSegmentKind::CrateKw, PathSegmentKind::CrateKw)
618 | (PathSegmentKind::SelfKw, PathSegmentKind::SelfKw)
619 | (PathSegmentKind::SuperKw, PathSegmentKind::SuperKw) => true,
620 (PathSegmentKind::Name(lhs), PathSegmentKind::Name(rhs)) => {
621 lhs.text() == rhs.text()
622 }
623 _ => false,
624 })
625 })
626 }
627 (VisibilityKind::PubSelf, VisibilityKind::PubSelf)
628 | (VisibilityKind::PubSuper, VisibilityKind::PubSuper)
629 | (VisibilityKind::PubCrate, VisibilityKind::PubCrate)
630 | (VisibilityKind::Pub, VisibilityKind::Pub) => true,
631 _ => false,
632 }
633 }
611} 634}
612 635
613impl ast::LifetimeParam { 636impl ast::LifetimeParam {