From 0334dd7cc4a7fcfba49b70c976c2e5b42ede6e54 Mon Sep 17 00:00:00 2001 From: Makhnev Petr <51853996+i582@users.noreply.github.com> Date: Sat, 21 Aug 2021 19:10:18 +0300 Subject: [PATCH] linter: split `undefined` checker into the following (#1092) - maybeUndefined - undefinedConstant - undefinedFunction - undefinedMethod - undefinedProperty - undefinedType - undefinedVariable * tests: fixed baseline --- docs/checkers_doc.md | 151 ++++++++++++++++-- src/linter/block.go | 2 +- src/linter/block_linter.go | 14 +- src/linter/report.go | 79 ++++++++- src/linter/root.go | 8 +- src/tests/checkers/basic_test.go | 4 +- src/tests/checkers/oop_test.go | 6 +- .../testdata/baseline-test/baseline.json | 11 +- .../golden/testdata/baseline-test/golden.txt | 2 +- src/tests/golden/testdata/mustache/golden.txt | 8 +- .../golden/testdata/parsedown/golden.txt | 4 +- .../golden/testdata/phprocksyd/golden.txt | 2 +- src/tests/golden/testdata/qrcode/golden.txt | 2 +- .../golden/testdata/underscore/golden.txt | 22 +-- src/tests/regression/issue16_test.go | 2 +- src/tests/regression/issue288_test.go | 2 +- 16 files changed, 259 insertions(+), 60 deletions(-) diff --git a/docs/checkers_doc.md b/docs/checkers_doc.md index 1a95856a..8545a91a 100644 --- a/docs/checkers_doc.md +++ b/docs/checkers_doc.md @@ -4,7 +4,7 @@ | Total checks | Checks enabled by default | Disabled checks by default | Autofixable checks | | ------------ | ------------------------- | -------------------------- | ------------------ | -| 89 | 79 | 10 | 12 | +| 95 | 85 | 10 | 12 | ## Table of contents - Enabled by default - [`accessLevel` checker](#accesslevel-checker) @@ -48,6 +48,7 @@ - [`keywordCase` checker](#keywordcase-checker) - [`linterError` checker](#lintererror-checker) - [`magicMethodDecl` checker](#magicmethoddecl-checker) + - [`maybeUndefined` checker](#maybeundefined-checker) - [`methodSignatureMismatch` checker](#methodsignaturemismatch-checker) - [`misspellComment` checker](#misspellcomment-checker) - [`misspellName` checker](#misspellname-checker) @@ -81,7 +82,12 @@ - [`syntax` checker](#syntax-checker) - [`ternarySimplify` checker (autofixable)](#ternarysimplify-checker) - [`unaryRepeat` checker (autofixable)](#unaryrepeat-checker) - - [`undefined` checker](#undefined-checker) + - [`undefinedConstant` checker](#undefinedconstant-checker) + - [`undefinedFunction` checker](#undefinedfunction-checker) + - [`undefinedMethod` checker](#undefinedmethod-checker) + - [`undefinedProperty` checker](#undefinedproperty-checker) + - [`undefinedType` checker](#undefinedtype-checker) + - [`undefinedVariable` checker](#undefinedvariable-checker) - [`unimplemented` checker](#unimplemented-checker) - [`unused` checker](#unused-checker) - [`varShadow` checker](#varshadow-checker) @@ -940,6 +946,31 @@ class Foo {


+### `maybeUndefined` checker + +#### Description + +Report usages of potentially undefined symbols. + +#### Non-compliant code: +```php +if ($cond) { + $v = 10; +} +return $v; // $v may be undefined. +``` + +#### Compliant code: +```php +$v = 0; // Default value. +if ($cond) { + $v = 10; +} +return $v; +``` +


+ + ### `methodSignatureMismatch` checker #### Description @@ -1591,29 +1622,127 @@ echo (bool) $a;


-### `undefined` checker +### `undefinedConstant` checker #### Description -Report usages of potentially undefined symbols. +Report usages of undefined constant. #### Non-compliant code: ```php -if ($cond) { - $v = 10; +echo PI; +``` + +#### Compliant code: +```php +echo M_PI; +``` +


+ + +### `undefinedFunction` checker + +#### Description + +Report usages of undefined function. + +#### Non-compliant code: +```php +undefinedFunc(); +``` + +#### Compliant code: +```php +definedFunc(); +``` +


+ + +### `undefinedMethod` checker + +#### Description + +Report usages of undefined method. + +#### Non-compliant code: +```php +class Foo { + public function method() {}; } -return $v; // $v may be undefined. +(new Foo)->method2(); // method2 is undefined. ``` #### Compliant code: ```php -$v = 0; // Default value. -if ($cond) { - $v = 10; +class Foo { + public function method() {} } -return $v; +(new Foo)->method(); +``` +


+ + +### `undefinedProperty` checker + +#### Description + +Report usages of undefined property. + +#### Non-compliant code: +```php +class Foo { + public string $prop; +} + +(new Foo)->prop2; // prop2 is undefined. +``` + +#### Compliant code: +```php +class Foo { + public string $prop; +} + +(new Foo)->prop; +``` +


+ + +### `undefinedType` checker + +#### Description + +Report usages of undefined type. + +#### Non-compliant code: +```php +class Foo extends UndefinedClass {} +``` + +#### Compliant code: +```php +class Foo extends DefinedClass {} +``` +


+ + +### `undefinedVariable` checker + +#### Description + +Report usages of undefined variable. + +#### Non-compliant code: +```php +echo $undefinedVar; +``` + +#### Compliant code: +```php +$definedVar = 100; +echo $definedVar; ```


diff --git a/src/linter/block.go b/src/linter/block.go index 5a0c8a90..b2df75b9 100644 --- a/src/linter/block.go +++ b/src/linter/block.go @@ -1236,7 +1236,7 @@ func (b *blockWalker) enterClosure(fun *ir.ClosureExpr, haveThis bool, thisType } if !b.ctx.sc.HaveVar(v) && !byRef { - b.r.Report(v, LevelWarning, "undefined", "Undefined variable $%s", v.Name) + b.r.Report(v, LevelWarning, "undefinedVariable", "Undefined variable $%s", v.Name) } typ, ok := b.ctx.sc.GetVarNameType(v.Name) diff --git a/src/linter/block_linter.go b/src/linter/block_linter.go index 740a0207..fe0b78d2 100644 --- a/src/linter/block_linter.go +++ b/src/linter/block_linter.go @@ -561,7 +561,7 @@ func (b *blockLinter) checkConstFetch(e *ir.ConstFetchExpr) { b.report(e.Constant, LevelError, "constCase", "Constant '%s' should be used in lower case as '%s'", nm, expected) b.addFixForBuiltInConstantCase(e.Constant, expected) default: - b.report(e.Constant, LevelError, "undefined", "Undefined constant %s", nm) + b.report(e.Constant, LevelError, "undefinedConstant", "Undefined constant %s", nm) } } } @@ -942,7 +942,7 @@ func (b *blockLinter) checkDeprecatedFunctionCall(e *ir.FunctionCallExpr, call * func (b *blockLinter) checkFunctionAvailability(e *ir.FunctionCallExpr, call *funcCallInfo) { if !call.isFound && !b.walker.ctx.customFunctionExists(e.Function) { - b.report(e.Function, LevelError, "undefined", "Call to undefined function %s", utils.NameNodeToString(e.Function)) + b.report(e.Function, LevelError, "undefinedFunction", "Call to undefined function %s", utils.NameNodeToString(e.Function)) } } @@ -1175,7 +1175,7 @@ func (b *blockLinter) checkMethodCall(e *ir.MethodCallExpr) { // The method is undefined, but we permit calling it if `method_exists` // was called prior to that call. if !b.walker.ctx.customMethodExists(e.Variable, call.methodName) && needShowUndefinedMethod { - b.report(e.Method, LevelError, "undefined", "Call to undefined method {%s}->%s()", call.methodCallerType, call.methodName) + b.report(e.Method, LevelError, "undefinedMethod", "Call to undefined method {%s}->%s()", call.methodCallerType, call.methodName) } } else if !call.isMagic && !parseState.IsTrait { // Method is defined. @@ -1213,7 +1213,7 @@ func (b *blockLinter) checkStaticCall(e *ir.StaticCallExpr) { } if !call.isFound && !call.isMagic && !b.classParseState().IsTrait { - b.report(e.Call, LevelError, "undefined", "Call to undefined method %s::%s()", call.className, call.methodName) + b.report(e.Call, LevelError, "undefinedMethod", "Call to undefined method %s::%s()", call.className, call.methodName) } else if !call.isParentCall && !call.methodInfo.Info.IsStatic() && !call.isMagic && !b.classParseState().IsTrait { // Method is defined. // parent::f() is permitted. @@ -1247,7 +1247,7 @@ func (b *blockLinter) checkPropertyFetch(e *ir.PropertyFetchExpr) { !b.classParseState().IsTrait && !b.walker.isThisInsideClosure(e.Variable) && needShowUndefinedProperty { - b.report(e.Property, LevelError, "undefined", "Property {%s}->%s does not exist", fetch.propertyFetchType, fetch.propertyNode.Value) + b.report(e.Property, LevelError, "undefinedProperty", "Property {%s}->%s does not exist", fetch.propertyFetchType, fetch.propertyNode.Value) } if fetch.isFound && !fetch.isMagic && !canAccess(b.classParseState(), fetch.className, fetch.info.AccessLevel) { @@ -1264,7 +1264,7 @@ func (b *blockLinter) checkStaticPropertyFetch(e *ir.StaticPropertyFetchExpr) { b.checkClassSpecialNameCase(e, fetch.className) if !fetch.isFound && !b.classParseState().IsTrait { - b.report(e.Property, LevelError, "undefined", "Property %s::$%s does not exist", fetch.className, fetch.propertyName) + b.report(e.Property, LevelError, "undefinedProperty", "Property %s::$%s does not exist", fetch.className, fetch.propertyName) } if fetch.isFound && !canAccess(b.classParseState(), fetch.info.ClassName, fetch.info.Info.AccessLevel) { @@ -1288,7 +1288,7 @@ func (b *blockLinter) checkClassConstFetch(e *ir.ClassConstFetchExpr) { } if !fetch.isFound && !b.classParseState().IsTrait { - b.walker.r.Report(e.ConstantName, LevelError, "undefined", "Class constant %s::%s does not exist", fetch.className, fetch.constName) + b.walker.r.Report(e.ConstantName, LevelError, "undefinedConstant", "Class constant %s::%s does not exist", fetch.className, fetch.constName) } if fetch.isFound && !canAccess(b.classParseState(), fetch.implClassName, fetch.info.AccessLevel) { diff --git a/src/linter/report.go b/src/linter/report.go index 0a294ba9..c456cb6e 100644 --- a/src/linter/report.go +++ b/src/linter/report.go @@ -344,21 +344,90 @@ public function process($acts, $config) { }, { - Name: "undefined", + Name: "undefinedProperty", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined property.`, + Before: `class Foo { + public string $prop; +} + +(new Foo)->prop2; // prop2 is undefined.`, + After: `class Foo { + public string $prop; +} + +(new Foo)->prop;`, + }, + + { + Name: "undefinedMethod", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined method.`, + Before: `class Foo { + public function method() {}; +} + +(new Foo)->method2(); // method2 is undefined.`, + After: `class Foo { + public function method() {} +} + +(new Foo)->method();`, + }, + + { + Name: "undefinedConstant", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined constant.`, + Before: `echo PI;`, + After: `echo M_PI;`, + }, + + { + Name: "undefinedFunction", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined function.`, + Before: `undefinedFunc();`, + After: `definedFunc();`, + }, + + { + Name: "undefinedVariable", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined variable.`, + Before: `echo $undefinedVar;`, + After: `$definedVar = 100; +echo $definedVar;`, + }, + + { + Name: "maybeUndefined", Default: true, Quickfix: false, Comment: `Report usages of potentially undefined symbols.`, Before: `if ($cond) { $v = 10; } -return $v; // $v may be undefined. -`, +return $v; // $v may be undefined.`, After: `$v = 0; // Default value. if ($cond) { $v = 10; } -return $v; -`, +return $v;`, + }, + + { + Name: "undefinedType", + Default: true, + Quickfix: false, + Comment: `Report usages of undefined type.`, + Before: `class Foo extends UndefinedClass {}`, + After: `class Foo extends DefinedClass {}`, }, { diff --git a/src/linter/root.go b/src/linter/root.go index 2d11c632..9ff81324 100644 --- a/src/linter/root.go +++ b/src/linter/root.go @@ -569,7 +569,7 @@ func (d *rootWalker) reportHash(loc *ir.Location, contextLine []byte, checkName, func (d *rootWalker) reportUndefinedVariable(v ir.Node, maybeHave bool) { sv, ok := v.(*ir.SimpleVar) if !ok { - d.Report(v, LevelWarning, "undefined", "Unknown variable variable %s used", + d.Report(v, LevelWarning, "undefinedVariable", "Unknown variable variable %s used", utils.NameNodeToString(v)) return } @@ -579,9 +579,9 @@ func (d *rootWalker) reportUndefinedVariable(v ir.Node, maybeHave bool) { } if maybeHave { - d.Report(sv, LevelWarning, "undefined", "Variable $%s might have not been defined", sv.Name) + d.Report(sv, LevelWarning, "maybeUndefined", "Variable $%s might have not been defined", sv.Name) } else { - d.Report(sv, LevelError, "undefined", "Undefined variable $%s", sv.Name) + d.Report(sv, LevelError, "undefinedVariable", "Undefined variable $%s", sv.Name) } } @@ -2309,7 +2309,7 @@ func (d *rootWalker) checkImplementedStep(classNode, name ir.Node, className str } func (d *rootWalker) reportUndefinedType(n ir.Node, name string) { - d.Report(n, LevelError, "undefined", "Type %s not found", name) + d.Report(n, LevelError, "undefinedType", "Type %s not found", name) } func (d *rootWalker) checkNameCase(n ir.Node, nameUsed, nameExpected string) { diff --git a/src/tests/checkers/basic_test.go b/src/tests/checkers/basic_test.go index c1644918..4da78641 100644 --- a/src/tests/checkers/basic_test.go +++ b/src/tests/checkers/basic_test.go @@ -716,7 +716,7 @@ class Foo { "Undefined variable $argc", } - linttest.RunFilterMatch(test, "undefined") + linttest.RunFilterMatch(test, "undefinedVariable") } func TestAutogenSkip(t *testing.T) { @@ -2115,7 +2115,7 @@ function f() { "Undefined variable $x", "Undefined variable $y", } - linttest.RunFilterMatch(test, "undefined") + linttest.RunFilterMatch(test, "undefinedVariable") } func TestAssignByRef(t *testing.T) { diff --git a/src/tests/checkers/oop_test.go b/src/tests/checkers/oop_test.go index 06c7007d..317a3558 100644 --- a/src/tests/checkers/oop_test.go +++ b/src/tests/checkers/oop_test.go @@ -843,7 +843,7 @@ func TestClosureLateBinding(t *testing.T) { "Undefined variable $a", "Call to undefined method {undefined}->method()", } - linttest.RunFilterMatch(test, "undefined") + linttest.RunFilterMatch(test, "undefinedVariable", "undefinedMethod") } func TestProtected(t *testing.T) { @@ -1083,7 +1083,7 @@ func TestInstanceOf(t *testing.T) { `Call to undefined method {void}->get2()`, `Call to undefined method {\Element}->callUndefinedMethod()`, } - linttest.RunFilterMatch(test, "undefined") + linttest.RunFilterMatch(test, "undefinedMethod") } func TestNullableTypes(t *testing.T) { @@ -1383,7 +1383,7 @@ trait AbstractTraitAB { `Class \T6\Bad must implement \T6\TraitAbstractA::a method`, } - linttest.RunFilterMatch(test, `unimplemented`, `nameMismatch`, `undefined`) + linttest.RunFilterMatch(test, `unimplemented`, `nameMismatch`, `undefinedType`) } func TestInterfaceRules(t *testing.T) { diff --git a/src/tests/golden/testdata/baseline-test/baseline.json b/src/tests/golden/testdata/baseline-test/baseline.json index cae6d425..a8fb32f8 100644 --- a/src/tests/golden/testdata/baseline-test/baseline.json +++ b/src/tests/golden/testdata/baseline-test/baseline.json @@ -1,25 +1,26 @@ { - "LinterVersion": "0e47cc44623afb94af3d315708cf831696bbda9d", - "CreatedAt": 1626115955, + "LinterVersion": "e605ebd8f04e03e74712fb4d8cb3fdcf459f2e7c", + "CreatedAt": 1629561919, "Version": 3, "Stats": { "CountTotal": 3, "CountPerCheck": { "discardExpr": 1, - "undefined": 2 + "undefinedFunction": 1, + "undefinedProperty": 1 } }, "Files": [ { "File": "file1.php", "Hashes": [ - "11ngx7h7507kw,m3krbhb78pqm" + "33xto60mohiss,m3krbhb78pqm" ] }, { "File": "file2.php", "Hashes": [ - "209wyajyitniw" + "28uq3iyzkgyeb" ] } ] diff --git a/src/tests/golden/testdata/baseline-test/golden.txt b/src/tests/golden/testdata/baseline-test/golden.txt index 8493f0f7..4c8c3a3e 100644 --- a/src/tests/golden/testdata/baseline-test/golden.txt +++ b/src/tests/golden/testdata/baseline-test/golden.txt @@ -1,6 +1,6 @@ WARNING discardExpr: Expression evaluated but not used at testdata/baseline-test/src/file1.php:10 "this line is not suppressed"; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -ERROR undefined: Type \NonExisting not found at testdata/baseline-test/src/file2.php:5 +ERROR undefinedType: Type \NonExisting not found at testdata/baseline-test/src/file2.php:5 $bad = new NonExisting(); ^^^^^^^^^^^ diff --git a/src/tests/golden/testdata/mustache/golden.txt b/src/tests/golden/testdata/mustache/golden.txt index 19a34aeb..a2b82155 100644 --- a/src/tests/golden/testdata/mustache/golden.txt +++ b/src/tests/golden/testdata/mustache/golden.txt @@ -121,16 +121,16 @@ MAYBE ternarySimplify: Could rewrite as `$options['cache_file_mode'] ?? null` MAYBE misspellComment: "entitity" is a misspelling of "entity" at testdata/mustache/src/Mustache/Engine.php:254 public function getEntityFlags() ^^^^^^^^^^^^^^ -ERROR undefined: Call to undefined method {\Mustache_Cache}->getLogger() at testdata/mustache/src/Mustache/Engine.php:459 +ERROR undefinedMethod: Call to undefined method {\Mustache_Cache}->getLogger() at testdata/mustache/src/Mustache/Engine.php:459 if ($this->getCache()->getLogger() === null) { ^^^^^^^^^ -ERROR undefined: Call to undefined method {\Mustache_Cache}->setLogger() at testdata/mustache/src/Mustache/Engine.php:460 +ERROR undefinedMethod: Call to undefined method {\Mustache_Cache}->setLogger() at testdata/mustache/src/Mustache/Engine.php:460 $this->getCache()->setLogger($logger); ^^^^^^^^^ -ERROR undefined: Call to undefined method {\Mustache_Cache}->getLogger() at testdata/mustache/src/Mustache/Engine.php:561 +ERROR undefinedMethod: Call to undefined method {\Mustache_Cache}->getLogger() at testdata/mustache/src/Mustache/Engine.php:561 if (isset($this->logger) && $cache->getLogger() === null) { ^^^^^^^^^ -ERROR undefined: Call to undefined method {\Mustache_Cache}->setLogger() at testdata/mustache/src/Mustache/Engine.php:562 +ERROR undefinedMethod: Call to undefined method {\Mustache_Cache}->setLogger() at testdata/mustache/src/Mustache/Engine.php:562 $cache->setLogger($this->getLogger()); ^^^^^^^^^ MAYBE ternarySimplify: Could rewrite as `$this->delimiters ?: '{{ }}'` at testdata/mustache/src/Mustache/Engine.php:628 diff --git a/src/tests/golden/testdata/parsedown/golden.txt b/src/tests/golden/testdata/parsedown/golden.txt index 817f78e2..dd0d7f39 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 undefined: Variable $text might have not been defined at testdata/parsedown/parsedown.php:1755 +WARNING maybeUndefined: Variable $text might have not been defined at testdata/parsedown/parsedown.php:1755 $markup .= self::escape($text, true); ^^^^^ -WARNING undefined: Variable $text might have not been defined at testdata/parsedown/parsedown.php:1759 +WARNING maybeUndefined: Variable $text might have not been defined 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/phprocksyd/golden.txt b/src/tests/golden/testdata/phprocksyd/golden.txt index 45ad2dab..f293b81b 100644 --- a/src/tests/golden/testdata/phprocksyd/golden.txt +++ b/src/tests/golden/testdata/phprocksyd/golden.txt @@ -31,7 +31,7 @@ WARNING phpdocLint: Malformed @param $stream_id tag (maybe type is missing?) at WARNING phpdocLint: Malformed @param $req tag (maybe type is missing?) at testdata/phprocksyd/Phprocksyd.php:444 * @param $req ^^^^ -ERROR undefined: Call to undefined method {mixed}->run() at testdata/phprocksyd/Phprocksyd.php:479 +ERROR undefinedMethod: Call to undefined method {mixed}->run() at testdata/phprocksyd/Phprocksyd.php:479 $instance->run($req['params']); ^^^ ERROR constCase: Constant 'NULL' should be used in lower case as 'null' at testdata/phprocksyd/Simple.php:158 diff --git a/src/tests/golden/testdata/qrcode/golden.txt b/src/tests/golden/testdata/qrcode/golden.txt index 619629d8..d5be1673 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 undefined: Variable $code might have not been defined at testdata/qrcode/qrcode.php:221 +WARNING maybeUndefined: Variable $code might have not been defined 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/golden/testdata/underscore/golden.txt b/src/tests/golden/testdata/underscore/golden.txt index 62fd2ab6..22fda221 100644 --- a/src/tests/golden/testdata/underscore/golden.txt +++ b/src/tests/golden/testdata/underscore/golden.txt @@ -112,37 +112,37 @@ WARNING unused: Variable $__ is unused (use $_ to ignore this inspection or spec WARNING unused: Variable $args is unused (use $_ to ignore this inspection or specify --unused-var-regex flag) at testdata/underscore/underscore.php:615 $args = self::_wrapArgs(func_get_args(), 1); ^^^^^ -ERROR undefined: Property {\__|mixed|null}->isEqual does not exist at testdata/underscore/underscore.php:723 +ERROR undefinedProperty: Property {\__|mixed|null}->isEqual does not exist at testdata/underscore/underscore.php:723 if(is_object($a) && isset($a->isEqual)) return self::_wrap($a->isEqual($b)); ^^^^^^^ -ERROR undefined: Property {mixed|null}->isEqual does not exist at testdata/underscore/underscore.php:724 +ERROR undefinedProperty: Property {mixed|null}->isEqual does not exist at testdata/underscore/underscore.php:724 if(is_object($b) && isset($b->isEqual)) return self::_wrap($b->isEqual($a)); ^^^^^^^ -ERROR undefined: Call to undefined method {mixed|null}->isEqual() at testdata/underscore/underscore.php:724 +ERROR undefinedMethod: Call to undefined method {mixed|null}->isEqual() at testdata/underscore/underscore.php:724 if(is_object($b) && isset($b->isEqual)) return self::_wrap($b->isEqual($a)); ^^^^^^^ MAYBE arrayAccess: Array access to non-array type \__|mixed|null at testdata/underscore/underscore.php:725 if(is_array($a) && array_key_exists('isEqual', $a)) return self::_wrap($a['isEqual']($b)); ^^ -ERROR undefined: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:822 +ERROR undefinedProperty: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:822 $_instance->_uniqueId++; ^^^^^^^^^ -ERROR undefined: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:824 +ERROR undefinedProperty: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:824 return (is_null($prefix)) ? self::_wrap($_instance->_uniqueId) : self::_wrap($prefix . $_instance->_uniqueId); ^^^^^^^^^ -ERROR undefined: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:824 +ERROR undefinedProperty: Property {mixed}->_uniqueId does not exist at testdata/underscore/underscore.php:824 return (is_null($prefix)) ? self::_wrap($_instance->_uniqueId) : self::_wrap($prefix . $_instance->_uniqueId); ^^^^^^^^^ -ERROR undefined: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:843 +ERROR undefinedProperty: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:843 $mixins =& self::getInstance()->_mixins; ^^^^^^^ -ERROR undefined: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:853 +ERROR undefinedProperty: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:853 $mixins =& self::getInstance()->_mixins; ^^^^^^^ -ERROR undefined: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:859 +ERROR undefinedProperty: Property {mixed}->_mixins does not exist at testdata/underscore/underscore.php:859 $mixins =& self::getInstance()->_mixins; ^^^^^^^ -ERROR undefined: Property {mixed}->_template_settings does not exist at testdata/underscore/underscore.php:882 +ERROR undefinedProperty: Property {mixed}->_template_settings does not exist at testdata/underscore/underscore.php:882 $_template_settings =& self::getInstance()->_template_settings; ^^^^^^^^^^^^^^^^^^ MAYBE arraySyntax: Use the short form '[]' instead of the old 'array()' at testdata/underscore/underscore.php:885 @@ -151,7 +151,7 @@ MAYBE arraySyntax: Use the short form '[]' instead of the old 'array()' at tes MAYBE trailingComma: Last element in a multi-line array should have a trailing comma at testdata/underscore/underscore.php:888 'escape' => self::TEMPLATE_DEFAULT_ESCAPE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -ERROR undefined: Property {mixed}->_template_settings does not exist at testdata/underscore/underscore.php:909 +ERROR undefinedProperty: Property {mixed}->_template_settings does not exist at testdata/underscore/underscore.php:909 $ts = $class_name::getInstance()->_template_settings; ^^^^^^^^^^^^^^^^^^ MAYBE deprecated: Call to deprecated function create_function (7.2 Use anonymous functions instead.) at testdata/underscore/underscore.php:940 diff --git a/src/tests/regression/issue16_test.go b/src/tests/regression/issue16_test.go index fc86b23e..e0c87999 100644 --- a/src/tests/regression/issue16_test.go +++ b/src/tests/regression/issue16_test.go @@ -44,5 +44,5 @@ func TestIssue16(t *testing.T) { "Call to undefined method {mixed}->format()", "Class constant \\TestExInterface::TEST2 does not exist", } - linttest.RunFilterMatch(test, "undefined") + linttest.RunFilterMatch(test, "undefinedMethod", "undefinedConstant") } diff --git a/src/tests/regression/issue288_test.go b/src/tests/regression/issue288_test.go index 7e79d1c0..2034949a 100644 --- a/src/tests/regression/issue288_test.go +++ b/src/tests/regression/issue288_test.go @@ -40,7 +40,7 @@ $_ = $x instanceof Box ? 0 : 1; `Undefined variable $b1`, `Undefined variable $b2`, `Undefined variable $b3`, - `undefined: Property {mixed}->item2 does not exist`, + `Property {mixed}->item2 does not exist`, } test.RunAndMatch() }