From 03b77b03fefa4dc260b5a63223db253706d41ca8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 14 Oct 2020 01:39:58 +0200 Subject: Fix stackoverflow in insert_use::recursive_merge --- crates/assists/src/handlers/merge_imports.rs | 14 +++++++++++++ .../handlers/replace_qualified_name_with_use.rs | 17 +++++++++++++++ crates/assists/src/utils/insert_use.rs | 24 ++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) (limited to 'crates/assists') diff --git a/crates/assists/src/handlers/merge_imports.rs b/crates/assists/src/handlers/merge_imports.rs index fe33cee53..fd9c9e03c 100644 --- a/crates/assists/src/handlers/merge_imports.rs +++ b/crates/assists/src/handlers/merge_imports.rs @@ -72,6 +72,20 @@ mod tests { use super::*; + #[test] + fn test_merge_equal() { + check_assist( + merge_imports, + r" +use std::fmt<|>::{Display, Debug}; +use std::fmt::{Display, Debug}; +", + r" +use std::fmt::{Debug, Display}; +", + ) + } + #[test] fn test_merge_first() { check_assist( diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs index e95b971a4..c50bc7604 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs @@ -123,6 +123,23 @@ mod tests { use super::*; + #[test] + fn test_replace_already_imported() { + check_assist( + replace_qualified_name_with_use, + r"use std::fs; + +fn main() { + std::f<|>s::Path +}", + r"use std::fs; + +fn main() { + fs::Path +}", + ) + } + #[test] fn test_replace_add_use_no_anchor() { check_assist( diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index bfd457d18..409985b3b 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs @@ -173,8 +173,15 @@ pub(crate) fn try_merge_trees( let rhs_path = rhs.path()?; let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; - let lhs = lhs.split_prefix(&lhs_prefix); - let rhs = rhs.split_prefix(&rhs_prefix); + let (lhs, rhs) = if is_simple_path(lhs) + && is_simple_path(rhs) + && lhs_path == lhs_prefix + && rhs_path == rhs_prefix + { + (lhs.clone(), rhs.clone()) + } else { + (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix)) + }; recursive_merge(&lhs, &rhs, merge) } @@ -250,6 +257,10 @@ fn recursive_merge( use_trees.insert(idx, make::glob_use_tree()); continue; } + + if lhs_t.use_tree_list().is_none() && rhs_t.use_tree_list().is_none() { + continue; + } } let lhs = lhs_t.split_prefix(&lhs_prefix); let rhs = rhs_t.split_prefix(&rhs_prefix); @@ -295,6 +306,10 @@ fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Pa } } +fn is_simple_path(use_tree: &ast::UseTree) -> bool { + use_tree.use_tree_list().is_none() && use_tree.star_token().is_none() +} + fn path_is_self(path: &ast::Path) -> bool { path.segment().and_then(|seg| seg.self_token()).is_some() && path.qualifier().is_none() } @@ -523,6 +538,11 @@ mod tests { use test_utils::assert_eq_text; + #[test] + fn insert_existing() { + check_full("std::fs", "use std::fs;", "use std::fs;") + } + #[test] fn insert_start() { check_none( -- cgit v1.2.3