forked from Rust-related/RustPython
Improved the fix for the continuing problem in the shell (#4406)
This commit is contained in:
59
src/shell.rs
59
src/shell.rs
@@ -1,6 +1,9 @@
|
||||
mod helper;
|
||||
|
||||
use rustpython_parser::error::{LexicalErrorType, ParseErrorType};
|
||||
use rustpython_parser::{
|
||||
error::{LexicalErrorType, ParseErrorType},
|
||||
token::Tok,
|
||||
};
|
||||
use rustpython_vm::{
|
||||
builtins::PyBaseExceptionRef,
|
||||
compiler::{self, CompileError, CompileErrorBody, CompileErrorType},
|
||||
@@ -19,7 +22,6 @@ fn shell_exec(
|
||||
vm: &VirtualMachine,
|
||||
source: &str,
|
||||
scope: Scope,
|
||||
last_row: &mut usize,
|
||||
empty_line_given: bool,
|
||||
continuing: bool,
|
||||
) -> ShellExecResult {
|
||||
@@ -27,7 +29,6 @@ fn shell_exec(
|
||||
Ok(code) => {
|
||||
if empty_line_given || !continuing {
|
||||
// We want to execute the full code
|
||||
*last_row = 0;
|
||||
match vm.run_code_obj(code, scope) {
|
||||
Ok(_val) => ShellExecResult::Ok,
|
||||
Err(err) => ShellExecResult::PyErr(err),
|
||||
@@ -54,28 +55,30 @@ fn shell_exec(
|
||||
..
|
||||
}) => ShellExecResult::Continue,
|
||||
Err(err) => {
|
||||
// Indent error or something else?
|
||||
let indent_error = match err.body.error {
|
||||
CompileErrorType::Parse(ref p) => p.is_indentation_error(),
|
||||
_ => false,
|
||||
// bad_error == true if we are handling an error that should be thrown even if we are continuing
|
||||
// if its an indentation error, set to true if we are continuing and the error is on column 0,
|
||||
// since indentations errors on columns other than 0 should be ignored.
|
||||
// if its an unrecognized token for dedent, set to false
|
||||
|
||||
let bad_error = match err.body.error {
|
||||
CompileErrorType::Parse(ref p) => {
|
||||
if matches!(
|
||||
p,
|
||||
ParseErrorType::Lexical(LexicalErrorType::IndentationError)
|
||||
) {
|
||||
continuing && err.body.location.column() != 0
|
||||
} else {
|
||||
!matches!(p, ParseErrorType::UnrecognizedToken(Tok::Dedent, _))
|
||||
}
|
||||
}
|
||||
_ => true, // It is a bad error for everything else
|
||||
};
|
||||
|
||||
if indent_error && !empty_line_given {
|
||||
// The input line is not empty and it threw an indentation error
|
||||
let l = err.body.location;
|
||||
|
||||
// This is how we can mask unnecesary errors
|
||||
if l.row() > *last_row {
|
||||
*last_row = l.row();
|
||||
ShellExecResult::Continue
|
||||
} else {
|
||||
*last_row = 0;
|
||||
ShellExecResult::PyErr(vm.new_syntax_error(&err))
|
||||
}
|
||||
} else {
|
||||
// Throw the error for all other cases
|
||||
*last_row = 0;
|
||||
// If we are handling an error on an empty line or an error worthy of throwing
|
||||
if empty_line_given || bad_error {
|
||||
ShellExecResult::PyErr(vm.new_syntax_error(&err))
|
||||
} else {
|
||||
ShellExecResult::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +103,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
}
|
||||
|
||||
let mut continuing = false;
|
||||
let mut last_row: usize = 0;
|
||||
|
||||
loop {
|
||||
let prompt_name = if continuing { "ps2" } else { "ps1" };
|
||||
@@ -128,14 +130,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
}
|
||||
full_input.push('\n');
|
||||
|
||||
match shell_exec(
|
||||
vm,
|
||||
&full_input,
|
||||
scope.clone(),
|
||||
&mut last_row,
|
||||
empty_line_given,
|
||||
continuing,
|
||||
) {
|
||||
match shell_exec(vm, &full_input, scope.clone(), empty_line_given, continuing) {
|
||||
ShellExecResult::Ok => {
|
||||
if continuing {
|
||||
if empty_line_given {
|
||||
@@ -150,7 +145,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
}
|
||||
} else {
|
||||
// We aren't in continue mode so proceed normally
|
||||
last_row = 0;
|
||||
continuing = false;
|
||||
full_input.clear();
|
||||
Ok(())
|
||||
@@ -168,7 +162,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
}
|
||||
}
|
||||
ReadlineResult::Interrupt => {
|
||||
last_row = 0;
|
||||
continuing = false;
|
||||
full_input.clear();
|
||||
let keyboard_interrupt =
|
||||
|
||||
Reference in New Issue
Block a user