SanderRonde / phpstan-vscode

PHPStan plugin for VSCode
https://marketplace.visualstudio.com/items?itemName=SanderRonde.phpstan-vscode
MIT License
43 stars 8 forks source link

Unable to encode JSON: Recursion detected #54

Closed rubinlinux closed 6 months ago

rubinlinux commented 7 months ago

I'm using the preview release--

Something about the PHPStanVSCodeTreeFetecher is causing phpstan to fail with recursion detected while attempting to output json.

If I copy the command line from the logs, I get something like:

> vendor/bin/phpstan analyse -c phpstan.neon --error-format=json --no-interaction -a ~/.vscode/extensions/sanderronde.phpstan-vscode-3.0.1/_config/autoload.php  -c ~/.vscode/extensions/sanderronde.phpstan-vscode-3.0.1/_config/config.neon

{"totals":{"errors":1,"file_errors":11},"files":{"/home/myusername/develop/myproject/myapp.myproject.com/app/docs/teachers/auth/parent-report/lib/ParentReportDAO.php":{"errors":4,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $list_of_sids follows optional parameter $db.","line":70,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $sid follows optional parameter $db.","line":103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $student_info follows optional parameter $db.","line":265,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $sid follows optional parameter $db.","line":325,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/docs/teachers/auth/student-report/lib/StudentReportDAO.php":{"errors":1,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $list_of_cbm_types follows optional parameter $tid.","line":292,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/libs/DBAccess.php":{"errors":5,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $scope follows optional parameter $academic_years_tested.","line":824,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope_id follows optional parameter $academic_years_tested.","line":824,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $grade follows optional parameter $academic_year.","line":1103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope follows optional parameter $academic_year.","line":1103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope_id follows optional parameter $academic_year.","line":1103,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/libs/utils/states.php":{"errors":1,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $default follows optional parameter $name.","line":14,"ignorable":false}]}},"errors":["Child process error (exit code 1): Error: Unable to encode JSON: Recursion detected\n"]}

But if I leave out the phpstan-vscode neon file, the error does not happen

vendor/bin/phpstan analyse -c phpstan.neon --no-interaction -a ~/.vscode/extensions/sanderronde.phpstan-vscode-3.0.1/_config/autoload.php --error-format=json

{"totals":{"errors":0,"file_errors":13},"files":{"/home/myusername/develop/myproject/myapp.myproject.com/app/docs/select_cbm.php":{"errors":2,"messages":[{"message":"Variable $teacherDAO might not be defined.","line":137,"ignorable":true},{"message":"Variable $teachers might not be defined.","line":148,"ignorable":true}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/docs/teachers/auth/parent-report/lib/ParentReportDAO.php":{"errors":4,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $list_of_sids follows optional parameter $db.","line":70,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $sid follows optional parameter $db.","line":103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $student_info follows optional parameter $db.","line":265,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $sid follows optional parameter $db.","line":325,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/docs/teachers/auth/student-report/lib/StudentReportDAO.php":{"errors":1,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $list_of_cbm_types follows optional parameter $tid.","line":292,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/libs/DBAccess.php":{"errors":5,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $scope follows optional parameter $academic_years_tested.","line":824,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope_id follows optional parameter $academic_years_tested.","line":824,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $grade follows optional parameter $academic_year.","line":1103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope follows optional parameter $academic_year.","line":1103,"ignorable":false},{"message":"Deprecated in PHP 8.0: Required parameter $scope_id follows optional parameter $academic_year.","line":1103,"ignorable":false}]},"/home/myusername/develop/myproject/myapp.myproject.com/app/libs/utils/states.php":{"errors":1,"messages":[{"message":"Deprecated in PHP 8.0: Required parameter $default follows optional parameter $name.","line":14,"ignorable":false}]}},"errors":[]}
rubinlinux commented 7 months ago

Trying to track this down, some interesting items:

1: This is not either call to json_encode inside TreeFetcher.php, I replaced both with a test string, and the outcome is the same

2: without --error-format=json I still see that error, at the end, after all my file-connected errors print out:

...
 ------ -------------------------------------------------------------------------------------- 
  Line   app/libs/utils/states.php                                                             
 ------ -------------------------------------------------------------------------------------- 
  14     Deprecated in PHP 8.0: Required parameter $default follows optional parameter $name.  
 ------ -------------------------------------------------------------------------------------- 

 -- ------------------------------------------------------------------------------------- 
     Error                                                                                
 -- ------------------------------------------------------------------------------------- 
     Child process error (exit code 1): Error: Unable to encode JSON: Recursion detected  

 -- ------------------------------------------------------------------------------------- 

So the error is happening somewhere inside phpstan, but only when TreeFetcher is enabled?

rubinlinux commented 7 months ago

However, there are 2 calls to json_encode in TreeFetecher, and neither of them is responsible (as indicated by replacing them with '' strings)

SanderRonde commented 7 months ago

Hey sorry for being a bit slow to respond (am a bit busy). Could it maybe still be related to the TreeFetcher? Maybe PHPStan didn't clear the cache correctly (and just showed you the same error as before) or maybe you edited a different TreeFetcher? Just guessing here since I haven't had a look at the relevant code yet.

Will probably take a look at this coming weekend

SanderRonde commented 7 months ago

Hmm yeah it does sound unlikely that this is coming from the TreeFetcher since the json_encode call should just return false when it fails (it has no JSON_THROW_ON_ERROR flag). Can you maybe isolate it down to a specific file or piece of code? Maybe by running the command you ran before but checking a single file instead of a folder? Otherwise maybe try disabling the processNode function in TreeFetcher (by early-returning). Then it'll effectively do nothing at all, that could provide some clarity.

gglnx commented 6 months ago

I already posted to https://github.com/SanderRonde/phpstan-vscode/issues/57#issuecomment-1991337565, but this looks like my problem too. I tried to comment out the json_encode in TreeFetcher and nothing changed. It ran without errors and using the cache only after early-returning public function processNode(Node $node, Scope $scope): ?array as suggested. I've run the generated command with --debug and it outputted a never ending stream of the same error: Warning: var_export does not handle circular references in phar:///[redacted]/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/ResultCache/ResultCacheManager.php on line 555

SanderRonde commented 6 months ago

Ah that's interesting, so it looks like it fails when serializing it into the resultCache. I've got a couple hunches on what it might be. I've attached a couple of variations of the TreeFetcher. Could you please try them and report which ones worked and which ones didn't? Depending on how you did the replacing before you might need to change the REPORTER_FILE back after copying in these files. Thanks in advance!

TreeFetcher-variants.zip

gglnx commented 6 months ago

Sure:

SanderRonde commented 6 months ago

Thank you so much for checking it. I'm pretty sure I've found the error. It was the name of a variable being an expression (non-serializable) instead of a string, which I did not expect. I've attached a version of the TreeFetcher that should work. If it does, I'll fix the issue in the extension.

TreeFetcher.zip

gglnx commented 6 months ago

Works :)

SanderRonde commented 6 months ago

Awesome, will add the fix in the next (pre-release) version, 3.0.5. Thanks again for checking