aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/io/io_interface.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-02 08:55:56 +0900
committernsfisis <nsfisis@gmail.com>2026-08-02 08:55:56 +0900
commit2c3373a7466c31f5cce7c2867c00a91afaa8e128 (patch)
tree754c7da92def5d14fc425230f9db41c654897b4f /crates/shirabe/src/io/io_interface.rs
parent92f5c977b42d1322f3cebb260024179e1285b9d0 (diff)
downloadphp-shirabe-2c3373a7466c31f5cce7c2867c00a91afaa8e128.tar.gz
php-shirabe-2c3373a7466c31f5cce7c2867c00a91afaa8e128.tar.zst
php-shirabe-2c3373a7466c31f5cce7c2867c00a91afaa8e128.zip
fix(io): propagate ask/select errors instead of panicking
IOInterface::ask/select now return anyhow::Result<PhpMixed>, and ConsoleIO::ask_question forwards QuestionHelper errors (validator failures, MissingInputException) instead of collapsing them with .expect(). In PHP these exceptions propagate from QuestionHelper through ConsoleIO to the caller, so callers such as UpdateCommand's interactive package selection must be able to observe them; the MissingInputException is wrapped with its concrete type preserved so Application's ExceptionInterface downcast keeps working. All call sites now propagate with `?` (Perforce::query_p4_user becomes Result-returning: PHP declares it void but exceptions still escape), and the previously ignored test_interactive_mode_throws_if_no_package_entered passes. ask_confirmation/ask_and_hide_answer still collapse errors; extending propagation to them is left as TODO(phase-c) pending a decision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/io/io_interface.rs')
-rw-r--r--crates/shirabe/src/io/io_interface.rs15
1 files changed, 11 insertions, 4 deletions
diff --git a/crates/shirabe/src/io/io_interface.rs b/crates/shirabe/src/io/io_interface.rs
index 33a2f017..b0271767 100644
--- a/crates/shirabe/src/io/io_interface.rs
+++ b/crates/shirabe/src/io/io_interface.rs
@@ -92,7 +92,10 @@ pub trait IOInterfaceImmutable: std::fmt::Debug {
}
fn overwrite_error4(&self, message: &str, newline: bool, size: Option<i64>, verbosity: i64);
- fn ask(&self, question: String, default: PhpMixed) -> PhpMixed;
+ /// PHP: `@throws \RuntimeException If there is no data to read in the input stream`.
+ /// `QuestionHelper::ask` exceptions (validator errors, `MissingInputException`) propagate
+ /// to the caller, hence the `anyhow::Result` return type.
+ fn ask(&self, question: String, default: PhpMixed) -> anyhow::Result<PhpMixed>;
fn ask_confirmation(&self, question: String, default: bool) -> bool;
@@ -109,6 +112,10 @@ pub trait IOInterfaceImmutable: std::fmt::Debug {
/// PHP `array $choices` may be a list (`PhpMixed::List`) or an associative
/// array (`PhpMixed::Array`); list choices resolve to their index, while
/// associative choices resolve to their key.
+ ///
+ /// PHP: `@throws \InvalidArgumentException` — the `ChoiceQuestion` validator error
+ /// propagates to the caller once `$attempts` is exhausted, hence the `anyhow::Result`
+ /// return type.
fn select(
&self,
question: String,
@@ -117,7 +124,7 @@ pub trait IOInterfaceImmutable: std::fmt::Debug {
attempts: PhpMixed,
error_message: String,
multiselect: bool,
- ) -> PhpMixed;
+ ) -> anyhow::Result<PhpMixed>;
fn get_authentications(&self) -> IndexMap<String, IndexMap<String, Option<String>>>;
@@ -278,7 +285,7 @@ impl IOInterfaceImmutable for std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
.overwrite_error4(message, newline, size, verbosity)
}
- fn ask(&self, question: String, default: PhpMixed) -> PhpMixed {
+ fn ask(&self, question: String, default: PhpMixed) -> anyhow::Result<PhpMixed> {
self.borrow().ask(question, default)
}
@@ -309,7 +316,7 @@ impl IOInterfaceImmutable for std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
attempts: PhpMixed,
error_message: String,
multiselect: bool,
- ) -> PhpMixed {
+ ) -> anyhow::Result<PhpMixed> {
self.borrow().select(
question,
choices,