Skip to content

Commit e3227bd

Browse files
Merge #6529
6529: Do not insert imports before inner comments r=Veykril a=SomeoneToIgnore Co-authored-by: Kirill Bulatov <[email protected]>
2 parents 99fa139 + 07e633e commit e3227bd

File tree

1 file changed

+77
-19
lines changed

1 file changed

+77
-19
lines changed

crates/assists/src/utils/insert_use.rs

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use syntax::{
99
edit::{AstNodeEdit, IndentLevel},
1010
make, AstNode, PathSegmentKind, VisibilityOwner,
1111
},
12-
InsertPosition, SyntaxElement, SyntaxNode,
12+
AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
1313
};
1414
use test_utils::mark;
1515

@@ -63,27 +63,30 @@ impl ImportScope {
6363
}
6464
}
6565

66-
fn insert_pos_after_inner_attribute(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
67-
// check if the scope has inner attributes, we dont want to insert in front of them
68-
match self
69-
.as_syntax_node()
70-
.children()
71-
// no flat_map here cause we want to short circuit the iterator
72-
.map(ast::Attr::cast)
73-
.take_while(|attr| {
74-
attr.as_ref().map(|attr| attr.kind() == ast::AttrKind::Inner).unwrap_or(false)
66+
fn insert_pos_after_last_inner_element(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
67+
self.as_syntax_node()
68+
.children_with_tokens()
69+
.filter(|child| match child {
70+
NodeOrToken::Node(node) => is_inner_attribute(node.clone()),
71+
NodeOrToken::Token(token) => is_inner_comment(token.clone()),
7572
})
7673
.last()
77-
.flatten()
78-
{
79-
Some(attr) => {
80-
(InsertPosition::After(attr.syntax().clone().into()), AddBlankLine::BeforeTwice)
81-
}
82-
None => self.first_insert_pos(),
83-
}
74+
.map(|last_inner_element| {
75+
(InsertPosition::After(last_inner_element.into()), AddBlankLine::BeforeTwice)
76+
})
77+
.unwrap_or_else(|| self.first_insert_pos())
8478
}
8579
}
8680

81+
fn is_inner_attribute(node: SyntaxNode) -> bool {
82+
ast::Attr::cast(node).map(|attr| attr.kind()) == Some(ast::AttrKind::Inner)
83+
}
84+
85+
fn is_inner_comment(token: SyntaxToken) -> bool {
86+
ast::Comment::cast(token).and_then(|comment| comment.kind().doc)
87+
== Some(ast::CommentPlacement::Inner)
88+
}
89+
8790
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
8891
pub(crate) fn insert_use<'a>(
8992
scope: &ImportScope,
@@ -558,7 +561,7 @@ fn find_insert_position(
558561
(InsertPosition::After(node.into()), AddBlankLine::BeforeTwice)
559562
}
560563
// there are no imports in this file at all
561-
None => scope.insert_pos_after_inner_attribute(),
564+
None => scope.insert_pos_after_last_inner_element(),
562565
},
563566
}
564567
}
@@ -830,12 +833,67 @@ use foo::bar;",
830833
"foo::bar",
831834
r"#![allow(unused_imports)]
832835
836+
#![no_std]
833837
fn main() {}",
834838
r"#![allow(unused_imports)]
835839
836-
use foo::bar;
840+
#![no_std]
837841
842+
use foo::bar;
838843
fn main() {}",
844+
);
845+
}
846+
847+
#[test]
848+
fn inserts_after_single_line_inner_comments() {
849+
check_none(
850+
"foo::bar::Baz",
851+
"//! Single line inner comments do not allow any code before them.",
852+
r#"//! Single line inner comments do not allow any code before them.
853+
854+
use foo::bar::Baz;"#,
855+
);
856+
}
857+
858+
#[test]
859+
fn inserts_after_multiline_inner_comments() {
860+
check_none(
861+
"foo::bar::Baz",
862+
r#"/*! Multiline inner comments do not allow any code before them. */
863+
864+
/*! Still an inner comment, cannot place any code before. */
865+
fn main() {}"#,
866+
r#"/*! Multiline inner comments do not allow any code before them. */
867+
868+
/*! Still an inner comment, cannot place any code before. */
869+
870+
use foo::bar::Baz;
871+
fn main() {}"#,
872+
)
873+
}
874+
875+
#[test]
876+
fn inserts_after_all_inner_items() {
877+
check_none(
878+
"foo::bar::Baz",
879+
r#"#![allow(unused_imports)]
880+
/*! Multiline line comment 2 */
881+
882+
883+
//! Single line comment 1
884+
#![no_std]
885+
//! Single line comment 2
886+
fn main() {}"#,
887+
r#"#![allow(unused_imports)]
888+
/*! Multiline line comment 2 */
889+
890+
891+
//! Single line comment 1
892+
#![no_std]
893+
//! Single line comment 2
894+
895+
use foo::bar::Baz;
896+
fn main() {}"#,
839897
)
840898
}
841899

0 commit comments

Comments
 (0)