Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14140617
D20213.id48272.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D20213.id48272.diff
View Options
diff --git a/src/__phutil_library_init__.php b/src/__phutil_library_init__.php
--- a/src/__phutil_library_init__.php
+++ b/src/__phutil_library_init__.php
@@ -26,10 +26,9 @@
$class_name,
pht('class or interface'),
pht(
- "the class or interface '%s' is not defined in the library ".
- "map for any loaded %s library.",
- $class_name,
- 'phutil'));
+ 'The class or interface "%s" is not defined in the library '.
+ 'map of any loaded library.',
+ $class_name));
}
} catch (PhutilMissingSymbolException $ex) {
$should_throw = true;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -542,6 +542,7 @@
'phutil_date_format' => 'utils/viewutils.php',
'phutil_decode_mime_header' => 'utils/utils.php',
'phutil_deprecated' => 'moduleutils/moduleutils.php',
+ 'phutil_describe_type' => 'utils/utils.php',
'phutil_error_listener_example' => 'error/phlog.php',
'phutil_escape_html' => 'markup/render.php',
'phutil_escape_html_newlines' => 'markup/render.php',
@@ -564,6 +565,7 @@
'phutil_implode_html' => 'markup/render.php',
'phutil_ini_decode' => 'utils/utils.php',
'phutil_is_hiphop_runtime' => 'utils/utils.php',
+ 'phutil_is_natural_list' => 'utils/utils.php',
'phutil_is_system_locale_available' => 'utils/utf8.php',
'phutil_is_utf8' => 'utils/utf8.php',
'phutil_is_utf8_slowly' => 'utils/utf8.php',
diff --git a/src/conduit/ConduitClient.php b/src/conduit/ConduitClient.php
--- a/src/conduit/ConduitClient.php
+++ b/src/conduit/ConduitClient.php
@@ -348,7 +348,7 @@
$out = array();
if (is_array($data)) {
- if (!$data || (array_keys($data) == range(0, count($data) - 1))) {
+ if (phutil_is_natural_list($data)) {
$out[] = 'A';
$out[] = count($data);
$out[] = ':';
diff --git a/src/moduleutils/PhutilBootloader.php b/src/moduleutils/PhutilBootloader.php
--- a/src/moduleutils/PhutilBootloader.php
+++ b/src/moduleutils/PhutilBootloader.php
@@ -62,6 +62,15 @@
$this->registeredLibraries[$name] = $path;
+ // If we're loading libphutil itself, load the utility functions first so
+ // we can safely call functions like "id()" when handling errors. In
+ // particular, this improves error behavior when "utils.php" itself can
+ // not load.
+ if ($name === 'phutil') {
+ $root = $this->getLibraryRoot('phutil');
+ $this->executeInclude($root.'/utils/utils.php');
+ }
+
// For libphutil v2 libraries, load all functions when we load the library.
if (!class_exists('PhutilSymbolLoader', false)) {
diff --git a/src/parser/PhutilJSON.php b/src/parser/PhutilJSON.php
--- a/src/parser/PhutilJSON.php
+++ b/src/parser/PhutilJSON.php
@@ -118,7 +118,7 @@
*/
private function encodeFormattedValue($value, $depth) {
if (is_array($value)) {
- if (empty($value) || array_keys($value) === range(0, count($value) - 1)) {
+ if (phutil_is_natural_list($value)) {
return $this->encodeFormattedArray($value, $depth);
} else {
return $this->encodeFormattedObject($value, $depth);
diff --git a/src/parser/PhutilTypeSpec.php b/src/parser/PhutilTypeSpec.php
--- a/src/parser/PhutilTypeSpec.php
+++ b/src/parser/PhutilTypeSpec.php
@@ -93,7 +93,7 @@
if (!is_array($value)) {
throw new PhutilTypeCheckException($this, $value, $name);
}
- if ($value && (array_keys($value) !== range(0, count($value) - 1))) {
+ if ($value && !phutil_is_natural_list($value)) {
throw new PhutilTypeCheckException($this, $value, $name);
}
try {
@@ -209,7 +209,7 @@
return get_class($value);
} else if (is_array($value)) {
$vtype = self::getTypeOfVector($value);
- if ($value && (array_keys($value) === range(0, count($value) - 1))) {
+ if ($value && phutil_is_natural_list($value)) {
return 'list<'.$vtype.'>';
} else {
$ktype = self::getTypeOfVector(array_keys($value));
diff --git a/src/symbols/PhutilSymbolLoader.php b/src/symbols/PhutilSymbolLoader.php
--- a/src/symbols/PhutilSymbolLoader.php
+++ b/src/symbols/PhutilSymbolLoader.php
@@ -386,11 +386,11 @@
$load_failed = null;
if ($is_function) {
if (!function_exists($name)) {
- $load_failed = pht('function');
+ $load_failed = 'function';
}
} else {
if (!class_exists($name, false) && !interface_exists($name, false)) {
- $load_failed = pht('class or interface');
+ $load_failed = 'class/interface';
}
}
@@ -400,14 +400,13 @@
$name,
$load_failed,
pht(
- "the symbol map for library '%s' (at '%s') claims this %s is ".
- "defined in '%s', but loading that source file did not cause the ".
- "%s to become defined.",
+ 'The symbol map for library "%s" (at "%s") claims this symbol '.
+ '(of type "%s") is defined in "%s", but loading that source file '.
+ 'did not cause the symbol to become defined.',
$lib_name,
$lib_path,
$load_failed,
- $where,
- $load_failed));
+ $where));
}
}
diff --git a/src/symbols/exception/PhutilMissingSymbolException.php b/src/symbols/exception/PhutilMissingSymbolException.php
--- a/src/symbols/exception/PhutilMissingSymbolException.php
+++ b/src/symbols/exception/PhutilMissingSymbolException.php
@@ -5,22 +5,24 @@
public function __construct($symbol, $type, $reason) {
parent::__construct(
pht(
- "Failed to load %s '%s': %s\n\n".
- "If you are not a developer, this almost always means that a library ".
- "is out of date. For example, you may have upgraded `phabricator` ".
- "without upgrading `libphutil`, or vice versa. It might also mean ".
- "that you need to restart Apache or PHP-FPM. Make sure all libraries ".
- "are up to date and all services have been restarted.\n\n".
- "If you are a developer and this symbol was recently added or moved, ".
- "your library map may need to be rebuilt. You can rebuild the map by ".
- "running '%s'. For more information, see:\n\n".
- "%s",
+ 'Failed to load %s "%s".'.
+ "\n\n".
+ '%s'.
+ "\n\n".
+ 'If you are not a developer, this almost always means that a library '.
+ 'is out of date. For example, you may have upgraded "phabricator/" '.
+ 'without upgrading "libphutil/", or vice versa. It might also mean '.
+ 'that you need to restart Apache or PHP-FPM. Make sure all libraries '.
+ 'are up to date and all services have been restarted.'.
+ "\n\n".
+ 'If you are a developer and this symbol was recently added or '.
+ 'moved, your library map may need to be rebuilt. You can rebuild '.
+ 'the map by running "arc liberate".'.
+ "\n\n".
+ 'For more information, see: https://phurl.io/newclasses',
$type,
$symbol,
- $reason,
- 'arc liberate',
- 'https://secure.phabricator.com/book/phabcontrib/article/'.
- 'adding_new_classes/'));
+ $reason));
}
}
diff --git a/src/utils/__tests__/PhutilUtilsTestCase.php b/src/utils/__tests__/PhutilUtilsTestCase.php
--- a/src/utils/__tests__/PhutilUtilsTestCase.php
+++ b/src/utils/__tests__/PhutilUtilsTestCase.php
@@ -918,4 +918,21 @@
}
}
+ public function testNaturalList() {
+ $cases = array(
+ array(true, array()),
+ array(true, array(0 => true, 1 => true, 2 => true)),
+ array(true, array('a', 'b', 'c')),
+ array(false, array(0 => true, 2 => true, 1 => true)),
+ array(false, array(1 => true)),
+ array(false, array('sound' => 'quack')),
+ );
+
+ foreach ($cases as $case) {
+ list($expect, $value) = $case;
+ $this->assertEqual($expect, phutil_is_natural_list($value));
+ }
+ }
+
+
}
diff --git a/src/utils/utils.php b/src/utils/utils.php
--- a/src/utils/utils.php
+++ b/src/utils/utils.php
@@ -1476,7 +1476,7 @@
}
// Don't show keys for non-associative arrays.
- $show_keys = (array_keys($var) !== range(0, count($var) - 1));
+ $show_keys = !phutil_is_natural_list($var);
$output = array();
$output[] = 'array(';
@@ -1757,3 +1757,40 @@
return (string)$value;
}
+
+
+/**
+ * Return a short, human-readable description of an object's type.
+ *
+ * This is mostly useful for raising errors like "expected x() to return a Y,
+ * but it returned a Z".
+ *
+ * This is similar to "get_type()", but describes objects and arrays in more
+ * detail.
+ *
+ * @param wild Anything.
+ * @return string Human-readable description of the value's type.
+ */
+function phutil_describe_type($value) {
+ return PhutilTypeSpec::getTypeOf($value);
+}
+
+
+/**
+ * Test if a list has the natural numbers (1, 2, 3, and so on) as keys, in
+ * order.
+ *
+ * @return bool True if the list is a natural list.
+ */
+function phutil_is_natural_list(array $list) {
+ $expect = 0;
+
+ foreach ($list as $key => $item) {
+ if ($key !== $expect) {
+ return false;
+ }
+ $expect++;
+ }
+
+ return true;
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 4, 6:52 AM (2 h, 37 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6823441
Default Alt Text
D20213.id48272.diff (9 KB)
Attached To
Mode
D20213: Add "phutil_describe_type()" and clean up a few obscure things in "libphutil/"
Attached
Detach File
Event Timeline
Log In to Comment