diff options
-rw-r--r-- | crates/ide_assists/src/handlers/merge_imports.rs | 14 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/merge_imports.rs | 15 | ||||
-rw-r--r-- | crates/stdx/src/lib.rs | 28 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 23 |
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" | ||
220 | pub(in this::path) use std::fmt$0::Debug; | ||
221 | pub(in this::path) use std::fmt::Display; | ||
222 | ", | ||
223 | r" | ||
224 | pub(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 { | |||
292 | pub fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool { | 292 | pub 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 | ||
311 | fn path_is_self(path: &ast::Path) -> bool { | 314 | fn 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 | ||
145 | pub fn iter_eq_by<I, I2, F>(this: I2, other: I, mut eq: F) -> bool | ||
146 | where | ||
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)] |
144 | mod tests { | 172 | mod 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 | ||
613 | impl ast::LifetimeParam { | 636 | impl ast::LifetimeParam { |