Skip to content

Commit 134355e

Browse files
authored
Improved the fix for the continuing problem in the shell (RustPython#4406)
1 parent 144f619 commit 134355e

File tree

1 file changed

+26
-33
lines changed

1 file changed

+26
-33
lines changed

src/shell.rs

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
mod helper;
22

3-
use rustpython_parser::error::{LexicalErrorType, ParseErrorType};
3+
use rustpython_parser::{
4+
error::{LexicalErrorType, ParseErrorType},
5+
token::Tok,
6+
};
47
use rustpython_vm::{
58
builtins::PyBaseExceptionRef,
69
compiler::{self, CompileError, CompileErrorBody, CompileErrorType},
@@ -19,15 +22,13 @@ fn shell_exec(
1922
vm: &VirtualMachine,
2023
source: &str,
2124
scope: Scope,
22-
last_row: &mut usize,
2325
empty_line_given: bool,
2426
continuing: bool,
2527
) -> ShellExecResult {
2628
match vm.compile(source, compiler::Mode::Single, "<stdin>".to_owned()) {
2729
Ok(code) => {
2830
if empty_line_given || !continuing {
2931
// We want to execute the full code
30-
*last_row = 0;
3132
match vm.run_code_obj(code, scope) {
3233
Ok(_val) => ShellExecResult::Ok,
3334
Err(err) => ShellExecResult::PyErr(err),
@@ -54,28 +55,30 @@ fn shell_exec(
5455
..
5556
}) => ShellExecResult::Continue,
5657
Err(err) => {
57-
// Indent error or something else?
58-
let indent_error = match err.body.error {
59-
CompileErrorType::Parse(ref p) => p.is_indentation_error(),
60-
_ => false,
58+
// bad_error == true if we are handling an error that should be thrown even if we are continuing
59+
// if its an indentation error, set to true if we are continuing and the error is on column 0,
60+
// since indentations errors on columns other than 0 should be ignored.
61+
// if its an unrecognized token for dedent, set to false
62+
63+
let bad_error = match err.body.error {
64+
CompileErrorType::Parse(ref p) => {
65+
if matches!(
66+
p,
67+
ParseErrorType::Lexical(LexicalErrorType::IndentationError)
68+
) {
69+
continuing && err.body.location.column() != 0
70+
} else {
71+
!matches!(p, ParseErrorType::UnrecognizedToken(Tok::Dedent, _))
72+
}
73+
}
74+
_ => true, // It is a bad error for everything else
6175
};
6276

63-
if indent_error && !empty_line_given {
64-
// The input line is not empty and it threw an indentation error
65-
let l = err.body.location;
66-
67-
// This is how we can mask unnecesary errors
68-
if l.row() > *last_row {
69-
*last_row = l.row();
70-
ShellExecResult::Continue
71-
} else {
72-
*last_row = 0;
73-
ShellExecResult::PyErr(vm.new_syntax_error(&err))
74-
}
75-
} else {
76-
// Throw the error for all other cases
77-
*last_row = 0;
77+
// If we are handling an error on an empty line or an error worthy of throwing
78+
if empty_line_given || bad_error {
7879
ShellExecResult::PyErr(vm.new_syntax_error(&err))
80+
} else {
81+
ShellExecResult::Continue
7982
}
8083
}
8184
}
@@ -100,7 +103,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
100103
}
101104

102105
let mut continuing = false;
103-
let mut last_row: usize = 0;
104106

105107
loop {
106108
let prompt_name = if continuing { "ps2" } else { "ps1" };
@@ -128,14 +130,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
128130
}
129131
full_input.push('\n');
130132

131-
match shell_exec(
132-
vm,
133-
&full_input,
134-
scope.clone(),
135-
&mut last_row,
136-
empty_line_given,
137-
continuing,
138-
) {
133+
match shell_exec(vm, &full_input, scope.clone(), empty_line_given, continuing) {
139134
ShellExecResult::Ok => {
140135
if continuing {
141136
if empty_line_given {
@@ -150,7 +145,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
150145
}
151146
} else {
152147
// We aren't in continue mode so proceed normally
153-
last_row = 0;
154148
continuing = false;
155149
full_input.clear();
156150
Ok(())
@@ -168,7 +162,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
168162
}
169163
}
170164
ReadlineResult::Interrupt => {
171-
last_row = 0;
172165
continuing = false;
173166
full_input.clear();
174167
let keyboard_interrupt =

0 commit comments

Comments
 (0)