Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #12545 - jeremyBanks:shebangs, r=Veykril
fix: inserted imports must come after a shebang if present
The current `insert_use` logic adds the first `use` item near the beginning of the file, only skipping past comments and whitespace. However, it does not skip leading [shebang lines](https://en.wikipedia.org/wiki/Shebang_\(Unix\)). This can produce a syntax error, as shebangs are only accepted (ignored) on the first line of the file.
### Before Insertion (valid syntax)
```rust
#!/usr/bin/env rust
fn main() {}
```
### After Insertion (invalid syntax)
```rust
use foo::bar::Baz;
#!/usr/bin/env rust
fn main() {}
```
Rust analyzer's grammar is already shebang-aware, so this PR just adds that to the array of SyntaxKinds that are skipped past when looking for an insertion location, and adds a corresponding test case.
| -rw-r--r-- | crates/ide-db/src/imports/insert_use.rs | 3 | ||||
| -rw-r--r-- | crates/ide-db/src/imports/insert_use/tests.rs | 11 |
2 files changed, 13 insertions, 1 deletions
diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 66d0b2ee82..d1cd347819 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -403,7 +403,8 @@ fn insert_use_( .take_while(|child| match child { NodeOrToken::Node(node) => is_inner_attribute(node.clone()), NodeOrToken::Token(token) => { - [SyntaxKind::WHITESPACE, SyntaxKind::COMMENT].contains(&token.kind()) + [SyntaxKind::WHITESPACE, SyntaxKind::COMMENT, SyntaxKind::SHEBANG] + .contains(&token.kind()) } }) .filter(|child| child.as_token().map_or(true, |t| t.kind() != SyntaxKind::WHITESPACE)) diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs index 6569e4ed8c..70a7a15232 100644 --- a/crates/ide-db/src/imports/insert_use/tests.rs +++ b/crates/ide-db/src/imports/insert_use/tests.rs @@ -455,6 +455,17 @@ use foo::bar::Baz;"#, } #[test] +fn inserts_after_shebang() { + check_none( + "foo::bar::Baz", + "#!/usr/bin/env rust", + r#"#!/usr/bin/env rust + +use foo::bar::Baz;"#, + ); +} + +#[test] fn inserts_after_multiple_single_line_comments() { check_none( "foo::bar::Baz", |