Skip to content
Permalink
Browse files

Fix #2061 - add config to allow suppression of string increment issues

  • Loading branch information...
muglug committed Sep 1, 2019
1 parent 5f0514b commit 51e552665e96823332522146390bc27bbb477500
@@ -311,6 +311,7 @@
<xs:element name="RedundantConditionGivenDocblockType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="ReferenceConstraintViolation" type="IssueHandlerType" minOccurs="0" />
<xs:element name="ReservedWord" type="IssueHandlerType" minOccurs="0" />
<xs:element name="StringIncrement" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TaintedInput" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TraitMethodSignatureMismatch" type="IssueHandlerType" minOccurs="0" />
<xs:element name="TooFewArguments" type="ArgumentIssueHandlerType" minOccurs="0" />
@@ -2092,6 +2092,15 @@ Emitted when using a reserved word as a class name
function foo(resource $res) : void {}
```

### StringIncrement

Emitted when attempting to increment a string - this works in PHP, but is unexpected behaviour for most people.

```php
$a = "hello";
$a++;
```

### TaintedInput

Emitted when tainted input detection is turned on
@@ -1286,6 +1286,10 @@ public static function getParentIssueType($issue_type)
return 'UnusedParam';
}
if ($issue_type === 'StringIncrement') {
return 'InvalidOperand';
}
if ($issue_type === 'TraitMethodSignatureMismatch') {
return 'MethodSignatureMismatch';
}
@@ -17,6 +17,7 @@
use Psalm\Issue\PossiblyFalseOperand;
use Psalm\Issue\PossiblyInvalidOperand;
use Psalm\Issue\PossiblyNullOperand;
use Psalm\Issue\StringIncrement;
use Psalm\IssueBuffer;
use Psalm\StatementsSource;
use Psalm\Type;
@@ -722,23 +723,14 @@ private static function hasArrayDimFetch(PhpParser\Node\Expr $expr) : bool
return false;
}
/**
* @param StatementsSource|null $statements_source
* @param PhpParser\Node\Expr $left
* @param PhpParser\Node\Expr $right
* @param PhpParser\Node $parent
* @param Type\Union|null &$result_type
*
* @return void
*/
public static function analyzeNonDivArithmeticOp(
$statements_source,
?StatementsSource $statements_source,
PhpParser\Node\Expr $left,
PhpParser\Node\Expr $right,
PhpParser\Node $parent,
Type\Union &$result_type = null,
Context $context = null
) {
?Type\Union &$result_type = null,
?Context $context = null
) : void {
$codebase = $statements_source ? $statements_source->getCodebase() : null;
$left_type = isset($left->inferredType) ? $left->inferredType : null;
@@ -854,6 +846,7 @@ public static function analyzeNonDivArithmeticOp(
$invalid_right_messages = [];
$has_valid_left_operand = false;
$has_valid_right_operand = false;
$has_string_increment = false;
foreach ($left_type->getTypes() as $left_type_part) {
foreach ($right_type->getTypes() as $right_type_part) {
@@ -871,6 +864,7 @@ public static function analyzeNonDivArithmeticOp(
$invalid_right_messages,
$has_valid_left_operand,
$has_valid_right_operand,
$has_string_increment,
$result_type
);
@@ -932,34 +926,42 @@ public static function analyzeNonDivArithmeticOp(
}
}
}
if ($has_string_increment && $statements_source) {
if (IssueBuffer::accepts(
new StringIncrement(
'Possibly unintended string increment',
new CodeLocation($statements_source, $left)
),
$statements_source->getSuppressedIssues()
)) {
// fall through
}
}
}
}
/**
* @param StatementsSource|null $statements_source
* @param \Psalm\Codebase|null $codebase
* @param Context|null $context
* @param string[] &$invalid_left_messages
* @param string[] &$invalid_right_messages
* @param bool &$has_valid_left_operand
* @param bool &$has_valid_right_operand
*
* @return Type\Union|null
*/
public static function analyzeNonDivOperands(
$statements_source,
$codebase,
private static function analyzeNonDivOperands(
?StatementsSource $statements_source,
?\Psalm\Codebase $codebase,
Config $config,
$context,
?Context $context,
PhpParser\Node\Expr $left,
PhpParser\Node\Expr $right,
PhpParser\Node $parent,
Type\Atomic $left_type_part,
Type\Atomic $right_type_part,
array &$invalid_left_messages,
array &$invalid_right_messages,
&$has_valid_left_operand,
&$has_valid_right_operand,
bool &$has_valid_left_operand,
bool &$has_valid_right_operand,
bool &$has_string_increment,
Type\Union &$result_type = null
) {
if ($left_type_part instanceof TNull || $right_type_part instanceof TNull) {
@@ -972,6 +974,24 @@ public static function analyzeNonDivOperands(
return;
}
if ($left_type_part instanceof Type\Atomic\TString
&& $right_type_part instanceof TInt
&& $parent instanceof PhpParser\Node\Expr\PostInc
) {
$has_string_increment = true;
if (!$result_type) {
$result_type = Type::getString();
} else {
$result_type = Type::combineUnionTypes(Type::getString(), $result_type);
}
$has_valid_left_operand = true;
$has_valid_right_operand = true;
return;
}
if ($left_type_part instanceof TMixed
|| $right_type_part instanceof TMixed
|| $left_type_part instanceof TTemplateParam
@@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class StringIncrement extends CodeIssue
{
}
@@ -213,6 +213,15 @@ function foo(string $s) : int {
'$d' => 'string',
],
],
'stringIncrementSuppressed' => [
'<?php
$a = "hello";
/** @psalm-suppress StringIncrement */
$a++;',
'assertions' => [
'$a' => 'string',
],
],
];
}
@@ -275,7 +284,7 @@ public function providerInvalidCodeParse()
'<?php
$a = "hello";
$a++;',
'error_message' => 'InvalidOperand',
'error_message' => 'StringIncrement',
],
'falseIncrement' => [
'<?php

0 comments on commit 51e5526

Please sign in to comment.
You can’t perform that action at this time.