mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Correct some Arcanist behaviors under PHP8.1
Summary: Ref T13588. See that task for discussion. Improve behavior under PHP8.1, particularly the deprecation warning raised by calling `strlen(null)`. Test Plan: - Ran `arc help`, `arc branches`, `arc diff`, etc., under PHP 8.1 and PHP 7.4. - Created this change with PHP8.1. Maniphest Tasks: T13588 Differential Revision: https://secure.phabricator.com/D21740
This commit is contained in:
parent
13d3a3c3b1
commit
3626582354
12 changed files with 83 additions and 22 deletions
|
@ -181,7 +181,6 @@ final class PhutilErrorHandler extends Phobject {
|
||||||
* @task internal
|
* @task internal
|
||||||
*/
|
*/
|
||||||
public static function handleError($num, $str, $file, $line, $ctx = null) {
|
public static function handleError($num, $str, $file, $line, $ctx = null) {
|
||||||
|
|
||||||
foreach (self::$traps as $trap) {
|
foreach (self::$traps as $trap) {
|
||||||
$trap->addError($num, $str, $file, $line);
|
$trap->addError($num, $str, $file, $line);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +377,7 @@ final class PhutilErrorHandler extends Phobject {
|
||||||
* @task internal
|
* @task internal
|
||||||
*/
|
*/
|
||||||
public static function dispatchErrorMessage($event, $value, $metadata) {
|
public static function dispatchErrorMessage($event, $value, $metadata) {
|
||||||
$timestamp = strftime('%Y-%m-%d %H:%M:%S');
|
$timestamp = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
switch ($event) {
|
switch ($event) {
|
||||||
case self::ERROR:
|
case self::ERROR:
|
||||||
|
|
|
@ -212,7 +212,7 @@ abstract class LinesOfALarge extends Phobject implements Iterator {
|
||||||
if (strlen($this->buf)) {
|
if (strlen($this->buf)) {
|
||||||
$this->num++;
|
$this->num++;
|
||||||
$this->line = $this->buf;
|
$this->line = $this->buf;
|
||||||
$this->buf = null;
|
$this->buf = '';
|
||||||
} else {
|
} else {
|
||||||
$this->valid = false;
|
$this->valid = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
(string)substr($this->stderr, $this->stderrPos),
|
(string)substr($this->stderr, $this->stderrPos),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->stderrPos = strlen($this->stderr);
|
$this->stderrPos = $this->getStderrBufferLength();
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,8 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = (string)substr($this->stdout, $this->stdoutPos);
|
$result = (string)substr($this->stdout, $this->stdoutPos);
|
||||||
$this->stdoutPos = strlen($this->stdout);
|
$this->stdoutPos = $this->getStdoutBufferLength();
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +476,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
* @task internal
|
* @task internal
|
||||||
*/
|
*/
|
||||||
public function isReadBufferEmpty() {
|
public function isReadBufferEmpty() {
|
||||||
return !strlen($this->stdout);
|
return !$this->getStdoutBufferLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -757,14 +758,17 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
$max_stdout_read_bytes = PHP_INT_MAX;
|
$max_stdout_read_bytes = PHP_INT_MAX;
|
||||||
$max_stderr_read_bytes = PHP_INT_MAX;
|
$max_stderr_read_bytes = PHP_INT_MAX;
|
||||||
if ($read_buffer_size !== null) {
|
if ($read_buffer_size !== null) {
|
||||||
$max_stdout_read_bytes = $read_buffer_size - strlen($this->stdout);
|
$stdout_len = $this->getStdoutBufferLength();
|
||||||
$max_stderr_read_bytes = $read_buffer_size - strlen($this->stderr);
|
$stderr_len = $this->getStderrBufferLength();
|
||||||
|
|
||||||
|
$max_stdout_read_bytes = $read_buffer_size - $stdout_len;
|
||||||
|
$max_stderr_read_bytes = $read_buffer_size - $stderr_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($max_stdout_read_bytes > 0) {
|
if ($max_stdout_read_bytes > 0) {
|
||||||
$this->stdout .= $this->readAndDiscard(
|
$this->stdout .= $this->readAndDiscard(
|
||||||
$stdout,
|
$stdout,
|
||||||
$this->getStdoutSizeLimit() - strlen($this->stdout),
|
$this->getStdoutSizeLimit() - $this->getStdoutBufferLength(),
|
||||||
'stdout',
|
'stdout',
|
||||||
$max_stdout_read_bytes);
|
$max_stdout_read_bytes);
|
||||||
}
|
}
|
||||||
|
@ -772,7 +776,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
if ($max_stderr_read_bytes > 0) {
|
if ($max_stderr_read_bytes > 0) {
|
||||||
$this->stderr .= $this->readAndDiscard(
|
$this->stderr .= $this->readAndDiscard(
|
||||||
$stderr,
|
$stderr,
|
||||||
$this->getStderrSizeLimit() - strlen($this->stderr),
|
$this->getStderrSizeLimit() - $this->getStderrBufferLength(),
|
||||||
'stderr',
|
'stderr',
|
||||||
$max_stderr_read_bytes);
|
$max_stderr_read_bytes);
|
||||||
}
|
}
|
||||||
|
@ -1013,5 +1017,20 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getStdoutBufferLength() {
|
||||||
|
if ($this->stdout === null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strlen($this->stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getStderrBufferLength() {
|
||||||
|
if ($this->stderr === null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strlen($this->stderr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,12 +206,14 @@ abstract class BaseHTTPFuture extends Future {
|
||||||
* @task config
|
* @task config
|
||||||
*/
|
*/
|
||||||
public function getHeaders($filter = null) {
|
public function getHeaders($filter = null) {
|
||||||
$filter = strtolower($filter);
|
if ($filter !== null) {
|
||||||
|
$filter = phutil_utf8_strtolower($filter);
|
||||||
|
}
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach ($this->headers as $header) {
|
foreach ($this->headers as $header) {
|
||||||
list($name, $value) = $header;
|
list($name, $value) = $header;
|
||||||
if (!$filter || ($filter == strtolower($name))) {
|
if (($filter === null) || ($filter === phutil_utf8_strtolower($name))) {
|
||||||
$result[] = $header;
|
$result[] = $header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
|
||||||
curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, $allowed_protocols);
|
curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, $allowed_protocols);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($this->rawBody)) {
|
if ($this->rawBody !== null) {
|
||||||
if ($this->getData()) {
|
if ($this->getData()) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
pht(
|
pht(
|
||||||
|
|
|
@ -17,6 +17,14 @@ final class ArcanistCommentStyleXHPASTLinterRule
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't warn about PHP comment directives. In particular, we need
|
||||||
|
// to use "#[\ReturnTypeWillChange]" to implement "Iterator" in a way
|
||||||
|
// that is compatible with PHP 8.1 and older versions of PHP prior
|
||||||
|
// to the introduction of return types. See T13588.
|
||||||
|
if (preg_match('/^#\\[\\\\/', $value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$this->raiseLintAtOffset(
|
$this->raiseLintAtOffset(
|
||||||
$comment->getOffset(),
|
$comment->getOffset(),
|
||||||
pht(
|
pht(
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class X implements Iterator {
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
|
public function reset() {
|
||||||
|
# See T13588 for PHP8.1 compatibility information.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
~~~~~~~~~~
|
||||||
|
error:7:5:XHP18:Comment Style
|
||||||
|
~~~~~~~~~~
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class X implements Iterator {
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
|
public function reset() {
|
||||||
|
// See T13588 for PHP8.1 compatibility information.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -33,22 +33,27 @@ abstract class Phobject implements Iterator {
|
||||||
get_class($this).'::'.$name));
|
get_class($this).'::'.$name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
public function current() {
|
public function current() {
|
||||||
$this->throwOnAttemptedIteration();
|
$this->throwOnAttemptedIteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
public function key() {
|
public function key() {
|
||||||
$this->throwOnAttemptedIteration();
|
$this->throwOnAttemptedIteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
public function next() {
|
public function next() {
|
||||||
$this->throwOnAttemptedIteration();
|
$this->throwOnAttemptedIteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
public function rewind() {
|
public function rewind() {
|
||||||
$this->throwOnAttemptedIteration();
|
$this->throwOnAttemptedIteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
public function valid() {
|
public function valid() {
|
||||||
$this->throwOnAttemptedIteration();
|
$this->throwOnAttemptedIteration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ final class PhutilURI extends Phobject {
|
||||||
if ($this->isGitURI()) {
|
if ($this->isGitURI()) {
|
||||||
$protocol = null;
|
$protocol = null;
|
||||||
} else {
|
} else {
|
||||||
if (strlen($auth)) {
|
if ($auth !== null) {
|
||||||
$protocol = nonempty($this->protocol, 'http');
|
$protocol = nonempty($this->protocol, 'http');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -769,7 +769,12 @@ final class PhutilArgumentParser extends Phobject {
|
||||||
pht('There is no **%s** workflow.', $workflow_name));
|
pht('There is no **%s** workflow.', $workflow_name));
|
||||||
} else {
|
} else {
|
||||||
$out[] = $this->indent($indent, $workflow->getExamples());
|
$out[] = $this->indent($indent, $workflow->getExamples());
|
||||||
$out[] = $this->indent($indent, $workflow->getSynopsis());
|
|
||||||
|
$synopsis = $workflow->getSynopsis();
|
||||||
|
if ($synopsis !== null) {
|
||||||
|
$out[] = $this->indent($indent, $workflow->getSynopsis());
|
||||||
|
}
|
||||||
|
|
||||||
if ($show_details) {
|
if ($show_details) {
|
||||||
$full_help = $workflow->getHelp();
|
$full_help = $workflow->getHelp();
|
||||||
if ($full_help) {
|
if ($full_help) {
|
||||||
|
|
|
@ -226,8 +226,8 @@ final class PhutilClassMapQuery extends Phobject {
|
||||||
$unique = $this->uniqueMethod;
|
$unique = $this->uniqueMethod;
|
||||||
$sort = $this->sortMethod;
|
$sort = $this->sortMethod;
|
||||||
|
|
||||||
if (strlen($expand)) {
|
if ($expand !== null) {
|
||||||
if (!strlen($unique)) {
|
if ($unique === null) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
pht(
|
pht(
|
||||||
'Trying to execute a class map query for descendants of class '.
|
'Trying to execute a class map query for descendants of class '.
|
||||||
|
@ -245,7 +245,7 @@ final class PhutilClassMapQuery extends Phobject {
|
||||||
->loadObjects();
|
->loadObjects();
|
||||||
|
|
||||||
// Apply the "expand" mechanism, if it is configured.
|
// Apply the "expand" mechanism, if it is configured.
|
||||||
if (strlen($expand)) {
|
if ($expand !== null) {
|
||||||
$list = array();
|
$list = array();
|
||||||
foreach ($objects as $object) {
|
foreach ($objects as $object) {
|
||||||
foreach (call_user_func(array($object, $expand)) as $instance) {
|
foreach (call_user_func(array($object, $expand)) as $instance) {
|
||||||
|
@ -257,7 +257,7 @@ final class PhutilClassMapQuery extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the "unique" mechanism, if it is configured.
|
// Apply the "unique" mechanism, if it is configured.
|
||||||
if (strlen($unique)) {
|
if ($unique !== null) {
|
||||||
$map = array();
|
$map = array();
|
||||||
foreach ($list as $object) {
|
foreach ($list as $object) {
|
||||||
$key = call_user_func(array($object, $unique));
|
$key = call_user_func(array($object, $unique));
|
||||||
|
@ -287,12 +287,12 @@ final class PhutilClassMapQuery extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the "filter" mechanism, if it is configured.
|
// Apply the "filter" mechanism, if it is configured.
|
||||||
if (strlen($filter)) {
|
if ($filter !== null) {
|
||||||
$map = mfilter($map, $filter);
|
$map = mfilter($map, $filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the "sort" mechanism, if it is configured.
|
// Apply the "sort" mechanism, if it is configured.
|
||||||
if (strlen($sort)) {
|
if ($sort !== null) {
|
||||||
if ($map) {
|
if ($map) {
|
||||||
// The "sort" method may return scalars (which we want to sort with
|
// The "sort" method may return scalars (which we want to sort with
|
||||||
// "msort()"), or may return PhutilSortVector objects (which we want
|
// "msort()"), or may return PhutilSortVector objects (which we want
|
||||||
|
|
|
@ -143,7 +143,7 @@ abstract class ArcanistWorkflow extends Phobject {
|
||||||
|
|
||||||
if ($information) {
|
if ($information) {
|
||||||
$synopsis = $information->getSynopsis();
|
$synopsis = $information->getSynopsis();
|
||||||
if (strlen($synopsis)) {
|
if ($synopsis !== null) {
|
||||||
$phutil_workflow->setSynopsis($synopsis);
|
$phutil_workflow->setSynopsis($synopsis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue