Eliminate Some Phpstan-ignore Annotations

This PR resolves about half the statements which we tell Phpstan to ignore. There will still be 23 such annotations spread over 10 source modules for various reasons (too complicated, suspect PhpSpreadsheet code, one Phpstan bug), plus some deliberate errors in the test suite.
This commit is contained in:
oleibman
2024-02-08 21:14:14 -08:00
parent d620497511
commit 1ac1e7f11f
22 changed files with 115 additions and 61 deletions
-4
View File
@@ -1,6 +1,2 @@
parameters:
ignoreErrors:
-
message: "#^Binary operation \"/\" between float and array\\|float\\|int\\|string results in an error\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php
@@ -25,7 +25,7 @@ class TimeValue
* Excel Function:
* TIMEVALUE(timeValue)
*
* @param null|array|bool|int|string $timeValue A text string that represents a time in any one of the Microsoft
* @param null|array|bool|float|int|string $timeValue A text string that represents a time in any one of the Microsoft
* Excel time formats; for example, "6:45 PM" and "18:45" text strings
* within quotation marks that represent time.
* Date information in time_text is ignored.
@@ -36,7 +36,7 @@ class TimeValue
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function fromString(null|array|string|int|bool $timeValue): array|string|Datetime|int|float
public static function fromString(null|array|string|int|bool|float $timeValue): array|string|Datetime|int|float
{
if (is_array($timeValue)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $timeValue);
@@ -40,7 +40,14 @@ class Combinations
return $e->getMessage();
}
return round(Factorial::fact($numObjs) / Factorial::fact($numObjs - $numInSet)) / Factorial::fact($numInSet); // @phpstan-ignore-line
/** @var float */
$quotient = Factorial::fact($numObjs);
/** @var float */
$divisor1 = Factorial::fact($numObjs - $numInSet);
/** @var float */
$divisor2 = Factorial::fact($numInSet);
return round($quotient / ($divisor1 * $divisor2));
}
/**
@@ -84,8 +91,13 @@ class Combinations
return $e->getMessage();
}
return round(
Factorial::fact($numObjs + $numInSet - 1) / Factorial::fact($numObjs - 1) // @phpstan-ignore-line
) / Factorial::fact($numInSet);
/** @var float */
$quotient = Factorial::fact($numObjs + $numInSet - 1);
/** @var float */
$divisor1 = Factorial::fact($numObjs - 1);
/** @var float */
$divisor2 = Factorial::fact($numInSet);
return round($quotient / ($divisor1 * $divisor2));
}
}
@@ -46,16 +46,17 @@ class Permutations
if ($numObjs < $numInSet) {
return ExcelError::NAN();
}
/** @var float|int|string */
$result1 = MathTrig\Factorial::fact($numObjs);
if (is_string($result1)) {
return $result1;
}
/** @var float|int|string */
$result2 = MathTrig\Factorial::fact($numObjs - $numInSet);
if (is_string($result2)) {
return $result2;
}
// phpstan thinks result1 and result2 can be arrays; they can't.
$result = round($result1 / $result2); // @phpstan-ignore-line
$result = round($result1 / $result2);
return IntOrFloat::evaluate($result);
}
@@ -148,7 +148,7 @@ class Trends
* @param mixed[] $newValues Values of X for which we want to find Y
* @param mixed $const A logical (boolean) value specifying whether to force the intersect to equal 0 or not
*
* @return float[]
* @return array<int, array<int, array<int, float>>>
*/
public static function GROWTH(array $yValues, array $xValues = [], array $newValues = [], mixed $const = true): array
{
@@ -167,7 +167,7 @@ class Trends
$returnArray[0][] = [$bestFitExponential->getValueOfYForX($xValue)];
}
return $returnArray; //* @phpstan-ignore-line
return $returnArray;
}
/**
@@ -401,7 +401,7 @@ class Trends
* @param mixed[] $newValues Values of X for which we want to find Y
* @param mixed $const A logical (boolean) value specifying whether to force the intersect to equal 0 or not
*
* @return float[]
* @return array<int, array<int, array<int, float>>>
*/
public static function TREND(array $yValues, array $xValues = [], array $newValues = [], mixed $const = true): array
{
@@ -420,6 +420,6 @@ class Trends
$returnArray[0][] = [$bestFitLinear->getValueOfYForX($xValue)];
}
return $returnArray; //* @phpstan-ignore-line
return $returnArray;
}
}
@@ -126,8 +126,9 @@ class Format
$format = Helpers::extractString($format);
if (!is_numeric($value) && Date::isDateTimeFormatCode($format)) {
// @phpstan-ignore-next-line
$value = DateTimeExcel\DateValue::fromString($value) + DateTimeExcel\TimeValue::fromString($value);
$value1 = DateTimeExcel\DateValue::fromString($value);
$value2 = DateTimeExcel\TimeValue::fromString($value);
$value = (is_numeric($value1) && is_numeric($value2)) ? ($value1 + $value2) : (is_numeric($value1) ? $value2 : $value1);
}
return (string) NumberFormat::toFormattedString($value, $format);
@@ -63,7 +63,9 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder
// Convert value to number
$sign = ($matches['PrefixedSign'] ?? $matches['PrefixedSign2'] ?? $matches['PostfixedSign']) ?? null;
$currencyCode = $matches['PrefixedCurrency'] ?? $matches['PostfixedCurrency'];
$value = (float) ($sign . trim(str_replace([$decimalSeparatorNoPreg, $currencyCode, ' ', '-'], ['.', '', '', ''], preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value)))); // @phpstan-ignore-line
/** @var string */
$temp = str_replace([$decimalSeparatorNoPreg, $currencyCode, ' ', '-'], ['.', '', '', ''], preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value));
$value = (float) ($sign . trim($temp));
return $this->setCurrency($value, $cell, $currencyCode ?? '');
}
+3 -3
View File
@@ -140,9 +140,9 @@ class Properties
return $this;
}
private static function intOrFloatTimestamp(null|float|int|string $timestamp): float|int
private static function intOrFloatTimestamp(null|bool|float|int|string $timestamp): float|int
{
if ($timestamp === null) {
if ($timestamp === null || is_bool($timestamp)) {
$timestamp = (float) (new DateTime())->format('U');
} elseif (is_string($timestamp)) {
if (is_numeric($timestamp)) {
@@ -468,7 +468,7 @@ class Properties
case self::PROPERTY_TYPE_FLOAT:
return (float) $propertyValue;
case self::PROPERTY_TYPE_DATE:
return self::intOrFloatTimestamp($propertyValue); // @phpstan-ignore-line
return self::intOrFloatTimestamp($propertyValue);
case self::PROPERTY_TYPE_BOOLEAN:
return is_bool($propertyValue) ? $propertyValue : ($propertyValue === 'true');
default: // includes string
+1 -1
View File
@@ -26,7 +26,7 @@ class HashTable
*
* @param T[] $source Optional source array to create HashTable from
*/
public function __construct(?array $source = null)
public function __construct(?array $source = [])
{
if ($source !== null) {
// Create HashTable
+1
View File
@@ -1002,6 +1002,7 @@ class Xlsx extends BaseReader
if (isset($item->formula1)) {
$childNode = $node->addChild('formula1');
if ($childNode !== null) { // null should never happen
// see https://github.com/phpstan/phpstan/issues/8236
$childNode[0] = (string) $item->formula1->children(Namespaces::DATA_VALIDATIONS2)->f; // @phpstan-ignore-line
}
}
+30 -11
View File
@@ -574,6 +574,7 @@ class Chart
$multiSeriesType = null;
$smoothLine = false;
$seriesLabel = $seriesCategory = $seriesValues = $plotOrder = $seriesBubbles = [];
$plotDirection = null;
$seriesDetailSet = $chartDetail->children($this->cNamespace);
foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) {
@@ -604,11 +605,16 @@ class Chart
break;
case 'order':
$seriesOrder = self::getAttributeInteger($seriesDetail, 'val');
$plotOrder[$seriesIndex] = $seriesOrder;
if ($seriesOrder !== null) {
$plotOrder[$seriesIndex] = $seriesOrder;
}
break;
case 'tx':
$seriesLabel[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);
$temp = $this->chartDataSeriesValueSet($seriesDetail);
if ($temp !== null) {
$seriesLabel[$seriesIndex] = $temp;
}
break;
case 'spPr':
@@ -685,27 +691,42 @@ class Chart
break;
case 'smooth':
$smoothLine = self::getAttributeBoolean($seriesDetail, 'val');
$smoothLine = self::getAttributeBoolean($seriesDetail, 'val') ?? false;
break;
case 'cat':
$seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);
$temp = $this->chartDataSeriesValueSet($seriesDetail);
if ($temp !== null) {
$seriesCategory[$seriesIndex] = $temp;
}
break;
case 'val':
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
$temp = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
if ($temp !== null) {
$seriesValues[$seriesIndex] = $temp;
}
break;
case 'xVal':
$seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
$temp = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
if ($temp !== null) {
$seriesCategory[$seriesIndex] = $temp;
}
break;
case 'yVal':
$seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
$temp = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
if ($temp !== null) {
$seriesValues[$seriesIndex] = $temp;
}
break;
case 'bubbleSize':
$seriesBubbles[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
$seriesBubble = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
if ($seriesBubble !== null) {
$seriesBubbles[$seriesIndex] = $seriesBubble;
}
break;
case 'bubble3D':
@@ -819,9 +840,7 @@ class Chart
}
}
}
/** @phpstan-ignore-next-line */
$series = new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
/** @phpstan-ignore-next-line */
$series = new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $plotDirection, $smoothLine);
$series->setPlotBubbleSizes($seriesBubbles);
return $series;
@@ -19,9 +19,9 @@ class BSE
/**
* The parent BLIP Store Entry Container.
* Property is never currently read.
* Property is currently unused.
*/
private BstoreContainer $parent; // @phpstan-ignore-line
private BstoreContainer $parent;
/**
* The BLIP (Big Large Image or Picture).
@@ -43,6 +43,11 @@ class BSE
$this->parent = $parent;
}
public function getParent(): BstoreContainer
{
return $this->parent;
}
/**
* Get the BLIP.
*/
@@ -265,8 +265,12 @@ class NumberFormatter extends BaseFormatter
public static function padValue(string $value, string $baseFormat): string
{
/** @phpstan-ignore-next-line */
[$preDecimal, $postDecimal] = preg_split('/\.(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu', $baseFormat . '.?');
$preDecimal = $postDecimal = '';
$pregArray = preg_split('/\.(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu', $baseFormat . '.?');
if (is_array($pregArray)) {
$preDecimal = $pregArray[0] ?? '';
$postDecimal = $pregArray[1] ?? '';
}
$length = strlen($value);
if (str_contains($postDecimal, '?')) {
+3 -2
View File
@@ -1001,9 +1001,10 @@ class AutoFilter implements Stringable
foreach ($columnFilterTests as $columnID => $columnFilterTest) {
$cellValue = $this->workSheet->getCell($columnID . $row)->getCalculatedValue();
// Execute the filter test
/** @var callable */
$temp = [self::class, $columnFilterTest['method']];
$result // $result && // phpstan says $result is always true here
// @phpstan-ignore-next-line
= call_user_func_array([self::class, $columnFilterTest['method']], [$cellValue, $columnFilterTest['arguments']]);
= call_user_func_array($temp, [$cellValue, $columnFilterTest['arguments']]);
// If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests
if (!$result) {
break;
@@ -217,7 +217,7 @@ class MemoryDrawing extends BaseDrawing
if (function_exists('getimagesize')) {
$imageSize = @getimagesize($temporaryFileName);
if (is_array($imageSize)) {
$mimeType = $imageSize['mime'] ?? null; // @phpstan-ignore-line
$mimeType = $imageSize['mime'];
return self::supportedMimeTypes($mimeType);
}
+2 -2
View File
@@ -194,8 +194,8 @@ class Table implements Stringable
foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
$formula = $namedFormula->getValue();
if (preg_match($pattern, $formula) === 1) {
$formula = preg_replace($pattern, "{$newName}[", $formula);
$namedFormula->setValue($formula); // @phpstan-ignore-line
$formula = preg_replace($pattern, "{$newName}[", $formula) ?? '';
$namedFormula->setValue($formula);
}
}
}
@@ -232,8 +232,8 @@ class Column
foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
$formula = $namedFormula->getValue();
if (preg_match($pattern, $formula) === 1) {
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula);
$namedFormula->setValue($formula); // @phpstan-ignore-line
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula) ?? '';
$namedFormula->setValue($formula);
}
}
}
+3 -3
View File
@@ -96,7 +96,7 @@ class Meta extends WriterPart
case Properties::PROPERTY_TYPE_INTEGER:
case Properties::PROPERTY_TYPE_FLOAT:
$objWriter->writeAttribute('meta:value-type', 'float');
$objWriter->writeRawData($propertyValue); // @phpstan-ignore-line
$objWriter->writeRawData((string) $propertyValue);
break;
case Properties::PROPERTY_TYPE_BOOLEAN:
@@ -106,12 +106,12 @@ class Meta extends WriterPart
break;
case Properties::PROPERTY_TYPE_DATE:
$objWriter->writeAttribute('meta:value-type', 'date');
$dtobj = Date::dateTimeFromTimestamp($propertyValue ?? 0); // @phpstan-ignore-line
$dtobj = Date::dateTimeFromTimestamp((string) ($propertyValue ?? 0));
$objWriter->writeRawData($dtobj->format(DATE_W3C));
break;
default:
$objWriter->writeRawData($propertyValue); // @phpstan-ignore-line
$objWriter->writeRawData((string) $propertyValue);
break;
}
+4 -4
View File
@@ -52,12 +52,12 @@ class Workbook extends BIFFwriter
*/
private Parser $parser;
/**
/*
* The BIFF file size for the workbook. Not currently used.
*
* @see calcSheetOffsets()
*/
private int $biffSize; // @phpstan-ignore-line
//private int $biffSize;
/**
* XF Writers.
@@ -159,7 +159,7 @@ class Workbook extends BIFFwriter
parent::__construct();
$this->parser = $parser;
$this->biffSize = 0;
//$this->biffSize = 0;
$this->palette = [];
$this->countryCode = -1;
@@ -452,7 +452,7 @@ class Workbook extends BIFFwriter
$this->worksheetOffsets[$i] = $offset;
$offset += $this->worksheetSizes[$i];
}
$this->biffSize = $offset;
//$this->biffSize = $offset;
}
/**
-7
View File
@@ -158,19 +158,12 @@ class Xlsx extends BaseWriter
$this->writerPartWorksheet = new Worksheet($this);
// Set HashTable variables
// @phpstan-ignore-next-line
$this->bordersHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->drawingHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->fillHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->fontHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->numFmtHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->styleHashTable = new HashTable();
// @phpstan-ignore-next-line
$this->stylesConditionalHashTable = new HashTable();
}
+2 -2
View File
@@ -216,7 +216,7 @@ class DocProps extends WriterPart
switch ($propertyType) {
case Properties::PROPERTY_TYPE_INTEGER:
$objWriter->writeElement('vt:i4', $propertyValue); // @phpstan-ignore-line
$objWriter->writeElement('vt:i4', (string) $propertyValue);
break;
case Properties::PROPERTY_TYPE_FLOAT:
@@ -235,7 +235,7 @@ class DocProps extends WriterPart
break;
default:
$objWriter->writeElement('vt:lpwstr', $propertyValue); // @phpstan-ignore-line
$objWriter->writeElement('vt:lpwstr', (string) $propertyValue);
break;
}
@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Shared;
use PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer;
use PHPUnit\Framework\TestCase;
class DggContainerTest extends TestCase
{
public function testBseParent(): void
{
$container = new DggContainer\BstoreContainer();
$bse = new DggContainer\BstoreContainer\BSE();
$bse->setParent($container);
self::assertSame($container, $bse->getParent());
}
}