mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-04 07:35:49 +00:00
Do not insert imports before inner comments
This commit is contained in:
parent
99fa139bea
commit
335edf87bc
1 changed files with 92 additions and 18 deletions
|
@ -9,7 +9,7 @@ use syntax::{
|
||||||
edit::{AstNodeEdit, IndentLevel},
|
edit::{AstNodeEdit, IndentLevel},
|
||||||
make, AstNode, PathSegmentKind, VisibilityOwner,
|
make, AstNode, PathSegmentKind, VisibilityOwner,
|
||||||
},
|
},
|
||||||
InsertPosition, SyntaxElement, SyntaxNode,
|
AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
|
||||||
};
|
};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
|
@ -63,27 +63,46 @@ impl ImportScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_pos_after_inner_attribute(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
|
fn insert_pos_after_inner_elements(&self) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
|
||||||
// check if the scope has inner attributes, we dont want to insert in front of them
|
let mut last_inner_element = None;
|
||||||
match self
|
|
||||||
.as_syntax_node()
|
for maybe_inner_element in self.as_syntax_node().children_with_tokens() {
|
||||||
.children()
|
match maybe_inner_element {
|
||||||
// no flat_map here cause we want to short circuit the iterator
|
NodeOrToken::Node(maybe_inner_node) => {
|
||||||
.map(ast::Attr::cast)
|
if is_inner_node(maybe_inner_node.clone()) {
|
||||||
.take_while(|attr| {
|
last_inner_element = Some(NodeOrToken::Node(maybe_inner_node))
|
||||||
attr.as_ref().map(|attr| attr.kind() == ast::AttrKind::Inner).unwrap_or(false)
|
} else {
|
||||||
})
|
if let Some(maybe_inner_token) = maybe_inner_node.first_token() {
|
||||||
.last()
|
if is_inner_token(maybe_inner_token.clone()) {
|
||||||
.flatten()
|
last_inner_element = Some(NodeOrToken::Token(maybe_inner_token))
|
||||||
{
|
}
|
||||||
Some(attr) => {
|
}
|
||||||
(InsertPosition::After(attr.syntax().clone().into()), AddBlankLine::BeforeTwice)
|
};
|
||||||
|
}
|
||||||
|
NodeOrToken::Token(maybe_inner_token) => {
|
||||||
|
if is_inner_token(maybe_inner_token.clone()) {
|
||||||
|
last_inner_element = Some(NodeOrToken::Token(maybe_inner_token))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match last_inner_element {
|
||||||
|
Some(element) => (InsertPosition::After(element.into()), AddBlankLine::BeforeTwice),
|
||||||
None => self.first_insert_pos(),
|
None => self.first_insert_pos(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_inner_node(node: SyntaxNode) -> bool {
|
||||||
|
ast::Attr::cast(node).map(|attr| attr.kind()) == Some(ast::AttrKind::Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_inner_token(token: SyntaxToken) -> bool {
|
||||||
|
ast::Comment::cast(token).and_then(|comment| comment.kind().doc)
|
||||||
|
== Some(ast::CommentPlacement::Inner)
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
|
||||||
pub(crate) fn insert_use<'a>(
|
pub(crate) fn insert_use<'a>(
|
||||||
scope: &ImportScope,
|
scope: &ImportScope,
|
||||||
|
@ -558,7 +577,7 @@ fn find_insert_position(
|
||||||
(InsertPosition::After(node.into()), AddBlankLine::BeforeTwice)
|
(InsertPosition::After(node.into()), AddBlankLine::BeforeTwice)
|
||||||
}
|
}
|
||||||
// there are no imports in this file at all
|
// there are no imports in this file at all
|
||||||
None => scope.insert_pos_after_inner_attribute(),
|
None => scope.insert_pos_after_inner_elements(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -830,12 +849,67 @@ use foo::bar;",
|
||||||
"foo::bar",
|
"foo::bar",
|
||||||
r"#![allow(unused_imports)]
|
r"#![allow(unused_imports)]
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
fn main() {}",
|
fn main() {}",
|
||||||
r"#![allow(unused_imports)]
|
r"#![allow(unused_imports)]
|
||||||
|
|
||||||
use foo::bar;
|
#![no_std]
|
||||||
|
|
||||||
|
use foo::bar;
|
||||||
fn main() {}",
|
fn main() {}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inserts_after_single_line_inner_comments() {
|
||||||
|
check_none(
|
||||||
|
"foo::bar::Baz",
|
||||||
|
"//! Single line inner comments do not allow any code before them.",
|
||||||
|
r#"//! Single line inner comments do not allow any code before them.
|
||||||
|
|
||||||
|
use foo::bar::Baz;"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inserts_after_multiline_inner_comments() {
|
||||||
|
check_none(
|
||||||
|
"foo::bar::Baz",
|
||||||
|
r#"/*! Multiline inner comments do not allow any code before them. */
|
||||||
|
|
||||||
|
/*! RA considers this inner comment belonging to the function, yet we still cannot place the code before it. */
|
||||||
|
fn main() {}"#,
|
||||||
|
r#"/*! Multiline inner comments do not allow any code before them. */
|
||||||
|
|
||||||
|
/*! RA considers this inner comment belonging to the function, yet we still cannot place the code before it. */
|
||||||
|
|
||||||
|
use foo::bar::Baz;
|
||||||
|
fn main() {}"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inserts_after_all_inner_items() {
|
||||||
|
check_none(
|
||||||
|
"foo::bar::Baz",
|
||||||
|
r#"#![allow(unused_imports)]
|
||||||
|
/*! Multiline line comment 2 */
|
||||||
|
|
||||||
|
|
||||||
|
//! Single line comment 1
|
||||||
|
#![no_std]
|
||||||
|
//! Single line comment 2
|
||||||
|
fn main() {}"#,
|
||||||
|
r#"#![allow(unused_imports)]
|
||||||
|
/*! Multiline line comment 2 */
|
||||||
|
|
||||||
|
|
||||||
|
//! Single line comment 1
|
||||||
|
#![no_std]
|
||||||
|
//! Single line comment 2
|
||||||
|
|
||||||
|
use foo::bar::Baz;
|
||||||
|
fn main() {}"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue