Repository: VKCOM/noverify
Pull request #774 (2020-09-09 07:33:48)

linter: added quick fix for arraySyntax


Patch:
diff --git a/src/linter/block_linter.go b/src/linter/block_linter.go
index 7742192..5af3518 100644
--- a/src/linter/block_linter.go
+++ b/src/linter/block_linter.go
@@ -1,6 +1,7 @@
 package linter
 
 import (
+	"bytes"
 	"fmt"
 	"strings"
 
@@ -9,6 +10,7 @@ import (
 	"github.com/VKCOM/noverify/src/ir/irutil"
 	"github.com/VKCOM/noverify/src/meta"
 	"github.com/VKCOM/noverify/src/php/parser/freefloating"
+	"github.com/VKCOM/noverify/src/quickfix"
 	"github.com/VKCOM/noverify/src/solver"
 )
 
@@ -471,9 +473,28 @@ func (b *blockLinter) checkContinueStmt(c *ir.ContinueStmt) {
 	}
 }
 
+func (b *blockLinter) addFixForArray(arr *ir.ArrayExpr) {
+	if !ApplyQuickFixes {
+		return
+	}
+
+	from := arr.Position.StartPos
+	to := arr.Position.EndPos
+	have := b.walker.r.fileContents[from:to]
+	have = bytes.TrimPrefix(have, []byte("array("))
+	have = bytes.TrimSuffix(have, []byte(")"))
+
+	b.walker.r.ctx.fixes = append(b.walker.r.ctx.fixes, quickfix.TextEdit{
+		StartPos:    arr.Position.StartPos,
+		EndPos:      arr.Position.EndPos,
+		Replacement: fmt.Sprintf("[%s]", string(have)),
+	})
+}
+
 func (b *blockLinter) checkArray(arr *ir.ArrayExpr) {
 	if !arr.ShortSyntax {
 		b.report(arr, LevelDoNotReject, "arraySyntax", "Use of old array syntax (use short form instead)")
+		b.addFixForArray(arr)
 	}
 
 	items := arr.Items
diff --git a/src/linter/report.go b/src/linter/report.go
index 87e5e6c..6561565 100644
--- a/src/linter/report.go
+++ b/src/linter/report.go
@@ -161,7 +161,7 @@ func init() {
 		{
 			Name:     "arraySyntax",
 			Default:  true,
-			Quickfix: false,
+			Quickfix: true,
 			Comment:  `Report usages of old array() syntax.`,
 			Before:   `array(1, 2)`,
 			After:    `[1, 2]`,


Test patch:
diff --git a/src/tests/golden/testdata/quickfix/arraySyntax.php b/src/tests/golden/testdata/quickfix/arraySyntax.php
new file mode 100644
index 0000000..8d65301
--- /dev/null
+++ b/src/tests/golden/testdata/quickfix/arraySyntax.php
@@ -0,0 +1,41 @@
+<?php
+
+class Foo {}
+
+function f() {
+    $_ = array();
+    $_ = array(1,2,);
+    $_ = array(1,2,3);
+    $_ = array(new Foo, new Foo);
+    $_ = array("info" => new Foo, new Foo);
+    $_ = array("info" => new Foo, "for" => 2, "home" => function() {});
+
+    $_ = array(
+        "info" => new Foo,
+        new Foo
+    );
+    $_ = array(
+        1,2,
+        3,4,
+    );
+    $_ = array( new Foo,    "Hello",
+        1,2,
+        3,4,
+    );
+
+    b(array(1,2));
+
+    // So far, we cannot replace recursively, so replacement in
+    // multidimensional arrays will only be performed for internal arrays.
+    $_ = array(array(1,2,3), array(1,2,3));
+    $_ = array(array("info" => new Foo, "for" => 2, "home" => function() {}), array(1,2,3));
+}
+
+function b($a) {
+    switch ($a) {
+    case 1:
+        return array(1, 2, 3);
+    case 2:
+        return array("info" => new Foo, "for" => 2, "home" => function() {});
+    }
+}
diff --git a/src/tests/golden/testdata/quickfix/arraySyntax.php.fix.expected b/src/tests/golden/testdata/quickfix/arraySyntax.php.fix.expected
new file mode 100644
index 0000000..bbf14c2
--- /dev/null
+++ b/src/tests/golden/testdata/quickfix/arraySyntax.php.fix.expected
@@ -0,0 +1,41 @@
+<?php
+
+class Foo {}
+
+function f() {
+    $_ = [];
+    $_ = [1,2,];
+    $_ = [1,2,3];
+    $_ = [new Foo, new Foo];
+    $_ = ["info" => new Foo, new Foo];
+    $_ = ["info" => new Foo, "for" => 2, "home" => function() {}];
+
+    $_ = [
+        "info" => new Foo,
+        new Foo
+    ];
+    $_ = [
+        1,2,
+        3,4,
+    ];
+    $_ = [ new Foo,    "Hello",
+        1,2,
+        3,4,
+    ];
+
+    b([1,2]);
+
+    // So far, we cannot replace recursively, so replacement in
+    // multidimensional arrays will only be performed for internal arrays.
+    $_ = array([1,2,3], [1,2,3]);
+    $_ = array(["info" => new Foo, "for" => 2, "home" => function() {}], [1,2,3]);
+}
+
+function b($a) {
+    switch ($a) {
+    case 1:
+        return [1, 2, 3];
+    case 2:
+        return ["info" => new Foo, "for" => 2, "home" => function() {}];
+    }
+}