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
*/
public static function handleError($num, $str, $file, $line, $ctx = null) {
foreach (self::$traps as $trap) {
$trap->addError($num, $str, $file, $line);
}
@ -378,7 +377,7 @@ final class PhutilErrorHandler extends Phobject {
* @task internal
*/
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) {
case self::ERROR:

View file

@ -212,7 +212,7 @@ abstract class LinesOfALarge extends Phobject implements Iterator {
if (strlen($this->buf)) {
$this->num++;
$this->line = $this->buf;
$this->buf = null;
$this->buf = '';
} else {
$this->valid = false;
}

View file

@ -199,7 +199,7 @@ final class ExecFuture extends PhutilExecutableFuture {
(string)substr($this->stderr, $this->stderrPos),
);
$this->stderrPos = strlen($this->stderr);
$this->stderrPos = $this->getStderrBufferLength();
return $result;
}
@ -210,7 +210,8 @@ final class ExecFuture extends PhutilExecutableFuture {
}
$result = (string)substr($this->stdout, $this->stdoutPos);
$this->stdoutPos = strlen($this->stdout);
$this->stdoutPos = $this->getStdoutBufferLength();
return $result;
}
@ -475,7 +476,7 @@ final class ExecFuture extends PhutilExecutableFuture {
* @task internal
*/
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_stderr_read_bytes = PHP_INT_MAX;
if ($read_buffer_size !== null) {
$max_stdout_read_bytes = $read_buffer_size - strlen($this->stdout);
$max_stderr_read_bytes = $read_buffer_size - strlen($this->stderr);
$stdout_len = $this->getStdoutBufferLength();
$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) {
$this->stdout .= $this->readAndDiscard(
$stdout,
$this->getStdoutSizeLimit() - strlen($this->stdout),
$this->getStdoutSizeLimit() - $this->getStdoutBufferLength(),
'stdout',
$max_stdout_read_bytes);
}
@ -772,7 +776,7 @@ final class ExecFuture extends PhutilExecutableFuture {
if ($max_stderr_read_bytes > 0) {
$this->stderr .= $this->readAndDiscard(
$stderr,
$this->getStderrSizeLimit() - strlen($this->stderr),
$this->getStderrSizeLimit() - $this->getStderrBufferLength(),
'stderr',
$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
*/
public function getHeaders($filter = null) {
$filter = strtolower($filter);
if ($filter !== null) {
$filter = phutil_utf8_strtolower($filter);
}
$result = array();
foreach ($this->headers as $header) {
list($name, $value) = $header;
if (!$filter || ($filter == strtolower($name))) {
if (($filter === null) || ($filter === phutil_utf8_strtolower($name))) {
$result[] = $header;
}
}

View file

@ -269,7 +269,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, $allowed_protocols);
}
if (strlen($this->rawBody)) {
if ($this->rawBody !== null) {
if ($this->getData()) {
throw new Exception(
pht(

View file

@ -17,6 +17,14 @@ final class ArcanistCommentStyleXHPASTLinterRule
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(
$comment->getOffset(),
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));
}
#[\ReturnTypeWillChange]
public function current() {
$this->throwOnAttemptedIteration();
}
#[\ReturnTypeWillChange]
public function key() {
$this->throwOnAttemptedIteration();
}
#[\ReturnTypeWillChange]
public function next() {
$this->throwOnAttemptedIteration();
}
#[\ReturnTypeWillChange]
public function rewind() {
$this->throwOnAttemptedIteration();
}
#[\ReturnTypeWillChange]
public function valid() {
$this->throwOnAttemptedIteration();
}

View file

@ -166,7 +166,7 @@ final class PhutilURI extends Phobject {
if ($this->isGitURI()) {
$protocol = null;
} else {
if (strlen($auth)) {
if ($auth !== null) {
$protocol = nonempty($this->protocol, 'http');
}
}

View file

@ -769,7 +769,12 @@ final class PhutilArgumentParser extends Phobject {
pht('There is no **%s** workflow.', $workflow_name));
} else {
$out[] = $this->indent($indent, $workflow->getExamples());
$synopsis = $workflow->getSynopsis();
if ($synopsis !== null) {
$out[] = $this->indent($indent, $workflow->getSynopsis());
}
if ($show_details) {
$full_help = $workflow->getHelp();
if ($full_help) {

View file

@ -226,8 +226,8 @@ final class PhutilClassMapQuery extends Phobject {
$unique = $this->uniqueMethod;
$sort = $this->sortMethod;
if (strlen($expand)) {
if (!strlen($unique)) {
if ($expand !== null) {
if ($unique === null) {
throw new Exception(
pht(
'Trying to execute a class map query for descendants of class '.
@ -245,7 +245,7 @@ final class PhutilClassMapQuery extends Phobject {
->loadObjects();
// Apply the "expand" mechanism, if it is configured.
if (strlen($expand)) {
if ($expand !== null) {
$list = array();
foreach ($objects as $object) {
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.
if (strlen($unique)) {
if ($unique !== null) {
$map = array();
foreach ($list as $object) {
$key = call_user_func(array($object, $unique));
@ -287,12 +287,12 @@ final class PhutilClassMapQuery extends Phobject {
}
// Apply the "filter" mechanism, if it is configured.
if (strlen($filter)) {
if ($filter !== null) {
$map = mfilter($map, $filter);
}
// Apply the "sort" mechanism, if it is configured.
if (strlen($sort)) {
if ($sort !== null) {
if ($map) {
// The "sort" method may return scalars (which we want to sort with
// "msort()"), or may return PhutilSortVector objects (which we want

View file

@ -143,7 +143,7 @@ abstract class ArcanistWorkflow extends Phobject {
if ($information) {
$synopsis = $information->getSynopsis();
if (strlen($synopsis)) {
if ($synopsis !== null) {
$phutil_workflow->setSynopsis($synopsis);
}