phptools-docs icon indicating copy to clipboard operation
phptools-docs copied to clipboard

Identifying type of global variables

Open marinaglancy opened this issue 2 years ago • 20 comments

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.

marinaglancy avatar Sep 28 '23 14:09 marinaglancy

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:

cfg_error

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

marinaglancy avatar Sep 28 '23 14:09 marinaglancy

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.

jakubmisek avatar Sep 28 '23 16:09 jakubmisek

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.

marinaglancy avatar Sep 29 '23 07:09 marinaglancy

I see, this hack should work with Php Tools as well. I'll add some more tests and see what's wrong.

jakubmisek avatar Sep 29 '23 13:09 jakubmisek

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.

marinaglancy avatar Sep 29 '23 14:09 marinaglancy

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

jakubmisek avatar Oct 15 '23 11:10 jakubmisek

@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.

jakubmisek avatar Oct 18 '23 16:10 jakubmisek

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.

jakubmisek avatar Oct 19 '23 13:10 jakubmisek

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)?

marinaglancy avatar Oct 19 '23 13:10 marinaglancy

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();
}

jakubmisek avatar Oct 19 '23 13:10 jakubmisek

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

marinaglancy avatar Mar 13 '24 14:03 marinaglancy

Thank you @marinaglancy - I'll clone the repo and make it working.

jakubmisek avatar Mar 26 '24 11:03 jakubmisek

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.

jakubmisek avatar Mar 26 '24 12:03 jakubmisek

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 avatar Mar 27 '24 11:03 marinaglancy

@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.

jakubmisek avatar Mar 27 '24 12:03 jakubmisek

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.

marinaglancy avatar Mar 27 '24 12:03 marinaglancy

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).

jakubmisek avatar Mar 27 '24 14:03 jakubmisek

Preparing pre-release 1.45.15201 where the mouse hover works as I would expect it. Is the following correct?

vsc-db-hover

jakubmisek avatar Mar 27 '24 14:03 jakubmisek

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

jakubmisek avatar Mar 27 '24 15:03 jakubmisek

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.

marinaglancy avatar Mar 27 '24 15:03 marinaglancy