]> git.lizzy.rs Git - rust.git/commitdiff
Don't compare ast::Visibility by stringifying
authorLukas Tobias Wirth <lukastw97@gmail.com>
Thu, 20 May 2021 15:27:51 +0000 (17:27 +0200)
committerLukas Tobias Wirth <lukastw97@gmail.com>
Thu, 20 May 2021 15:45:59 +0000 (17:45 +0200)
crates/ide_assists/src/handlers/merge_imports.rs
crates/ide_db/src/helpers/merge_imports.rs
crates/stdx/src/lib.rs
crates/syntax/src/ast/node_ext.rs

index 31854840c22d345d69e345f2053a9747b3091fe6..fc117bd9a8469c6eb676977512eac5bd1211ca10 100644 (file)
@@ -212,6 +212,20 @@ fn merge_pub_crate() {
         )
     }
 
+    #[test]
+    fn merge_pub_in_path_crate() {
+        check_assist(
+            merge_imports,
+            r"
+pub(in this::path) use std::fmt$0::Debug;
+pub(in this::path) use std::fmt::Display;
+",
+            r"
+pub(in this::path) use std::fmt::{Debug, Display};
+",
+        )
+    }
+
     #[test]
     fn test_merge_nested() {
         check_assist(
index 697e8bcffa90024734d5938eba5ccf79c046d513..0dbabb44fba674986575f3b9fd2b0495aecc29b5 100644 (file)
@@ -292,9 +292,7 @@ fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering {
 pub fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -> bool {
     match (vis0, vis1) {
         (None, None) => true,
-        // FIXME: Don't use the string representation to check for equality
-        // spaces inside of the node would break this comparison
-        (Some(vis0), Some(vis1)) => vis0.to_string() == vis1.to_string(),
+        (Some(vis0), Some(vis1)) => vis0.is_eq_to(&vis1),
         _ => false,
     }
 }
@@ -303,9 +301,14 @@ pub fn eq_attrs(
     attrs0: impl Iterator<Item = ast::Attr>,
     attrs1: impl Iterator<Item = ast::Attr>,
 ) -> bool {
-    let attrs0 = attrs0.map(|attr| attr.to_string());
-    let attrs1 = attrs1.map(|attr| attr.to_string());
-    attrs0.eq(attrs1)
+    // FIXME order of attributes should not matter
+    let attrs0 = attrs0
+        .flat_map(|attr| attr.syntax().descendants_with_tokens())
+        .flat_map(|it| it.into_token());
+    let attrs1 = attrs1
+        .flat_map(|attr| attr.syntax().descendants_with_tokens())
+        .flat_map(|it| it.into_token());
+    stdx::iter_eq_by(attrs0, attrs1, |tok, tok2| tok.text() == tok2.text())
 }
 
 fn path_is_self(path: &ast::Path) -> bool {
index 340fcacfa3fa05f1e1ee265471f3412b15684770..18d5fadb9c52a428aa5d2bc80bee5ef9ea7676c1 100644 (file)
@@ -140,6 +140,34 @@ pub fn into_inner(self) -> std::process::Child {
     }
 }
 
+// feature: iter_order_by
+// Iterator::eq_by
+pub fn iter_eq_by<I, I2, F>(this: I2, other: I, mut eq: F) -> bool
+where
+    I: IntoIterator,
+    I2: IntoIterator,
+    F: FnMut(I2::Item, I::Item) -> bool,
+{
+    let mut other = other.into_iter();
+    let mut this = this.into_iter();
+
+    loop {
+        let x = match this.next() {
+            None => return other.next().is_none(),
+            Some(val) => val,
+        };
+
+        let y = match other.next() {
+            None => return false,
+            Some(val) => val,
+        };
+
+        if !eq(x, y) {
+            return false;
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
index bef49238f578374cafcc43e5a3150858ce60c64c..df8f98b5b5f50448d1011c97459501ff066f9b79 100644 (file)
@@ -608,6 +608,29 @@ pub fn kind(&self) -> VisibilityKind {
             None => VisibilityKind::Pub,
         }
     }
+
+    pub fn is_eq_to(&self, other: &Self) -> bool {
+        match (self.kind(), other.kind()) {
+            (VisibilityKind::In(this), VisibilityKind::In(other)) => {
+                stdx::iter_eq_by(this.segments(), other.segments(), |lhs, rhs| {
+                    lhs.kind().zip(rhs.kind()).map_or(false, |it| match it {
+                        (PathSegmentKind::CrateKw, PathSegmentKind::CrateKw)
+                        | (PathSegmentKind::SelfKw, PathSegmentKind::SelfKw)
+                        | (PathSegmentKind::SuperKw, PathSegmentKind::SuperKw) => true,
+                        (PathSegmentKind::Name(lhs), PathSegmentKind::Name(rhs)) => {
+                            lhs.text() == rhs.text()
+                        }
+                        _ => false,
+                    })
+                })
+            }
+            (VisibilityKind::PubSelf, VisibilityKind::PubSelf)
+            | (VisibilityKind::PubSuper, VisibilityKind::PubSuper)
+            | (VisibilityKind::PubCrate, VisibilityKind::PubCrate)
+            | (VisibilityKind::Pub, VisibilityKind::Pub) => true,
+            _ => false,
+        }
+    }
 }
 
 impl ast::LifetimeParam {