Repository: VKCOM/noverify
Pull request #1081 (2021-08-16 09:13:19)

cmd: improved `strangeCast` checker
Now no warning will be issued for unary plus with
constant expression.

For example:
```php
$a = +100;
$a = +CONST_A;
```


Patch:
diff --git a/src/cmd/embeddedrules/rules.php b/src/cmd/embeddedrules/rules.php
index b2b6c2e..7c754cd 100644
--- a/src/cmd/embeddedrules/rules.php
+++ b/src/cmd/embeddedrules/rules.php
@@ -438,9 +438,7 @@ function langDeprecated() {
 }
 
 /**
- * @comment Report a strange way of type cast.
- * @before  $x.""
- * @after   (string)$x
+ * @extends
  */
 function strangeCast() {
     /**
@@ -460,11 +458,6 @@ function strangeCast() {
         0 + $x;
         0.0 + $x;
     }
-
-    /**
-     * @warning Unary plus, possible type cast, use an explicit cast to int or float instead of using the unary plus
-     */
-    +$x;
 }
 
 /**
diff --git a/src/linter/block_linter.go b/src/linter/block_linter.go
index 57e4c5f..e6a3ec3 100644
--- a/src/linter/block_linter.go
+++ b/src/linter/block_linter.go
@@ -70,6 +70,9 @@ func (b *blockLinter) enterNode(n ir.Node) {
 	case *ir.GlobalStmt:
 		b.checkGlobalStmt(n)
 
+	case *ir.UnaryPlusExpr:
+		b.checkUnaryPlus(n)
+
 	case *ir.BitwiseAndExpr:
 		b.checkBitwiseOp(n, n.Left, n.Right)
 	case *ir.BitwiseOrExpr:
@@ -189,6 +192,15 @@ func (b *blockLinter) enterNode(n ir.Node) {
 	}
 }
 
+func (b *blockLinter) checkUnaryPlus(n *ir.UnaryPlusExpr) {
+	val := constfold.Eval(b.classParseState(), n.Expr)
+	if val.IsValid() {
+		return
+	}
+
+	b.report(n, LevelWarning, "strangeCast", "Unary plus with non-constant expression, possible type cast, use an explicit cast to int or float instead of using the unary plus")
+}
+
 func (b *blockLinter) checkClass(class *ir.ClassStmt) {
 	const classMethod = 0
 	const classOtherMember = 1
diff --git a/src/linter/report.go b/src/linter/report.go
index e3b4b37..aea62dc 100644
--- a/src/linter/report.go
+++ b/src/linter/report.go
@@ -882,6 +882,15 @@ function main(): void {
   makeHello($name, $age);
 }`,
 		},
+
+		{
+			Name:     "strangeCast",
+			Default:  true,
+			Quickfix: false,
+			Comment:  `Report a strange way of type cast.`,
+			Before:   `$x.""`,
+			After:    `(string)$x`,
+		},
 	}
 
 	for _, info := range allChecks {


Test patch:
diff --git a/src/tests/inline/testdata/embeddedrules/strangeCast.php b/src/tests/inline/testdata/embeddedrules/strangeCast.php
index 582f60b..4a0ec32 100644
--- a/src/tests/inline/testdata/embeddedrules/strangeCast.php
+++ b/src/tests/inline/testdata/embeddedrules/strangeCast.php
@@ -1,5 +1,7 @@
 <?php
 
+const A = 10;
+
 function strangeCast() {
     $x = 100;
 
@@ -10,12 +12,14 @@ function strangeCast() {
 
     $y = "10";
 
-    $_ = 0 + $y; // want `Addition with zero, possible type cast, use an explicit cast to int or float instead of zero addition`
-    $_ = $y + 10; // ok
+    $_ = 0 + $y;   // want `Addition with zero, possible type cast, use an explicit cast to int or float instead of zero addition`
+    $_ = $y + 10;  // ok
     $_ = 0.0 + $y; // want `Addition with zero, possible type cast, use an explicit cast to int or float instead of zero addition`
 
     $string = "10";
 
-    $_ = +$string; // want `Unary plus, possible type cast, use an explicit cast to int or float instead of using the unary plus`
+    $_ = +$string; // want `Unary plus with non-constant expression, possible type cast, use an explicit cast to int or float instead of using the unary plus`
+    $_ = +100;     // ok, constant expression
+    $_ = +A;       // ok, constant expression
     $_ = -$string; // ok, unary minus
 }