1
0
Fork 0
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:
epriestley 2021-12-09 12:40:00 -08:00
parent 13d3a3c3b1
commit 3626582354
12 changed files with 83 additions and 22 deletions

View file

@ -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:

View file

@ -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;
} }

View file

@ -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);
}
} }

View file

@ -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;
} }
} }

View file

@ -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(

View file

@ -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(

View file

@ -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.
}
}

View file

@ -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();
} }

View file

@ -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');
} }
} }

View file

@ -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());
$synopsis = $workflow->getSynopsis();
if ($synopsis !== null) {
$out[] = $this->indent($indent, $workflow->getSynopsis()); $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) {

View file

@ -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

View file

@ -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);
} }