Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F401 Deletes import, cause EOF error #5156

Closed
Tracked by #4972
jasikpark opened this issue Jun 17, 2023 · 10 comments · Fixed by #5173
Closed
Tracked by #4972

F401 Deletes import, cause EOF error #5156

jasikpark opened this issue Jun 17, 2023 · 10 comments · Fixed by #5173
Labels
bug Something isn't working

Comments

@jasikpark
Copy link

jasikpark commented Jun 17, 2023

With this program:

##d####
\
import ost

(possibly importantly w/ the lack of a return character after ost

outputs this when run w/ --fix:

ruff artifacts/ruff_fix_validity/minimized-from-crash-dd75211301269fe8 --fix
warning: Detected debug build without --no-cache.
error: Autofix introduced a syntax error in `artifacts/ruff_fix_validity/minimized-from-crash-dd75211301269fe8` with rule codes F401: unexpected EOF while parsing at byte offset 11
---
##d####
\

---
artifacts/ruff_fix_validity/minimized-from-crash-dd75211301269fe8:3:8: F401 `ost` imported but unused
Found 1 error.

Found via #4822, run against main (be107da)

@charliermarsh charliermarsh added the bug Something isn't working label Jun 17, 2023
@charliermarsh
Copy link
Member

Yeah the general problem here is that a file can't end in a backslash, I think (even a newline is sufficient).

@jasikpark
Copy link
Author

Ah, thanks for the info, I was pretty bewildered by this xd

@jasikpark
Copy link
Author

I wonder what the right thing to do is when a simple change ends up with an incorrect program?

@charliermarsh
Copy link
Member

We should of course fix it, but it's worth noting that this is a fairly unlikely case to hit in the wild. Continuations themselves are relatively rare, and most editors don't even let you save a file without a trailing newline :)

@charliermarsh
Copy link
Member

I actually thought we did handle this case already:

pub(crate) fn delete_stmt(
    stmt: &Stmt,
    parent: Option<&Stmt>,
    locator: &Locator,
    indexer: &Indexer,
    stylist: &Stylist,
) -> Edit {
    if parent
        .map(|parent| is_lone_child(stmt, parent))
        .unwrap_or_default()
    {
        // If removing this node would lead to an invalid syntax tree, replace
        // it with a `pass`.
        Edit::range_replacement("pass".to_string(), stmt.range())
    } else {
        if let Some(semicolon) = trailing_semicolon(stmt, locator) {
            let next = next_stmt_break(semicolon, locator);
            Edit::deletion(stmt.start(), next)
        } else if helpers::has_leading_content(stmt, locator) {
            Edit::range_deletion(stmt.range())
        } else if helpers::preceded_by_continuation(stmt, indexer, locator) {
            if is_end_of_file(stmt, locator) && locator.is_at_start_of_line(stmt.start()) {
                // Special-case: a file can't end in a continuation.
                Edit::range_replacement(stylist.line_ending().to_string(), stmt.range())
            } else {
                Edit::range_deletion(stmt.range())
            }
        } else {
            let range = locator.full_lines_range(stmt.range());
            Edit::range_deletion(range)
        }
    }
}

Note the branch that says // Special-case: a file can't end in a continuation.. Need to look into that...

@charliermarsh
Copy link
Member

I think the safest and most general fix is to extend the deletion to include the continuation character itself.

@evanrittenhouse
Copy link
Contributor

evanrittenhouse commented Jun 17, 2023

Yeah the general problem here is that a file can't end in a backslash, I think (even a newline is sufficient).

I'm pretty sure that the trailing newline is what's causing a similar issue #4404. We attempt to strip the newline, then on the next iteration, the file ends in a \. I think the fix will rely on some combination of physical lines (Line) and Stmt, but not quite sure how to unify them yet.

@dhruvmanila
Copy link
Member

dhruvmanila commented Jun 18, 2023

Note the branch that says // Special-case: a file can't end in a continuation.. Need to look into that...

Did a quick debug, it turns out that specific continuation offset is not being stored here:

/// Stores the start offset of continuation lines.
continuation_lines: Vec<TextSize>,

This is happening as the logic is not considering a possibility of having a continuation character before the first token in file.

Edit: It seems to be happening whenever the continuation character is at the start of the line because these continuation offsets are not being considered:

\
import sys

\
import os

// Newlines after a newline never form a continuation.
if !matches!(
prev_token,
Some(Tok::Newline | Tok::NonLogicalNewline) | None
) {
continuation_lines.push(line_start);
}

The logic says that if the previous token is not a newline or not at the start, only then consider this for the continuation offset.

@charliermarsh
Copy link
Member

Is that only a start-of-file problem? I wonder if that match should allow None?

@dhruvmanila
Copy link
Member

Is that only a start-of-file problem? I wonder if that match should allow None?

No, sorry I updated the comment. It's occurring whenever the continuation character is at the start of line. This means the previous token was either a newline or None. The opposite of this condition is used to check whether to add the offset or not.

charliermarsh added a commit that referenced this issue Jun 19, 2023
## Summary

Given:

```python
\
import os
```

Deleting `import os` leaves a syntax error: a file can't end in a
continuation. We have code to handle this case, but it failed to pick up
continuations at the _very start_ of a file.

Closes #5156.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants