diff --git a/src/lint/linter/__tests__/ArcanistLinterTestCase.php b/src/lint/linter/__tests__/ArcanistLinterTestCase.php index b86a43b2..a6dc69b5 100644 --- a/src/lint/linter/__tests__/ArcanistLinterTestCase.php +++ b/src/lint/linter/__tests__/ArcanistLinterTestCase.php @@ -1,262 +1,326 @@ getLinter(); $files = id(new FileFinder($root)) ->withType('f') ->withSuffix('lint-test') ->find(); $test_count = 0; foreach ($files as $file) { $this->lintFile($root.$file, $linter); $test_count++; } $this->assertTrue( ($test_count > 0), pht( 'Expected to find some %s tests in directory %s!', '.lint-test', $root)); } private function lintFile($file, ArcanistLinter $linter) { $linter = clone $linter; $contents = Filesystem::readFile($file); $contents = preg_split('/^~{4,}\n/m', $contents); if (count($contents) < 2) { throw new Exception( pht( "Expected '%s' separating test case and results.", '~~~~~~~~~~')); } list($data, $expect, $xform, $config) = array_merge( $contents, array(null, null)); $basename = basename($file); if ($config) { $config = phutil_json_decode($config); } else { $config = array(); } PhutilTypeSpec::checkMap( $config, array( 'config' => 'optional map', - 'path' => 'optional string', 'mode' => 'optional string', + 'path' => 'optional string', 'stopped' => 'optional bool', )); $exception = null; $after_lint = null; $messages = null; $exception_message = false; $caught_exception = false; try { $tmp = new TempFile($basename); Filesystem::writeFile($tmp, $data); $full_path = (string)$tmp; $mode = idx($config, 'mode'); if ($mode) { Filesystem::changePermissions($tmp, octdec($mode)); } $dir = dirname($full_path); $path = basename($full_path); $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile( $dir, null, pht('Unit Test')); $configuration_manager = new ArcanistConfigurationManager(); $configuration_manager->setWorkingCopyIdentity($working_copy); $engine = new ArcanistUnitTestableLintEngine(); $engine->setWorkingCopy($working_copy); $engine->setConfigurationManager($configuration_manager); $path_name = idx($config, 'path', $path); $engine->setPaths(array($path_name)); $linter->setEngine($engine); $linter->addPath($path_name); $linter->addData($path_name, $data); foreach (idx($config, 'config', array()) as $key => $value) { $linter->setLinterConfigurationValue($key, $value); } $engine->addLinter($linter); $engine->addFileData($path_name, $data); $results = $engine->run(); $this->assertEqual( 1, count($results), pht('Expect one result returned by linter.')); $assert_stopped = idx($config, 'stopped'); if ($assert_stopped !== null) { $this->assertEqual( $assert_stopped, $linter->didStopAllLinters(), $assert_stopped ? pht('Expect linter to be stopped.') : pht('Expect linter to not be stopped.')); } $result = reset($results); $patcher = ArcanistLintPatcher::newFromArcanistLintResult($result); $after_lint = $patcher->getModifiedFileContent(); } catch (PhutilTestTerminatedException $ex) { throw $ex; } catch (Exception $exception) { $caught_exception = true; if ($exception instanceof PhutilAggregateException) { $caught_exception = false; foreach ($exception->getExceptions() as $ex) { if ($ex instanceof ArcanistUsageException || $ex instanceof ArcanistMissingLinterException) { $this->assertSkipped($ex->getMessage()); } else { $caught_exception = true; } } } else if ($exception instanceof ArcanistUsageException || $exception instanceof ArcanistMissingLinterException) { $this->assertSkipped($exception->getMessage()); } $exception_message = $exception->getMessage()."\n\n". $exception->getTraceAsString(); } $this->assertEqual(false, $caught_exception, $exception_message); $this->compareLint($basename, $expect, $result); $this->compareTransform($xform, $after_lint); } - private function compareLint($file, $expect, ArcanistLintResult $result) { - $seen = array(); - $raised = array(); - $message_map = array(); - - foreach ($result->getMessages() as $message) { - $sev = $message->getSeverity(); - $line = $message->getLine(); - $char = $message->getChar(); - $code = $message->getCode(); - $name = $message->getName(); - $message_key = $sev.':'.$line.':'.$char; - $message_map[$message_key] = $message; - $seen[] = $message_key; - $raised[] = sprintf( - ' %s: %s %s', - pht('%s at line %d, char %d', $sev, $line, $char), - $code, - $name); - } + private function compareLint($file, $expect, ArcanistLintResult $results) { + $expected_results = new ArcanistLintResult(); + $expect = trim($expect); if ($expect) { $expect = explode("\n", $expect); } else { $expect = array(); } - foreach ($expect as $key => $expected) { - $expect[$key] = head(explode(' ', $expected)); - } - $expect = array_fill_keys($expect, true); - $seen = array_fill_keys($seen, true); + foreach ($expect as $result) { + $parts = explode(':', $result); + + $message = new ArcanistLintMessage(); + + $severity = idx($parts, 0); + $line = idx($parts, 1); + $char = idx($parts, 2); + $code = idx($parts, 3); + + if ($severity !== null) { + $message->setSeverity($severity); + } + + if ($line !== null) { + $message->setLine($line); + } + + if ($char !== null) { + $message->setChar($char); + } + + if ($code !== null) { + $message->setCode($code); + } - if (!$raised) { - $raised = array(pht('No messages.')); + $expected_results->addMessage($message); } - $raised = sprintf( - "%s:\n%s", - pht('Actually raised'), - implode("\n", $raised)); - foreach (array_diff_key($expect, $seen) as $missing => $ignored) { - $missing = explode(':', $missing); - $sev = array_shift($missing); - $pos = $missing; + $missing = array(); + $surprising = $results->getMessages(); - $this->assertFailure( - pht( - "In '%s', expected lint to raise %s on line %d at char %d, ". - "but no %s was raised. %s", - $file, - $sev, - idx($pos, 0), - idx($pos, 1), - $sev, - $raised)); + // TODO: Make this more efficient. + foreach ($expected_results->getMessages() as $expected_message) { + $found = false; + + foreach ($results->getMessages() as $ii => $actual_message) { + if (!self::compareLintMessageProperty( + $expected_message->getSeverity(), + $actual_message->getSeverity())) { + + continue; + } + + if (!self::compareLintMessageProperty( + $expected_message->getLine(), + $actual_message->getLine())) { + + continue; + } + + if (!self::compareLintMessageProperty( + $expected_message->getChar(), + $actual_message->getChar())) { + + continue; + } + + if (!self::compareLintMessageProperty( + $expected_message->getCode(), + $actual_message->getCode())) { + + continue; + } + + $found = true; + unset($surprising[$ii]); + } + + if (!$found) { + $missing[] = $expected_message; + } } - foreach (array_diff_key($seen, $expect) as $surprising => $ignored) { - $message = $message_map[$surprising]; - $message_info = $message->getDescription(); + if ($missing || $surprising) { + $expected = pht('EXPECTED MESSAGES'); + if ($missing) { + foreach ($missing as $message) { + $expected .= sprintf( + "\n %s: %s %s", + pht( + '%s at line %d, char %d', + $message->getSeverity(), + $message->getLine(), + $message->getChar()), + $message->getCode(), + $message->getName()); + } + } else { + $expected .= "\n ".pht('No messages'); + } + + $actual = pht('UNEXPECTED MESSAGES'); + if ($surprising) { + foreach ($surprising as $message) { + $actual .= sprintf( + "\n %s: %s %s", + pht( + '%s at line %d, char %d', + $message->getSeverity(), + $message->getLine(), + $message->getChar()), + $message->getCode(), + $message->getName()); + } + } else { + $actual .= "\n ".pht('No messages'); + } - list($sev, $line, $char) = explode(':', $surprising); $this->assertFailure( sprintf( - "%s:\n\n%s\n\n%s", - pht( - "In '%s', lint raised %s on line %d at char %d, ". - "but nothing was expected", - $file, - $sev, - $line, - $char), - $message_info, - $raised)); + "%s\n\n%s\n\n%s", + pht("Lint failed for '%s'.", $file), + $expected, + $actual)); } } private function compareTransform($expected, $actual) { if (!strlen($expected)) { return; } $this->assertEqual( $expected, $actual, pht('File as patched by lint did not match the expected patched file.')); } + /** + * Compare properties of @{class:ArcanistLintMessage} instances. + * + * The expectation is that if one (or both) of the properties is null, then + * we don't care about its value. + * + * @param wild + * @param wild + * @return bool + */ + private static function compareLintMessageProperty($x, $y) { + return $x === null || $y === null || $x === $y; + } + } diff --git a/src/lint/linter/__tests__/chmod/empty_executable.lint-test b/src/lint/linter/__tests__/chmod/empty_executable.lint-test index 54e5a85c..cf8980b6 100644 --- a/src/lint/linter/__tests__/chmod/empty_executable.lint-test +++ b/src/lint/linter/__tests__/chmod/empty_executable.lint-test @@ -1,5 +1,5 @@ ~~~~~~~~~~ -warning:: +warning:0:0:CHMOD1:Invalid Executable ~~~~~~~~~~ ~~~~~~~~~~ {"mode": "0755"} diff --git a/src/lint/linter/__tests__/coffeelint/no_trailing_whitespace.lint-test b/src/lint/linter/__tests__/coffeelint/no_trailing_whitespace.lint-test index 6b43ad21..87351e90 100644 --- a/src/lint/linter/__tests__/coffeelint/no_trailing_whitespace.lint-test +++ b/src/lint/linter/__tests__/coffeelint/no_trailing_whitespace.lint-test @@ -1,4 +1,4 @@ x = 1234 y = 1 ~~~~~~~~~~ -error:1: +error:1:0 diff --git a/src/lint/linter/__tests__/filename/bad_filename.lint-test b/src/lint/linter/__tests__/filename/bad_filename.lint-test index 7eb7c745..12ec5757 100644 --- a/src/lint/linter/__tests__/filename/bad_filename.lint-test +++ b/src/lint/linter/__tests__/filename/bad_filename.lint-test @@ -1,5 +1,5 @@ ~~~~~~~~~~ -error:: +error:0:0:NAME1:Bad Filename ~~~~~~~~~~ ~~~~~~~~~~ {"path": "bad@filename"} diff --git a/src/lint/linter/__tests__/flake8/undefined.lint-test b/src/lint/linter/__tests__/flake8/undefined.lint-test index 2f8a2548..72a09df0 100644 --- a/src/lint/linter/__tests__/flake8/undefined.lint-test +++ b/src/lint/linter/__tests__/flake8/undefined.lint-test @@ -1,7 +1,7 @@ x = 'y' def hello(): return foo ~~~~~~~~~~ -error:3:1 -error:4:12 +error:3:1:E302 +error:4:12:F821 diff --git a/src/lint/linter/__tests__/jshint/dot-notation.lint-test b/src/lint/linter/__tests__/jshint/dot-notation.lint-test index 681e3505..53cf0f91 100644 --- a/src/lint/linter/__tests__/jshint/dot-notation.lint-test +++ b/src/lint/linter/__tests__/jshint/dot-notation.lint-test @@ -1,6 +1,6 @@ var args = {}; args['foo'] = 'bar'; args['bar'] = 'baz'; ~~~~~~~~~~ -warning:2:5 -warning:3:5 +warning:2:5:W069 +warning:3:5:W069 diff --git a/src/lint/linter/__tests__/jshint/expected-conditional.lint-test b/src/lint/linter/__tests__/jshint/expected-conditional.lint-test index 2b229273..42b75257 100644 --- a/src/lint/linter/__tests__/jshint/expected-conditional.lint-test +++ b/src/lint/linter/__tests__/jshint/expected-conditional.lint-test @@ -1,6 +1,6 @@ var foo; if (foo = 'bar') { return true; } ~~~~~~~~~~ -warning:2:16 +warning:2:16:W084 diff --git a/src/lint/linter/__tests__/jshint/jshint.lint-test b/src/lint/linter/__tests__/jshint/jshint.lint-test index edb1c779..954e1033 100644 --- a/src/lint/linter/__tests__/jshint/jshint.lint-test +++ b/src/lint/linter/__tests__/jshint/jshint.lint-test @@ -1,12 +1,12 @@ function f() { for (ii = 0; ii < 3; ii++) { g() } } { ~~~~~~~~~~ -warning:3:8 -error:7:1 -error:9:1 +warning:3:8:W033 +error:7:1:E019 +error:9:1:E041 diff --git a/src/lint/linter/__tests__/jshint/missing-semicolon.lint-test b/src/lint/linter/__tests__/jshint/missing-semicolon.lint-test index a6669698..23ba765b 100644 --- a/src/lint/linter/__tests__/jshint/missing-semicolon.lint-test +++ b/src/lint/linter/__tests__/jshint/missing-semicolon.lint-test @@ -1,3 +1,3 @@ console.log('foobar') ~~~~~~~~~~ -warning:1:22 +warning:1:22:W033 diff --git a/src/lint/linter/__tests__/jshint/too-many-errors.lint-test b/src/lint/linter/__tests__/jshint/too-many-errors.lint-test index 6dbea1f9..e7b936dd 100644 --- a/src/lint/linter/__tests__/jshint/too-many-errors.lint-test +++ b/src/lint/linter/__tests__/jshint/too-many-errors.lint-test @@ -1,5 +1,5 @@ /* jshint maxerr: 1 */ console.log('foobar') ~~~~~~~~~~ -disabled:2:22 -warning:2:22 +disabled:2:22:E043 +warning:2:22:W033 diff --git a/src/lint/linter/__tests__/jshint/unnecessary-semicolon.lint-test b/src/lint/linter/__tests__/jshint/unnecessary-semicolon.lint-test index 14eafbdf..04c627ca 100644 --- a/src/lint/linter/__tests__/jshint/unnecessary-semicolon.lint-test +++ b/src/lint/linter/__tests__/jshint/unnecessary-semicolon.lint-test @@ -1,5 +1,5 @@ function main() { return 'Hello, World!'; }; ~~~~~~~~~~ -warning:3:2 +warning:3:2:W032 diff --git a/src/lint/linter/__tests__/mergeconflict/mergeconflict.lint-test b/src/lint/linter/__tests__/mergeconflict/mergeconflict.lint-test index 3e30be52..71b7d4aa 100644 --- a/src/lint/linter/__tests__/mergeconflict/mergeconflict.lint-test +++ b/src/lint/linter/__tests__/mergeconflict/mergeconflict.lint-test @@ -1,10 +1,10 @@ { "foo": "bar", <<<<<<< HEAD "bar": "baz" ======= "baz": "foo" >>>>>>> branch2 } ~~~~~~~~~~ -error:5:1 +error:5:1:MERGECONFLICT1:Unresolved merge conflict diff --git a/src/lint/linter/__tests__/pep8/imports.lint-test b/src/lint/linter/__tests__/pep8/imports.lint-test index cd9b2287..71f0ad21 100644 --- a/src/lint/linter/__tests__/pep8/imports.lint-test +++ b/src/lint/linter/__tests__/pep8/imports.lint-test @@ -1,3 +1,3 @@ import os, sys ~~~~~~~~~~ -error:1:10 +error:1:10:E401 diff --git a/src/lint/linter/__tests__/php/fatal.lint-test b/src/lint/linter/__tests__/php/fatal.lint-test index cf13b0cd..6d3c7b82 100644 --- a/src/lint/linter/__tests__/php/fatal.lint-test +++ b/src/lint/linter/__tests__/php/fatal.lint-test @@ -1,7 +1,7 @@ recieveData(); for (i=0; i This shouldn't fatal the parser. ~~~~~~~~~~ -disabled:2:1 +disabled:2:1:XHP78:Inline HTML diff --git a/src/lint/linter/__tests__/xhpast/empty.lint-test b/src/lint/linter/__tests__/xhpast/empty.lint-test index ddbbaebd..22cca1cd 100644 --- a/src/lint/linter/__tests__/xhpast/empty.lint-test +++ b/src/lint/linter/__tests__/xhpast/empty.lint-test @@ -1,4 +1,4 @@ ~~~~~~~~~~ -error:2:1 +error:2:1:XML4:LibXML Error diff --git a/src/lint/linter/__tests__/xml/char-ref.lint-test b/src/lint/linter/__tests__/xml/char-ref.lint-test index a142bbe4..6f4cca9a 100644 --- a/src/lint/linter/__tests__/xml/char-ref.lint-test +++ b/src/lint/linter/__tests__/xml/char-ref.lint-test @@ -1,3 +1,3 @@ ~~~~~~~~~~ -error:1:63 +error:1:63:XML9:LibXML Error diff --git a/src/lint/linter/__tests__/xml/languages-5.lint-test b/src/lint/linter/__tests__/xml/languages-5.lint-test index cf469965..508b4f1a 100644 --- a/src/lint/linter/__tests__/xml/languages-5.lint-test +++ b/src/lint/linter/__tests__/xml/languages-5.lint-test @@ -1,6 +1,6 @@ <> ~~~~~~~~~~ -error:3:6 +error:3:6:XML68:LibXML Error diff --git a/src/lint/linter/__tests__/xml/languages-6.lint-test b/src/lint/linter/__tests__/xml/languages-6.lint-test index 1cdb9519..f652fbb8 100644 --- a/src/lint/linter/__tests__/xml/languages-6.lint-test +++ b/src/lint/linter/__tests__/xml/languages-6.lint-test @@ -1,7 +1,7 @@ ~~~~~~~~~~ -error:3:16 -error:4:1 +error:3:16:XML76:LibXML Error +error:4:1:XML5:LibXML Error diff --git a/src/lint/linter/xhpast/rules/__tests__/__lambda_func-function/lamba-func-function.lint-test b/src/lint/linter/xhpast/rules/__tests__/__lambda_func-function/lamba-func-function.lint-test index 554a4034..a65ee01f 100644 --- a/src/lint/linter/xhpast/rules/__tests__/__lambda_func-function/lamba-func-function.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/__lambda_func-function/lamba-func-function.lint-test @@ -1,5 +1,5 @@ << << 'bar', 'bar' => 'baz', ); array( 1, /* quack */ 2, /* quack */3, ); array( /* OPEN */ 1, /* CLOSED */ 2, ); array('quack', ); ~~~~~~~~~~ -warning:4:5 -warning:4:8 -warning:8:18 -warning:12:17 -warning:12:32 -warning:20:7 +warning:4:5:XHP76:Array Element +warning:4:8:XHP76:Array Element +warning:8:18:XHP76:Array Element +warning:12:17:XHP76:Array Element +warning:12:32:XHP76:Array Element +warning:20:7:XHP76:Array Element ~~~~~~~~~~ 'bar', 'bar' => 'baz', ); array( 1, /* quack */ 2, /* quack */ 3, ); array( /* OPEN */ 1, /* CLOSED */ 2, ); array( 'quack', ); diff --git a/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/array.lint-test b/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/array.lint-test index 8e0857c9..46fc5b8a 100644 --- a/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/array.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/array.lint-test @@ -1,40 +1,40 @@ $y); array($x=>$y); array($x =>$y); array($x=> $y); array( $x => $y, ); array( $x => $y, ); array( $x=>$y, ); ~~~~~~~~~~ -warning:4:9 -warning:5:10 -warning:6:9 -warning:16:5 +warning:4:9:XHP27:Space Around Binary Operator +warning:5:10:XHP27:Space Around Binary Operator +warning:6:9:XHP27:Space Around Binary Operator +warning:16:5:XHP27:Space Around Binary Operator ~~~~~~~~~~ $y); array($x => $y); array($x => $y); array($x => $y); array( $x => $y, ); array( $x => $y, ); array( $x => $y, ); diff --git a/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/binary-expression-spacing.lint-test b/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/binary-expression-spacing.lint-test index 571a5648..3caaab1c 100644 --- a/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/binary-expression-spacing.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/binary-expression-spacing/binary-expression-spacing.lint-test @@ -1,65 +1,65 @@ method(); Dog::bark(); $prev = ($total == 1) ? $navids[0] : $navids[$total-1]; $next = ($total == 1) ? $navids[0] : $navids[$current+1]; if ($x instanceof z &&$w) {} if ($x instanceof z && $w) {} f(1,2); ~~~~~~~~~~ -warning:4:3 -warning:5:4 -warning:6:3 -warning:8:3 -warning:9:3 -warning:10:4 -warning:11:3 -warning:12:3 -warning:14:14 -warning:21:52 -warning:22:54 -warning:23:21 -warning:25:4 +warning:4:3:XHP27:Space Around Binary Operator +warning:5:4:XHP27:Space Around Binary Operator +warning:6:3:XHP27:Space Around Binary Operator +warning:8:3:XHP27:Space Around Binary Operator +warning:9:3:XHP27:Space Around Binary Operator +warning:10:4:XHP27:Space Around Binary Operator +warning:11:3:XHP27:Space Around Binary Operator +warning:12:3:XHP27:Space Around Binary Operator +warning:14:14:XHP27:Space Around Binary Operator +warning:21:52:XHP27:Space Around Binary Operator +warning:22:54:XHP27:Space Around Binary Operator +warning:23:21:XHP27:Space Around Binary Operator +warning:25:4:XHP27:Space Around Binary Operator ~~~~~~~~~~ method(); Dog::bark(); $prev = ($total == 1) ? $navids[0] : $navids[$total - 1]; $next = ($total == 1) ? $navids[0] : $navids[$current + 1]; if ($x instanceof z && $w) {} if ($x instanceof z && $w) {} f(1, 2); diff --git a/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test b/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test index 406fe97c..8297e01f 100644 --- a/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test @@ -1,5 +1,5 @@ myfunc(&$myvar); $this->myfunc($myvar); MyClass::myfunc(&$myvar); MyClass::myfunc($myvar); while (testfunc($var1, &$var2, $var3, &$var4) === false) {} sprintf('0%o', 0777 & $p); $foo(&$myvar); array_walk(array(), function () use (&$x) {}); MyClass::myfunc(array(&$x, &$y)); ~~~~~~~~~~ -error:10:8 -error:13:15 -error:16:17 -error:19:24 -error:19:39 -error:23:6 +error:10:8:XHP53:Call-Time Pass-By-Reference +error:13:15:XHP53:Call-Time Pass-By-Reference +error:16:17:XHP53:Call-Time Pass-By-Reference +error:19:24:XHP53:Call-Time Pass-By-Reference +error:19:39:XHP53:Call-Time Pass-By-Reference +error:23:6:XHP53:Call-Time Pass-By-Reference diff --git a/src/lint/linter/xhpast/rules/__tests__/cast-spacing/cast-spacing.lint-test b/src/lint/linter/xhpast/rules/__tests__/cast-spacing/cast-spacing.lint-test index bc70f302..0662c526 100644 --- a/src/lint/linter/xhpast/rules/__tests__/cast-spacing/cast-spacing.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/cast-spacing/cast-spacing.lint-test @@ -1,14 +1,14 @@ 'val1', $a => 'val2', 'a' => val3(), 1 => val4(), '1' => val5(), 1 => $val6, 'b' => 'val7', b() => 'val8', ); static $b = array( 1 => 'one', 2 => 'two', 2 => 'TWO', ); $c = array(); $d = array( A => 'ay', A => 'aye', 'A' => 'AYE', ); $e = array( self::B => 'bee', self::B => 'bea', self::b() => 'ehh', self::$b => 'weh', B => 'b', C::B => 'cb', ); $f = array( $a => 'var', 'a' => 'lit', $a => 'var2', ); ~~~~~~~~~~ -error:6:3 -error:9:3 -error:16:3 -error:21:3 -error:26:3 -error:35:3 +error:6:3:XHP22:Duplicate Keys in Array +error:9:3:XHP22:Duplicate Keys in Array +error:16:3:XHP22:Duplicate Keys in Array +error:21:3:XHP22:Duplicate Keys in Array +error:26:3:XHP22:Duplicate Keys in Array +error:35:3:XHP22:Duplicate Keys in Array diff --git a/src/lint/linter/xhpast/rules/__tests__/duplicate-switch-case/duplicate-switch-case.lint-test b/src/lint/linter/xhpast/rules/__tests__/duplicate-switch-case/duplicate-switch-case.lint-test index 2c8e5c5c..2d95b899 100644 --- a/src/lint/linter/xhpast/rules/__tests__/duplicate-switch-case/duplicate-switch-case.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/duplicate-switch-case/duplicate-switch-case.lint-test @@ -1,29 +1,29 @@ ~~~~~~~~~~ -disabled:2:1 +disabled:2:1:XHP78:Inline HTML diff --git a/src/lint/linter/xhpast/rules/__tests__/inner-function/inner-function.lint-test b/src/lint/linter/xhpast/rules/__tests__/inner-function/inner-function.lint-test index 6294eb0a..d4f73fc1 100644 --- a/src/lint/linter/xhpast/rules/__tests__/inner-function/inner-function.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/inner-function/inner-function.lint-test @@ -1,14 +1,14 @@ doSomething(); id(new Something()) ->doSomething(); ~~~~~~~~~~ -warning:3:3 -warning:3:6 +warning:3:3:XHP74:Object Operator Spacing +warning:3:6:XHP74:Object Operator Spacing ~~~~~~~~~~ doSomething(); id(new Something()) ->doSomething(); diff --git a/src/lint/linter/xhpast/rules/__tests__/paamayim-nekudotayim-spacing/paamayim-nekudotayim-spacing.lint-test b/src/lint/linter/xhpast/rules/__tests__/paamayim-nekudotayim-spacing/paamayim-nekudotayim-spacing.lint-test index 7ee65d7b..67a6c11d 100644 --- a/src/lint/linter/xhpast/rules/__tests__/paamayim-nekudotayim-spacing/paamayim-nekudotayim-spacing.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/paamayim-nekudotayim-spacing/paamayim-nekudotayim-spacing.lint-test @@ -1,36 +1,36 @@ m( $x, $y, $z); for ( $ii = 0; $ii < 1; $ii++ ) {} foreach ( $x as $y ) {} function q( $x ) {} final class X { public function f( $y ) {} } foreach ( $z as $k => $v ) {} some_call( /* respect authorial intent */ $b, $a // if comments are present ); ~~~~~~~~~~ -warning:3:5 -warning:3:8 -warning:4:3 -warning:5:3 -warning:7:21 -warning:7:24 -warning:13:6 -warning:13:30 -warning:14:10 -warning:14:19 -warning:15:12 -warning:15:15 -warning:17:21 -warning:17:24 -warning:19:10 -warning:19:25 +warning:3:5:XHP25:Spaces Inside Parentheses +warning:3:8:XHP25:Spaces Inside Parentheses +warning:4:3:XHP25:Spaces Inside Parentheses +warning:5:3:XHP25:Spaces Inside Parentheses +warning:7:21:XHP25:Spaces Inside Parentheses +warning:7:24:XHP25:Spaces Inside Parentheses +warning:13:6:XHP25:Spaces Inside Parentheses +warning:13:30:XHP25:Spaces Inside Parentheses +warning:14:10:XHP25:Spaces Inside Parentheses +warning:14:19:XHP25:Spaces Inside Parentheses +warning:15:12:XHP25:Spaces Inside Parentheses +warning:15:15:XHP25:Spaces Inside Parentheses +warning:17:21:XHP25:Spaces Inside Parentheses +warning:17:24:XHP25:Spaces Inside Parentheses +warning:19:10:XHP25:Spaces Inside Parentheses +warning:19:25:XHP25:Spaces Inside Parentheses ~~~~~~~~~~ m( $x, $y, $z); for ($ii = 0; $ii < 1; $ii++) {} foreach ($x as $y) {} function q($x) {} final class X { public function f($y) {} } foreach ($z as $k => $v) {} some_call( /* respect authorial intent */ $b, $a // if comments are present ); diff --git a/src/lint/linter/xhpast/rules/__tests__/parse_str-use/parse_str-use.lint-test b/src/lint/linter/xhpast/rules/__tests__/parse_str-use/parse_str-use.lint-test index 21afe525..0e7541d6 100644 --- a/src/lint/linter/xhpast/rules/__tests__/parse_str-use/parse_str-use.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/parse_str-use/parse_str-use.lint-test @@ -1,7 +1,7 @@ ~~~~~~~~~~ -error:3:1 +error:3:1:XHP8:Use of Close Tag `?>` diff --git a/src/lint/linter/xhpast/rules/__tests__/php-compatibility/conditional-usage.lint-test b/src/lint/linter/xhpast/rules/__tests__/php-compatibility/conditional-usage.lint-test index 6b8a50de..ba34f703 100644 --- a/src/lint/linter/xhpast/rules/__tests__/php-compatibility/conditional-usage.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/php-compatibility/conditional-usage.lint-test @@ -1,32 +1,32 @@ m()[0]; final class SomeClass extends Phobject { public function someMethod() { return function () { $this->someOtherMethod(); }; } public static function someStaticMethod() { return function () { self::someOtherMethod(); }; } } 0b1; []; ~~~~~~~~~~ -error:3:5 -error:4:9 -error:12:7 -error:18:7 -error:23:1 -error:25:1 +error:3:5:XHP45:PHP Compatibility +error:4:9:XHP45:PHP Compatibility +error:12:7:XHP45:PHP Compatibility +error:18:7:XHP45:PHP Compatibility +error:23:1:XHP45:PHP Compatibility +error:25:1:XHP45:PHP Compatibility ~~~~~~~~~~ ~~~~~~~~~~ { "config": { "xhpast.php-version": "5.3.0" } } diff --git a/src/lint/linter/xhpast/rules/__tests__/php-compatibility/php54-incompat.lint-test b/src/lint/linter/xhpast/rules/__tests__/php-compatibility/php54-incompat.lint-test index fb6e3ac6..208adbfa 100644 --- a/src/lint/linter/xhpast/rules/__tests__/php-compatibility/php54-incompat.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/php-compatibility/php54-incompat.lint-test @@ -1,18 +1,18 @@ ~~~~~~~~~~ -error:1:1 +error:1:1:XHP15:Expected Open Tag ~~~~~~~~~~ garbage garbage diff --git a/src/lint/linter/xhpast/rules/__tests__/php-short-tag/php-short-tag.lint-test b/src/lint/linter/xhpast/rules/__tests__/php-short-tag/php-short-tag.lint-test index 9c5fb0c5..1e756cda 100644 --- a/src/lint/linter/xhpast/rules/__tests__/php-short-tag/php-short-tag.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/php-short-tag/php-short-tag.lint-test @@ -1,6 +1,6 @@ $val) {} $key = 1; $thing = 1; $thing = $key; $key = $thing; } function i($stuff, $thing) { foreach ($stuff as $thing) { $thing++; } // OK: Used afterwards but inside loop. foreach ($stuff as $thing) { $thing++; } } function j($stuff, $thing) { foreach ($stuff as $thing) { break; } // ERROR: Clobbers $thing; probably not what the author intended. f($thing); } function k($stuff, $thing) { foreach ($stuff as $thing) { break; } // ERROR: Clobbers $thing. Test case to cover some errors of implementation // where subsequent legitimate foreach()es threw a wrench in the gears. f($thing); $other = array(); foreach ($other as $item) {} } ~~~~~~~~~~ -error:43:22 -error:53:22 +error:43:22:XHP32:Variable Reused As Iterator +error:53:22:XHP32:Variable Reused As Iterator diff --git a/src/lint/linter/xhpast/rules/__tests__/reused-iterator-reference/reused-iterator-reference.lint-test b/src/lint/linter/xhpast/rules/__tests__/reused-iterator-reference/reused-iterator-reference.lint-test index 0bc4c345..be42a429 100644 --- a/src/lint/linter/xhpast/rules/__tests__/reused-iterator-reference/reused-iterator-reference.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/reused-iterator-reference/reused-iterator-reference.lint-test @@ -1,130 +1,130 @@ &$v) {} $v++; // Reuse of $v } function key_value2() { $ar = array(); foreach ($ar as $k => $v) {} $v++; } function unset() { $ar = array(); foreach ($ar as &$a) {} unset($a); $a++; } function unset2() { $ar = array(); foreach ($ar as &$a) {} $a++; // Reuse of $a unset($a); } function twice_ref() { $ar1 = array(); $ar2 = array(); foreach ($ar1 as &$b) {} foreach ($ar2 as &$b) {} } function assign_ref(&$a) { $ar = array(); foreach ($ar as &$b) {} $b = &$a; } function assign_ref2(&$a) { $ar = array(); foreach ($ar as &$b) {} $b = &$a; $c = $b; } function use_inside() { $ar = array(); foreach ($ar as &$a) { $a++; } } function variable_variable() { $ar = array(); foreach ($ar as &$$a) {} $a++; $$a++; } function closure1() { $ar = array(); foreach ($ar as &$a) {} function ($a) { $a++; }; } function closure2() { function () { $ar = array(); foreach ($ar as &$a) {} }; $a++; } function closure3() { function () { $ar = array(); foreach ($ar as &$a) {} $a++; // Reuse of $a }; } function closure4() { $ar = array(); foreach ($ar as &$a) {} function ($a) { unset($a); }; $a++; // Reuse of $a } ~~~~~~~~~~ -warning:6:3 -warning:12:8 -warning:18:10 -warning:27:20 -warning:33:3 -warning:52:3 -warning:110:5 -warning:120:3 +warning:6:3:XHP39:Reuse of Iterator References +warning:12:8:XHP39:Reuse of Iterator References +warning:18:10:XHP39:Reuse of Iterator References +warning:27:20:XHP39:Reuse of Iterator References +warning:33:3:XHP39:Reuse of Iterator References +warning:52:3:XHP39:Reuse of Iterator References +warning:110:5:XHP39:Reuse of Iterator References +warning:120:3:XHP39:Reuse of Iterator References diff --git a/src/lint/linter/xhpast/rules/__tests__/reused-iterator/reused-iterator.lint-test b/src/lint/linter/xhpast/rules/__tests__/reused-iterator/reused-iterator.lint-test index 29d31b72..bfe122ce 100644 --- a/src/lint/linter/xhpast/rules/__tests__/reused-iterator/reused-iterator.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/reused-iterator/reused-iterator.lint-test @@ -1,58 +1,58 @@ $jj) { // Reuse of $ii. } } for ($jj = 0; $jj < $len; $jj++) { foreach ($list as $jj) { // Reuse of $jj. } } for ($ii = 0; $ii < $len; $ii++) { foreach ($list as $ii => &$jj) { // Reuse of $ii. } } for ($jj = 0; $jj < $len; $jj++) { foreach ($list as &$jj) { // Reuse of $jj (by reference). } } for ($ii = 0; $ii < $len; $ii++) { for ($jj = 0; $jj < $len; $jj++) { foreach ($list as $kk) { // No reuse. } } } for ($ii = 0; $ii < $len; $ii++) { for ($ii = 0; $ii < $len; $ii++) { // Reuse of $ii, pure for loops. } } for ($ii = 0; $ii < $len; $ii++) { for ($jj = $ii; $jj < $jjlen; $jj++) { // No reuse. } } foreach ($list as $thing) { for ($thing = 0; $thing < $len; $thing++) { // Reuse of $thing, for within foreach. } } ~~~~~~~~~~ -error:4:11 -error:10:11 -error:16:11 -error:22:11 -error:36:7 -error:48:7 +error:4:11:XHP23:Reuse of Iterator Variable +error:10:11:XHP23:Reuse of Iterator Variable +error:16:11:XHP23:Reuse of Iterator Variable +error:22:11:XHP23:Reuse of Iterator Variable +error:36:7:XHP23:Reuse of Iterator Variable +error:48:7:XHP23:Reuse of Iterator Variable diff --git a/src/lint/linter/xhpast/rules/__tests__/self-class-reference/self-class-references.lint-test b/src/lint/linter/xhpast/rules/__tests__/self-class-reference/self-class-references.lint-test index 33c30f4d..8cf29ac3 100644 --- a/src/lint/linter/xhpast/rules/__tests__/self-class-reference/self-class-references.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/self-class-reference/self-class-references.lint-test @@ -1,37 +1,37 @@ f(); } public static function v() { $this->f(); } } ~~~~~~~~~~ -error:8:5 +error:8:5:XHP13:Use of `$this` in Static Context diff --git a/src/lint/linter/xhpast/rules/__tests__/tautological-expression/tautological-expression.lint-test b/src/lint/linter/xhpast/rules/__tests__/tautological-expression/tautological-expression.lint-test index fa1a7d8e..c9200a3a 100644 --- a/src/lint/linter/xhpast/rules/__tests__/tautological-expression/tautological-expression.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/tautological-expression/tautological-expression.lint-test @@ -1,23 +1,23 @@ m(3) < $x->m(3)) {} if ($y[2] - $y[2]) {} if ($x == $y) {} // See xhpast 0.54 -> 0.55. return $a->sub->value < $b->sub->value; $skip_cache = true || $some_complicated_expression; $skip_cache = $a || $b; $skip_cache = false && something(); $skip_cache = f(); ~~~~~~~~~~ -error:3:5 -error:5:5 -error:7:5 -error:14:15 -error:16:15 +error:3:5:XHP20:Tautological Expression +error:5:5:XHP20:Tautological Expression +error:7:5:XHP20:Tautological Expression +error:14:15:XHP20:Tautological Expression +error:16:15:XHP20:Tautological Expression diff --git a/src/lint/linter/xhpast/rules/__tests__/this-reassignment/class.lint-test b/src/lint/linter/xhpast/rules/__tests__/this-reassignment/class.lint-test index e4081b0d..a6c96f18 100644 --- a/src/lint/linter/xhpast/rules/__tests__/this-reassignment/class.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/this-reassignment/class.lint-test @@ -1,8 +1,8 @@ $m) {} $a++; $b++; $c++; $d++; $e++; $f++; $g++; $h++; $i++; $j++; $k++; $l++; $m++; $this++; $n++; // Only one that isn't declared. extract(z()); $o++; } function g($q) { $$q = x(); $r = y(); } final class C { public function m() { $a++; x($b); $c[] = 3; $d->v = 4; $a = $f; } } function worst() { global $$x; $y++; } function superglobals() { $GLOBALS[$_FILES[$_POST[$this]]]++; } function ref_foreach($x) { foreach ($x as &$z) {} $z++; } function has_default($x = 0) { $x++; } function declparse( $a, Q $b, Q &$c, Q $d = null, Q &$e = null, $f = null, $g = null, &$h = null, &$i = null) { $a++; $b++; $c++; $d++; $e++; $f++; $g++; $h++; $i++; $j++; } function declparse_a(Q $a) { $a++; } function declparse_b(Q &$a) { $a++; } function declparse_c(Q $a = null) { $a++; } function declparse_d(Q &$a = null) { $a++; } function declparse_e($a) { $a++; } function declparse_f(&$a) { $a++; } function declparse_g($a = null) { $a++; } function declparse_h(&$a = null) { $a++; } function static_class() { SomeClass::$x; } function instance_class() { $a = $this->$x; } function exception_vars() { try { // This is intentionally left blank. } catch (Exception $y) { $y++; } } function nonuse() { isset($x); empty($y); $x++; } function twice() { $y++; $y++; } function more_exceptions() { try { // This is intentionally left blank. } catch (Exception $a) { $a++; } catch (Exception $b) { $b++; } } abstract class P { abstract public function q(); } function x() { $lib = $_SERVER['PHP_ROOT'].'/lib/titan/display/read/init.php'; require_once $lib; f(((($lib)))); // Tests for paren expressions. f(((($lub)))); } final class A { public function foo($a) { $im_service = foo($a); if ($im_servce === false) { return 1; } return 2; } } function arrow($o, $x) { echo $o->{$x->{$x->{$x.$x->{$x}}.$x}}; } function strings() { $a = 1; echo "$a"; echo "$b"; } function catchy() { try { dangerous(); } catch (Exception $ex) { $y->z(); } } function some_func($x, $y) { $func = function ($z) use ($x) { echo $x; echo $y; echo $z; }; } function some_func($x, $y) { $func = function ($z) use ($x) { echo "$x/$y/$z"; }; } ~~~~~~~~~~ -error:28:3 -error:42:5 -error:43:7 -error:44:5 -error:45:5 -error:46:10 -error:87:3 This stuff is basically testing the lexer/parser for function decls. -error:104:15 Variables in instance derefs should be checked, static should not. -error:118:3 isset() and empty() should not trigger errors. -error:122:3 Should only warn once in this function. -error:144:8 -error:150:9 -error:164:9 -error:171:5 -error:178:10 -error:185:14 +error:28:3:XHP5:Use of Undeclared Variable +error:42:5:XHP5:Use of Undeclared Variable +error:43:7:XHP5:Use of Undeclared Variable +error:44:5:XHP5:Use of Undeclared Variable +error:45:5:XHP5:Use of Undeclared Variable +error:46:10:XHP5:Use of Undeclared Variable +error:87:3:XHP5:Use of Undeclared Variable +error:104:15:XHP5:Use of Undeclared Variable +error:118:3:XHP5:Use of Undeclared Variable +error:122:3:XHP5:Use of Undeclared Variable +error:144:8:XHP5:Use of Undeclared Variable +error:150:9:XHP5:Use of Undeclared Variable +error:164:9:XHP5:Use of Undeclared Variable +error:171:5:XHP5:Use of Undeclared Variable +error:178:10:XHP5:Use of Undeclared Variable +error:185:14:XHP5:Use of Undeclared Variable diff --git a/src/lint/linter/xhpast/rules/__tests__/unexpected-return-value/construct.lint-test b/src/lint/linter/xhpast/rules/__tests__/unexpected-return-value/construct.lint-test index 894c3f6b..e1173e7d 100644 --- a/src/lint/linter/xhpast/rules/__tests__/unexpected-return-value/construct.lint-test +++ b/src/lint/linter/xhpast/rules/__tests__/unexpected-return-value/construct.lint-test @@ -1,8 +1,8 @@ $bar; // okay ~~~~~~~~~~ -error:3:1 +error:3:1:XHP3:Use of Variable