phptools-docs
phptools-docs copied to clipboard
Identifying type of global variables
I have included PHP extension in the recommendations for the VSCode setup for Moodle development .
Moodle as a product started over 20 years ago and some architectural decisions from the early days are hard to change because of multiple plugins that exist. For example, Moodle has a bunch of global variables.
There are some 'hacks' to trick IDEs into understanding what type global variables have.
For example, we have the following code in lib/setup.php that is included in config.php that is included on every page: https://github.com/moodle/moodle/blob/master/lib/setup.php#L462-L467
// this is a funny trick to make Eclipse believe that $OUTPUT and other globals
// contains an instance of core_renderer, etc. which in turn fixes autocompletion ;-)
if (false) {
$DB = new moodle_database();
$OUTPUT = new core_renderer(null, null);
$PAGE = new moodle_page();
}
So far it worked in all IDEs and was usually working in VSCode with PHP extension. But recently more and more often VSCode (with PHP extension) fails to detect the type of the $DB variable and does not autocomplete the methods or hints parameters.
So basically my question is - how can we make PHP extension know the types of the common global variables? (except for hinting it in every single function where it is used).
Also, can other extensions communicate with PHP extension and "tell" about some project-specific magic? Because I work on MDLCode extension and if there is a way for mdlcode extension to "communicate" with php extension and notify about the 'magic' variables and functions in Moodle, it would be great.
here is another example, I keep seeing these kind of errors here and there. They sometimes happen and sometimes not. File config.php reads:
<?php
$CFG = new stdClass();
$CFG->dirroot = '.';
In Moodle it is included in every single file and $CFG is available everywhere. But PHP extension sometimes does not know about it:
When I was recording this video for setting up VSCode for Moodle development, I had to actually disable the error reporting on the error '407' so all these errors do not appear in the video
Hello Marina, thank you for your contribution! and for the question.
Typically, the global variable should be annotated with a doc comment:
/** @var stdClass $CFG */
$CFG = ...
or
/** @global stdClass $CFG */
We have some tips for annotating variable types at https://docs.devsense.com/en/vscode/editor/completion#optimizing-completion
I'll try Moodle and similar use-cases, to see if it works as expected. From what you've posted, we should be able to behave nicely.
Hello Jakub Thanks but it does not answer my question.
My question was - how can I make PHP extension understand the classes of global variables without adding doc comment to every single instance.
For example, running on the moodle codebase git grep -e 'global .*\$DB' gives 8712 results.
The "hack" we had in lib/setup.php worked for all other IDEs so far.
I see, this hack should work with Php Tools as well. I'll add some more tests and see what's wrong.
Also, Jakub, I was experimenting with changing the version of the php extension and I found something that may be interesting for you. This is my test scenario:
- open Moodle source code, I checked out latest stable branch: https://github.com/moodle/moodle/tree/MOODLE_402_STABLE
- open any file, I opened admin/presets/classes/manager.php (I'm pretty sure it does not matter, all files behave the same)
- set "PHP background analysis" to "all"
- wait until all reindexing finishes
- Line 567 has a call
$xmlwriter->full_tag- hover "full_tag" - you will see information about the method. If you don't see it, reindexing is not finished. This works on any version, just takes some time. - Line 560 has code
$DB->get_records(...), hover the method name ("get_records") - there should be information about this method - this has broken recently.
This works in PHP extension version 1.38.13826 This does not work in the version 1.38.13899
Another question, why the "PHP background analysis" setting affects it, I thought its intention was to highlight problems, not index source code. I actually do not want problems highlighting in absolutely all files, there are over 10K problems, it is not helpful to read and makes IDE slower.
working on the globals;
- [x] we did not recognize
global $CFG;outside a function scope actually - [x] we did not treat
/** @global ... */above assignments properly
@marinaglancy we've released 1.40.14103 which improves recognition of global variables.
If they're in /vendor/ folder, you may need to run VSCode Command Clear vendor cache after this update.
The feature should be available now; please let us know if it's not working as expected. We can improve that for more specific cases.
Thank you.
Hello, Thank you for looking at it. The functions from global variable $DB are still not recognised (there is no text on hover and "go to definition" does not work).
However I found an interesting thing - if I open file lib/setup.php (that contains "false" block, see description) and wait for php-tools to index it, after that it starts recognising $DB functions in other files.
Is there a way to tell PHP tools to always index a particular file (through settings or from another extension)?
Thank you for trying that so quickly,
PHP tools index all the files in your workspace; is this the code we're talking about right?
if (false) {
$DB = new moodle_database();
$OUTPUT = new core_renderer(null, null);
$PAGE = new moodle_page();
}
hello! I'm sorry I missed the last question, I think I went on holidays that day and stopped checking emails.
I regret to inform that this is still an issue and PHP extension alone does not implement hoverprovider and definitionprovider for the global $DB. Somehow autocompletion works, so if I type $DB->get_re it completes it.
We found a workaround though, we enable both PHP extension and intelephense. Intelephense provides both hover and go to definition.
All the previous conversation is still applicable. Answering to your last question - yes, this is how we trick IDEs into detecting the type of the globals , see https://github.com/moodle/moodle/blob/v4.3.0/lib/setup.php#L1130-L1136
Thank you @marinaglancy - I'll clone the repo and make it working.
I see, we'll try to fix this one.
Also, I've noticed there are tons of false warnings, especially in Moodle. I'll try to get them fixed as well.
Thanks Jakub!
Yes there are some false positives, the most annoying is that $OUTPUT->header() is highlighted as missing parameters because the extension thinks for some reason that $OUTPUT is an instance of mod_lesson_renderer and not an instance of core_renderer. I have no idea why :)
But also there are a lot of errors because phpdocs in Moodle are often messed up. I'm actually fixing some of them every major release, for example for the next release I'm trying to get https://tracker.moodle.org/browse/MDL-80820 in -
Here is the respective diff: https://github.com/moodle/moodle/compare/main...marinaglancy:moodle:MDL-80820
@marinaglancy Nice! Also, there are some @var \ annotations (just \ instead of a class name) and more.
I'm tracking more than 80 000 warnings - but I'm sure I'll get most of them disappear.
I'll take a look at $OUTPUT and $DB as well.
Thank you! For the next release we just added .phpstorm.meta.php to help with dependency injections:
https://github.com/moodle/moodle/blob/main/.phpstorm.meta.php
It works well in VSCode too. I was actually looking if we could use it to declare types of globals somehow but it does not look like this is supported in the standard. However if there is an option to add something to .phpstorm.meta.php it will be a very acceptable solution for us too.
Not sure, .phpstorm.meta.php allows to "override" global variables types (full spec can be found on https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html#navigate-to-a-metadata-directive).
As of now, the editor remembers all possible assignments to global variables, and all @global annotations, and it uses that.
We could introduce some custom annotation, or just be "smarter" in specific cases ... I'm still looking into the $OUTPUT variable. (It seems we mixed up $OUTPUT with another variable $output).
Preparing pre-release 1.45.15201 where the mouse hover works as I would expect it. Is the following correct?
The incorrect core_renderer of $OUTPUT is caused by this annotation:
- https://github.com/moodle/moodle/blob/c895def59b1ba0dba8b0306059cd4f314358b78a/lib/blocklib.php#L1537
- https://github.com/moodle/moodle/blob/c895def59b1ba0dba8b0306059cd4f314358b78a/lib/blocklib.php#L1615
Yes this looks good! I'm now on leave until late next week, so I won't be able to check at the computer. I asked a couple of people from the team to keep an eye on this thread but it's the Easter/school holidays so a lot of us are away ATM.
Thank you very much for looking at it, even if we can only improve $DB it will be great. It is the most used global in Moodle.