Repository: VKCOM/noverify
Pull request #1122 (2021-08-28 13:54:29)

linter: improved `undefinedVariable` and `maybeUndefined` checkers messages
## Before
```
undefinedVariable: Undefined variable $name
maybeUndefined: Variable $name might have not been defined
```

## After
```
undefinedVariable: Cannot find referenced variable $name
maybeUndefined: Possibly undefined variable $name
```


Patch:
diff --git a/src/linter/block.go b/src/linter/block.go
index cbb5d14..9a4e1c8 100644
--- a/src/linter/block.go
+++ b/src/linter/block.go
@@ -1243,7 +1243,7 @@ func (b *blockWalker) enterClosure(fun *ir.ClosureExpr, haveThis bool, thisType
 		}
 
 		if !b.ctx.sc.HaveVar(v) && !byRef {
-			b.r.Report(v, LevelWarning, "undefinedVariable", "Undefined variable $%s", v.Name)
+			b.r.Report(v, LevelWarning, "undefinedVariable", "Cannot find referenced variable $%s", v.Name)
 		}
 
 		typ, ok := b.ctx.sc.GetVarNameType(v.Name)
diff --git a/src/linter/root.go b/src/linter/root.go
index f4ff55d..d850e3e 100644
--- a/src/linter/root.go
+++ b/src/linter/root.go
@@ -634,9 +634,9 @@ func (d *rootWalker) reportUndefinedVariable(v ir.Node, maybeHave bool, path iru
 	}
 
 	if maybeHave {
-		d.Report(sv, LevelWarning, "maybeUndefined", "Variable $%s might have not been defined", sv.Name)
+		d.Report(sv, LevelWarning, "maybeUndefined", "Possibly undefined variable $%s", sv.Name)
 	} else {
-		d.Report(sv, LevelError, "undefinedVariable", "Undefined variable $%s", sv.Name)
+		d.Report(sv, LevelError, "undefinedVariable", "Cannot find referenced variable $%s", sv.Name)
 	}
 }
 


Test patch:
diff --git a/src/tests/checkers/basic_test.go b/src/tests/checkers/basic_test.go
index 044b655..87fada0 100644
--- a/src/tests/checkers/basic_test.go
+++ b/src/tests/checkers/basic_test.go
@@ -168,9 +168,9 @@ foreach ($xs as $x) {
 $_ = [$x]; // Bad
 `)
 	test.Expect = []string{
-		`Variable $k might have not been defined`,
-		`Variable $v might have not been defined`,
-		`Variable $x might have not been defined`,
+		`Possibly undefined variable $k`,
+		`Possibly undefined variable $v`,
+		`Possibly undefined variable $x`,
 	}
 	test.RunAndMatch()
 }
@@ -712,8 +712,8 @@ class Foo {
 `)
 
 	test.Expect = []string{
-		"Undefined variable $argv",
-		"Undefined variable $argc",
+		"Cannot find referenced variable $argv",
+		"Cannot find referenced variable $argc",
 	}
 
 	linttest.RunFilterMatch(test, "undefinedVariable")
@@ -923,8 +923,8 @@ func TestOrDie2(t *testing.T) {
 $undef1 or die($undef2);
 `)
 	test.Expect = []string{
-		"Undefined variable $undef1",
-		"Undefined variable $undef2",
+		"Cannot find referenced variable $undef1",
+		"Cannot find referenced variable $undef2",
 	}
 	test.RunAndMatch()
 }
@@ -1001,7 +1001,7 @@ function foo() {
 `)
 	test.Expect = []string{
 		`Variable $x is unused`,
-		`Undefined variable $y`,
+		`Cannot find referenced variable $y`,
 	}
 	test.RunAndMatch()
 }
@@ -1256,7 +1256,7 @@ func TestFunctionReferenceParamsInAnonymousFunction(t *testing.T) {
 			$result = 1;
 		};
 	}`)
-	test.Expect = []string{"Undefined variable $a"}
+	test.Expect = []string{"Cannot find referenced variable $a"}
 	test.RunAndMatch()
 }
 
@@ -1486,8 +1486,8 @@ func TestEmptyVar(t *testing.T) {
 		return $x2;
 	}`)
 	test.Expect = []string{
-		`Undefined variable $x1`,
-		`Undefined variable $x2`,
+		`Cannot find referenced variable $x1`,
+		`Cannot find referenced variable $x2`,
 	}
 	test.RunAndMatch()
 }
