diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-08 22:14:12 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-08 22:14:12 +0900 |
| commit | f4cad2123b2af0de72bda4ce039e16e74f163f4e (patch) | |
| tree | 21803308c5ff41e23c9d3b117433eea16b4ff663 /crates/shirabe-class-map-generator/src | |
| parent | 0209f63210e5b547b5c6b73367bb80ea86c255ec (diff) | |
| download | php-shirabe-f4cad2123b2af0de72bda4ce039e16e74f163f4e.tar.gz php-shirabe-f4cad2123b2af0de72bda4ce039e16e74f163f4e.tar.zst php-shirabe-f4cad2123b2af0de72bda4ce039e16e74f163f4e.zip | |
feat(php-shim): give ported exceptions PHP's class hierarchy
Ported exceptions were flat structs reached with `downcast_ref`, so
Composer's `catch (\RuntimeException $e)` only matched the exact leaf
type and `get_class($e)` had nothing to report. Each exception now
embeds an instance of the class it extends and travels inside an
`AnyThrowable`; `Catch::catch`/`catch_mut` walk that chain, and
`PhpClass::php_class_name` yields the PHP FQCN.
Dropping the `std::error::Error` impls from the exception types leaves
`AnyThrowable` as the only route into an `anyhow::Error`, so the walk
cannot be bypassed. A `no_exception_downcast` linter catches the
`downcast::<X>()` calls that would now silently answer `None`.
Three sites change behavior as a result: the `TransportException`
exit-code override reaches `MaxFileSizeExceededException`, the
`catch (\LogicException)` in findSimilar() reaches its subclasses, and
rendered exception titles carry the real class name rather than a
guess. `get_class_err()` is no longer a `todo!()`, which re-enables
FilesystemRepositoryTest::testCorruptedRepositoryFile.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-class-map-generator/src')
3 files changed, 39 insertions, 49 deletions
diff --git a/crates/shirabe-class-map-generator/src/class_map.rs b/crates/shirabe-class-map-generator/src/class_map.rs index 0b828be4..65eb3790 100644 --- a/crates/shirabe-class-map-generator/src/class_map.rs +++ b/crates/shirabe-class-map-generator/src/class_map.rs @@ -92,10 +92,11 @@ impl ClassMap { pub fn get_class_path(&self, class_name: &str) -> anyhow::Result<&str> { match self.map.get(class_name) { Some(path) => Ok(path.as_str()), - None => Err(anyhow::anyhow!(OutOfBoundsException { - message: format!("Class {} is not present in the map", class_name), - code: 0, - })), + None => Err(OutOfBoundsException::new(format!( + "Class {} is not present in the map", + class_name + )) + .into()), } } diff --git a/crates/shirabe-class-map-generator/src/class_map_generator.rs b/crates/shirabe-class-map-generator/src/class_map_generator.rs index 0f98ca27..d1a11c99 100644 --- a/crates/shirabe-class-map-generator/src/class_map_generator.rs +++ b/crates/shirabe-class-map-generator/src/class_map_generator.rs @@ -74,19 +74,15 @@ impl ClassMapGenerator { excluded_dirs: Vec<String>, ) -> anyhow::Result<()> { if !matches!(autoload_type, "psr-0" | "psr-4" | "classmap") { - return Err(anyhow::anyhow!(InvalidArgumentException { - message: "$autoloadType must be one of: \"psr-0\", \"psr-4\" or \"classmap\"" - .to_string(), - code: 0, - })); + return Err(InvalidArgumentException::new( + "$autoloadType must be one of: \"psr-0\", \"psr-4\" or \"classmap\"".to_string(), + ) + .into()); } let base_path: Option<String> = if autoload_type != "classmap" { if namespace.is_none() { - return Err(anyhow::anyhow!(InvalidArgumentException { - message: "$namespace must be given (even if it is an empty string if you do not want to filter) when specifying a psr-0 or psr-4 autoload type".to_string(), - code: 0, - })); + return Err(InvalidArgumentException::new("$namespace must be given (even if it is an empty string if you do not want to filter) when specifying a psr-0 or psr-4 autoload type".to_string()).into()); } Some(path.to_owned()) } else { @@ -116,13 +112,10 @@ impl ClassMapGenerator { .iter() .collect() } else { - return Err(anyhow::anyhow!(RuntimeException { - message: format!( - "Could not scan for classes inside \"{}\" which does not appear to be a file nor a folder", - path - ), - code: 0, - })); + return Err(RuntimeException::new(format!( + "Could not scan for classes inside \"{}\" which does not appear to be a file nor a folder", + path + )).into()); }; let cwd = realpath(getcwd().unwrap_or_default()).unwrap_or_default(); @@ -131,10 +124,11 @@ impl ClassMapGenerator { let mut file_path = match file.to_str() { Some(s) => s.to_string(), None => { - return Err(anyhow::anyhow!(RuntimeException { - message: format!("Path contains invalid UTF-8: {}", file.display()), - code: 0, - })); + return Err(RuntimeException::new(format!( + "Path contains invalid UTF-8: {}", + file.display() + )) + .into()); } }; let ext = pathinfo(&file_path, PATHINFO_EXTENSION); @@ -158,10 +152,11 @@ impl ClassMapGenerator { } if file_path.is_empty() { - return Err(anyhow::anyhow!(LogicException { - message: format!("Got an empty $filePath for {}", file.display()), - code: 0, - })); + return Err(LogicException::new(format!( + "Got an empty $filePath for {}", + file.display() + )) + .into()); } let real_path = if is_stream_wrapper_path { @@ -170,13 +165,11 @@ impl ClassMapGenerator { match realpath(&file_path) { Some(p) => p, None => { - return Err(anyhow::anyhow!(RuntimeException { - message: format!( - "realpath of {} failed to resolve, got false", - file_path - ), - code: 0, - })); + return Err(RuntimeException::new(format!( + "realpath of {} failed to resolve, got false", + file_path + )) + .into()); } } }; @@ -284,10 +277,10 @@ impl ClassMapGenerator { }; sub_path = str_replace("\\", DIRECTORY_SEPARATOR, &sub_namespace); } else { - return Err(anyhow::anyhow!(InvalidArgumentException { - message: "$namespaceType must be \"psr-0\" or \"psr-4\"".to_string(), - code: 0, - })); + return Err(InvalidArgumentException::new( + "$namespaceType must be \"psr-0\" or \"psr-4\"".to_string(), + ) + .into()); } if sub_path == real_sub_path { @@ -403,10 +396,10 @@ impl ClassMapGenerator { fn get_cwd() -> anyhow::Result<String> { match getcwd() { Some(cwd) => Ok(cwd), - None => Err(anyhow::anyhow!(RuntimeException { - message: "Could not determine the current working directory".to_string(), - code: 0, - })), + None => Err(RuntimeException::new( + "Could not determine the current working directory".to_string(), + ) + .into()), } } } diff --git a/crates/shirabe-class-map-generator/src/php_file_parser.rs b/crates/shirabe-class-map-generator/src/php_file_parser.rs index cf30c240..88676407 100644 --- a/crates/shirabe-class-map-generator/src/php_file_parser.rs +++ b/crates/shirabe-class-map-generator/src/php_file_parser.rs @@ -1,7 +1,6 @@ //! ref: composer/vendor/composer/class-map-generator/src/PhpFileParser.php use crate::php_file_cleaner::PhpFileCleaner; -use anyhow::anyhow; use indexmap::IndexMap; use shirabe_external_packages::composer::pcre::{CaptureKey, Preg}; use shirabe_php_shim::{ @@ -18,10 +17,7 @@ impl PhpFileParser { let extra_types = Self::get_extra_types(); if !function_exists("php_strip_whitespace") { - return Err(anyhow!(RuntimeException { - message: "Classmap generation relies on the php_strip_whitespace function, but it has been disabled by the disable_functions directive.".to_string(), - code: 0, - })); + return Err(RuntimeException::new("Classmap generation relies on the php_strip_whitespace function, but it has been disabled by the disable_functions directive.".to_string()).into()); } // Use @ here instead of Silencer to actively suppress 'unhelpful' output @@ -63,7 +59,7 @@ impl PhpFileParser { ); } - return Err(anyhow!(RuntimeException { message, code: 0 })); + return Err(RuntimeException::new(message).into()); } // return early if there is no chance of matching anything in this file |
