diff --git a/linter.py b/linter.py index c6f8556..f71310f 100644 --- a/linter.py +++ b/linter.py @@ -40,7 +40,11 @@ class PHP(Linter): } regex = ( r'^(?PParse|Fatal) error:\s*' - r'(?P((?:parse|syntax) error,?)?\s*(?:unexpected \'(?P[^\']+)\')?.*) ' + # PHP 7 quotes the token with single quotes (`unexpected 'foo'`), PHP 8 + # with double quotes and a description (`unexpected token ";"`, + # `unexpected identifier "foo"`). + r'(?P((?:parse|syntax) error,?)?\s*' + r'(?:unexpected (?:[a-z-]+(?: [a-z-]+)* )?(?P["\'])(?P.+?)(?P=quote))?.*) ' r'(?:in - )?on line (?P\d+)' ) error_stream = util.STREAM_STDOUT diff --git a/tests/test_regex.py b/tests/test_regex.py index bda56d1..86b9ad3 100644 --- a/tests/test_regex.py +++ b/tests/test_regex.py @@ -102,3 +102,59 @@ def test_issue_55_message_filter_only_strips_trailing_source(self): 'message': 'Cannot redeclare f() (previously declared in Standard input code:2)', }, ) + + def test_issue_56_php8_quoted_tokens(self): + # PHP 8 writes `unexpected token ";"`, `unexpected identifier "bar"`, ... + self.assertMatch( + 'Parse error: syntax error, unexpected token ";", expecting "]" ' + 'in Standard input code on line 2', + { + 'error': 'Parse', + 'line': 1, + 'message': 'syntax error, unexpected token ";", expecting "]"', + 'near': ';', + }, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected identifier "bar" in Standard input code on line 2', + { + 'error': 'Parse', + 'line': 1, + 'message': 'syntax error, unexpected identifier "bar"', + 'near': 'bar', + }, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected variable "$y" in Standard input code on line 2', + {'error': 'Parse', 'line': 1, 'near': '$y'}, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected integer "2", expecting "," or ";" ' + 'in Standard input code on line 2', + {'error': 'Parse', 'line': 1, 'near': '2'}, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected double-quoted string "def" ' + 'in Standard input code on line 2', + {'error': 'Parse', 'line': 1, 'near': 'def'}, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected double-quoted string "a\'b", ' + 'expecting "," or ";" in Standard input code on line 1', + {'error': 'Parse', 'line': 0, 'near': "a'b"}, + ) + + self.assertMatch( + 'Parse error: syntax error, unexpected end of file in Standard input code on line 3', + { + 'error': 'Parse', + 'line': 2, + 'message': 'syntax error, unexpected end of file', + 'near': None, + }, + )