@@ -1504,7 +1504,7 @@ function f() {
   echo $y; // But should be undefined here.
 }
 `)
-	test.Expect = []string{`Undefined variable $y`}
+	test.Expect = []string{`Cannot find referenced variable $y`}
 	test.RunAndMatch()
 }
 
@@ -1704,17 +1704,17 @@ func TestArrowFunction(t *testing.T) {
 		echo $w; // Undefined $w
 	}`)
 	test.Expect = []string{
-		`Undefined variable $undefined_variable`,
-		`Variable $maybe_defined might have not been defined`,
+		`Cannot find referenced variable $undefined_variable`,
+		`Possibly undefined variable $maybe_defined`,
 		`Variable $a is unused (use $_ to ignore this inspection or specify --unused-var-regex flag)`,
 		`Variable $a is unused (use $_ to ignore this inspection or specify --unused-var-regex flag)`,
 		`Variable $a is unused (use $_ to ignore this inspection or specify --unused-var-regex flag)`,
 		`Variable $a is unused (use $_ to ignore this inspection or specify --unused-var-regex flag)`,
-		`Undefined variable $a`,
-		`Undefined variable $x`,
-		`Undefined variable $y`,
-		`Undefined variable $w`,
-		`Variable $maybe_defined might have not been defined`,
+		`Cannot find referenced variable $a`,
+		`Cannot find referenced variable $x`,
+		`Cannot find referenced variable $y`,
+		`Cannot find referenced variable $w`,
+		`Possibly undefined variable $maybe_defined`,
 	}
 	test.RunAndMatch()
 }
@@ -2112,8 +2112,8 @@ function f() {
 	`)
 
 	test.Expect = []string{
-		"Undefined variable $x",
-		"Undefined variable $y",
+		"Cannot find referenced variable $x",
+		"Cannot find referenced variable $y",
 	}
 	linttest.RunFilterMatch(test, "undefinedVariable")
 }
@@ -2325,7 +2325,7 @@ function f($a) {
 `,
 	)
 	test.Expect = []string{
-		"Undefined variable $y1",
+		"Cannot find referenced variable $y1",
 	}
 	test.RunAndMatch()
 }
@@ -2352,8 +2352,8 @@ function f($a) {
 `,
 	)
 	test.Expect = []string{
-		"Variable $b might have not been defined",
-		"Variable $c might have not been defined",
+		"Possibly undefined variable $b",
+		"Possibly undefined variable $c",
 	}
 	test.RunAndMatch()
 }
@@ -2394,8 +2394,8 @@ function f2($v) {
 	// It could be more precise to report 2 "might have not been defined",
 	// but at least we report both usages. Can be improved in future.
 	test.Expect = []string{
-		`Undefined variable $x`,
-		`Variable $x might have not been defined`,
+		`Cannot find referenced variable $x`,
+		`Possibly undefined variable $x`,
 	}
 	test.RunAndMatch()
 }
@@ -2418,8 +2418,8 @@ function f2($v) {
 }
 `)
 	test.Expect = []string{
-		`Variable $x might have not been defined`,
-		`Undefined variable $x`,
+		`Possibly undefined variable $x`,
+		`Cannot find referenced variable $x`,
 	}
 	test.RunAndMatch()
 }
@@ -2443,7 +2443,7 @@ function f() {
 }
 `)
 	test.Expect = []string{
-		`Undefined variable $e`,
+		`Cannot find referenced variable $e`,
 	}
 	test.RunAndMatch()
 }
diff --git a/src/tests/checkers/catch_test.go b/src/tests/checkers/catch_test.go
index 8c613e3..22b9142 100644
--- a/src/tests/checkers/catch_test.go
+++ b/src/tests/checkers/catch_test.go
@@ -161,9 +161,9 @@ function f() {
 }
 `)
 	test.Expect = []string{
-		`Variable $c might have not been defined`,
-		`Variable $d might have not been defined`,
-		`Variable $f might have not been defined`,
+		`Possibly undefined variable $c`,
+		`Possibly undefined variable $d`,
+		`Possibly undefined variable $f`,
 	}
 	test.RunAndMatch()
 }
