From f6261dc614a78d243ecf61c93137c81b51d19ee6 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Fri, 15 Mar 2024 10:49:33 +0200 Subject: [PATCH] Arc liberate: support traits Summary: Looks like this is all that's needed? Ref T15751 Test Plan: R12 has some scenarios for testing this. Also ran `arc liberate --clean` on arc and phorge repos, and the generated map did not change. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15751 Differential Revision: https://we.phorge.it/D25551 --- src/moduleutils/PhutilLibraryMapBuilder.php | 7 +++- src/symbols/PhutilSymbolLoader.php | 10 ++++-- support/lib/extract-symbols.php | 36 ++++++++++----------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/moduleutils/PhutilLibraryMapBuilder.php b/src/moduleutils/PhutilLibraryMapBuilder.php index df05050a..5d359bbc 100644 --- a/src/moduleutils/PhutilLibraryMapBuilder.php +++ b/src/moduleutils/PhutilLibraryMapBuilder.php @@ -332,11 +332,16 @@ final class PhutilLibraryMapBuilder extends Phobject { 'xmap' => array(), ); + $type_translation = array( + 'interface' => 'class', + 'trait' => 'class', + ); + // Detect duplicate symbols within the library. foreach ($symbol_map as $file => $info) { foreach ($info['have'] as $type => $symbols) { foreach ($symbols as $symbol => $declaration) { - $lib_type = ($type == 'interface') ? 'class' : $type; + $lib_type = idx($type_translation, $type, $type); if (!empty($library_map[$lib_type][$symbol])) { $prior = $library_map[$lib_type][$symbol]; throw new Exception( diff --git a/src/symbols/PhutilSymbolLoader.php b/src/symbols/PhutilSymbolLoader.php index a5851a5e..7f733ee7 100644 --- a/src/symbols/PhutilSymbolLoader.php +++ b/src/symbols/PhutilSymbolLoader.php @@ -398,6 +398,12 @@ final class PhutilSymbolLoader { } + private static function classLikeExists($name) { + return class_exists($name, false) || + interface_exists($name, false) || + trait_exists($name, false); + } + /** * @task internal */ @@ -411,7 +417,7 @@ final class PhutilSymbolLoader { return; } } else { - if (class_exists($name, false) || interface_exists($name, false)) { + if (self::classLikeExists($name)) { return; } } @@ -431,7 +437,7 @@ final class PhutilSymbolLoader { $load_failed = pht('function'); } } else { - if (!class_exists($name, false) && !interface_exists($name, false)) { + if (!self::classLikeExists($name)) { $load_failed = pht('class or interface'); } } diff --git a/support/lib/extract-symbols.php b/support/lib/extract-symbols.php index a1cd28fa..6744cd90 100755 --- a/support/lib/extract-symbols.php +++ b/support/lib/extract-symbols.php @@ -112,18 +112,6 @@ foreach ($namespaces as $namespace) { $namespace, $path, pht('namespace `%s` statements', 'use')); } -$possible_traits = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); -foreach ($possible_traits as $possible_trait) { - $attributes = $possible_trait->getChildByIndex(0); - // Can't use getChildByIndex here because not all classes have attributes - foreach ($attributes->getChildren() as $attribute) { - if (strtolower($attribute->getConcreteString()) === 'trait') { - phutil_fail_on_unsupported_feature($possible_trait, $path, pht('traits')); - } - } -} - - // -( Marked Externals )------------------------------------------------------ @@ -256,17 +244,29 @@ foreach ($calls as $call) { // Find classes declared by this file. - // This is "class X ... { ... }". -$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); -foreach ($classes as $class) { - $class_name = $class->getChildByIndex(1); - $have[] = array( - 'type' => 'class', +function build_have_element_for_class_declaration(XHPASTNode $class_node) { + $class_name = $class_node->getChildByIndex(1); + + $type = 'class'; + $attributes = $class_node->getChildByIndex(0); + foreach ($attributes->getChildren() as $attribute) { + if (strtolower($attribute->getConcreteString()) === 'trait') { + $type = 'trait'; + } + } + + return array( + 'type' => $type, 'symbol' => $class_name, ); } +$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION'); +foreach ($classes as $class) { + $have[] = build_have_element_for_class_declaration($class); +} + // Find classes used by this file. We identify these: //