@@ -218,11 +218,11 @@ function f() {
 }
 `)
 	test.Expect = []string{
-		`Variable $b might have not been defined`,
+		`Possibly undefined variable $b`,
 		`Unreachable code`,
-		`Undefined variable $d`,
-		`Undefined variable $e`,
-		`Variable $g might have not been defined`,
+		`Cannot find referenced variable $d`,
+		`Cannot find referenced variable $e`,
+		`Possibly undefined variable $g`,
 	}
 	test.RunAndMatch()
 }
diff --git a/src/tests/checkers/oop_test.go b/src/tests/checkers/oop_test.go
index 40db07a..437cded 100644
--- a/src/tests/checkers/oop_test.go
+++ b/src/tests/checkers/oop_test.go
@@ -840,7 +840,7 @@ func TestClosureLateBinding(t *testing.T) {
 	})();
 	`)
 	test.Expect = []string{
-		"Undefined variable $a",
+		"Cannot find referenced variable $a",
 		"Call to undefined method {undefined}->method()",
 	}
 	linttest.RunFilterMatch(test, "undefinedVariable", "undefinedMethod")
diff --git a/src/tests/checkers/strict_mixed_test.go b/src/tests/checkers/strict_mixed_test.go
index e8750f2..f34b6c7 100644
--- a/src/tests/checkers/strict_mixed_test.go
+++ b/src/tests/checkers/strict_mixed_test.go
@@ -46,7 +46,7 @@ function f(stdClass $a) {
 	test.Expect = []string{
 		"Call to undefined method {mixed}->f()",
 		"Call to undefined method {object}->f()",
-		"Undefined variable $a",
+		"Cannot find referenced variable $a",
 		"Call to undefined method {undefined}->f()",
 		"Call to undefined method {unknown_from_list}->f()",
 		"Call to undefined method {\\Foo}->f()",
@@ -93,7 +93,7 @@ function f(stdClass $a) {
 `,
 	)
 	test.Expect = []string{
-		"Undefined variable $a",
+		"Cannot find referenced variable $a",
 		"Call to undefined method {\\Foo}->f()",
 	}
 	test.RunAndMatch()
diff --git a/src/tests/golden/testdata/parsedown/golden.txt b/src/tests/golden/testdata/parsedown/golden.txt
index dd0d7f3..c061c1f 100644
--- a/src/tests/golden/testdata/parsedown/golden.txt
+++ b/src/tests/golden/testdata/parsedown/golden.txt
@@ -142,10 +142,10 @@ MAYBE   typeHint: Specify the type for the parameter $Elements in PHPDoc, 'array
 MAYBE   typeHint: Specify the type for the parameter $Element in PHPDoc, 'array' type hint too generic at testdata/parsedown/parsedown.php:1689
     protected function element(array $Element)
                        ^^^^^^^
-WARNING maybeUndefined: Variable $text might have not been defined at testdata/parsedown/parsedown.php:1755
+WARNING maybeUndefined: Possibly undefined variable $text at testdata/parsedown/parsedown.php:1755
                     $markup .= self::escape($text, true);
                                             ^^^^^
-WARNING maybeUndefined: Variable $text might have not been defined at testdata/parsedown/parsedown.php:1759
+WARNING maybeUndefined: Possibly undefined variable $text at testdata/parsedown/parsedown.php:1759
                     $markup .= $text;
                                ^^^^^
 MAYBE   typeHint: Specify the type for the parameter $Elements in PHPDoc, 'array' type hint too generic at testdata/parsedown/parsedown.php:1773
diff --git a/src/tests/golden/testdata/qrcode/golden.txt b/src/tests/golden/testdata/qrcode/golden.txt
index d5be167..912349e 100644
--- a/src/tests/golden/testdata/qrcode/golden.txt
+++ b/src/tests/golden/testdata/qrcode/golden.txt
@@ -22,7 +22,7 @@ WARNING unused: Variable $mode is unused (use $_ to ignore this inspection or sp
 WARNING switchDefault: Add 'default' branch to avoid unexpected unhandled condition values at testdata/qrcode/qrcode.php:203
     switch ($mode) {
     ^
-WARNING maybeUndefined: Variable $code might have not been defined at testdata/qrcode/qrcode.php:221
+WARNING maybeUndefined: Possibly undefined variable $code at testdata/qrcode/qrcode.php:221
     while (count($code) % 8) {
                  ^^^^^
 WARNING caseBreak: Add break or '// fallthrough' to the end of the case at testdata/qrcode/qrcode.php:297
diff --git a/src/tests/regression/issue128_test.go b/src/tests/regression/issue128_test.go
index d7df8b4..d21a41a 100644
--- a/src/tests/regression/issue128_test.go
+++ b/src/tests/regression/issue128_test.go
@@ -40,13 +40,13 @@ function bad1($v) {
 $_ = $bad1;
 `)
 	test.Expect = []string{
-		`Undefined variable $bad0`,
-		`Undefined variable $bad1`, // At local scope
-		`Undefined variable $bad1`, // At global scope
-		`Undefined variable $bad2`,
-		`Undefined variable $bad3`,
+		`Cannot find referenced variable $bad0`,
+		`Cannot find referenced variable $bad1`, // At local scope
+		`Cannot find referenced variable $bad1`, // At global scope
+		`Cannot find referenced variable $bad2`,
+		`Cannot find referenced variable $bad3`,
 		`Property {mixed}->x does not exist`,
-		`Undefined variable $y1`,
+		`Cannot find referenced variable $y1`,
 	}
 	test.RunAndMatch()
 }
diff --git a/src/tests/regression/issue252_test.go b/src/tests/regression/issue252_test.go
index 818039a..a2d920b 100644
--- a/src/tests/regression/issue252_test.go
+++ b/src/tests/regression/issue252_test.go
@@ -47,7 +47,7 @@ function alt_switch($v) {
   endswitch;
 }`)
 	test.Expect = []string{
-		`Variable $x1 might have not been defined`,
+		`Possibly undefined variable $x1`,
 		`Add break or '// fallthrough' to the end of the case`,
 	}
 	test.RunAndMatch()
diff --git a/src/tests/regression/issue26_test.go b/src/tests/regression/issue26_test.go
index 6a1d0f2..6e2a994 100644
--- a/src/tests/regression/issue26_test.go
+++ b/src/tests/regression/issue26_test.go
@@ -20,7 +20,7 @@ func TestIssue26_1(t *testing.T) {
 		// After the block all vars are undefined again.
 		$_ = $x;
 	}`)
-	test.Expect = []string{"Undefined variable $y"}
+	test.Expect = []string{"Cannot find referenced variable $y"}
 	test.RunAndMatch()
 }
 
@@ -49,7 +49,7 @@ func TestIssue26_3(t *testing.T) {
 		}
 	}`)
 	test.Expect = []string{
-		"Undefined variable $x",
+		"Cannot find referenced variable $x",
 		"Unknown variable variable $$y used",
 	}
 	test.RunAndMatch()
diff --git a/src/tests/regression/issue288_test.go b/src/tests/regression/issue288_test.go
index 2034949..4ce757e 100644
--- a/src/tests/regression/issue288_test.go
+++ b/src/tests/regression/issue288_test.go
@@ -36,10 +36,10 @@ $_ = isset($x) && isset($y) ? $x : 0;
 $_ = $x instanceof Box ? 0 : 1;
 `)
 	test.Expect = []string{
-		`Undefined variable $badvar`,
-		`Undefined variable $b1`,
-		`Undefined variable $b2`,
-		`Undefined variable $b3`,
+		`Cannot find referenced variable $badvar`,
+		`Cannot find referenced variable $b1`,
+		`Cannot find referenced variable $b2`,
+		`Cannot find referenced variable $b3`,
 		`Property {mixed}->item2 does not exist`,
 	}
 	test.RunAndMatch()