New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PreloadExplicitClassSymbolsFixer - introduction #4891
Conversation
This looks like a good idea but I don't have all the background information required to understand it.
Can you elaborate a bit please? |
Look at the Symfony preloader. It reads all public functions for their arguments and return types. It makes sure to preload them. However, Preloaders can not find class use App\Foo;
class Case003
{
private $foo;
public function __construct()
{
$this->foo = new Foo();
}
} That is why you need to help the preloader by loading the class Foo in runtime. That could easily be done by adding See this PR as an example for such work: symfony/symfony#36103 |
This is my first fixer. I would appreciate some help with the |
use App\Foo; | ||
|
||
class_exists('App\Foo'); | ||
class_exists(Foo::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a nice solution. It will duplicate the class_exists(Foo::class);
for the App\Foo
class. However, it is soo much more easier.
Allowing this would avoid parsing use statements and class alias to figure out that App\Foo
is already "preloaded"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(...) and class alias (...)
I don't see class alias here in this test case, but if you need to handle them, maybe use https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/2.16/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php ?
6b1b0f0
to
fd3ac34
Compare
public function getDefinition() | ||
{ | ||
return new FixerDefinition( | ||
'Adds extra `class_exists` before a class to help opcache.preload to discover always-needed symbols.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice idea to make this as a fixer!
Please provide a $description
parameter with the reasoning, especially:
- why the rule is worth to use?
what classes we don't need to preload, ie classes that is found by reflection
and why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a desciption
$class = $tokens[$tokens->getPrevMeaningfulToken($i)]->getContent(); | ||
$classes[] = $class; | ||
} elseif ($token->isGivenKind(T_OBJECT_OPERATOR)) { | ||
// FIXME Better check if function call to avoid false positive like "$this->bar = 2;" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nyholm , are those 3 FIXME
cases covered by tests already? if not, maybe we can add a test case for each, so we can easier understand what is example code snippet you struggle with and expected outcome ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are. They are the failing tests.
I'll work with them now to see if I can make sure they are green
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are green. Locally at least. =)
new VersionSpecification(70300) | ||
), | ||
], | ||
'A script for opcache.preload should classes that are used by the average ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A script for opcache.preload should classes that are used by the average HTTP request.
should classes
? sorry, i can't understand this sentence
], | ||
'A script for opcache.preload should classes that are used by the average ' | ||
.'HTTP request. A good preloading script uses reflection to load the ' | ||
.'hot class and all classes it depends on. Reflection cannot always find ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is hot
class?
there is only ONE hot class
, or many of them (classes
)?
'A script for opcache.preload should classes that are used by the average ' | ||
.'HTTP request. A good preloading script uses reflection to load the ' | ||
.'hot class and all classes it depends on. Reflection cannot always find ' | ||
.'all dependencies. Example: Classes used in the constructor or dependent ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reflection cannot always find all dependencies
why?
(sorry for dummy questions, I am unaware about the idea and description here is not helping me to get what exactly should be added as outcome of this rule and why, and what not as it's automatically picked up by some preloading script)
} | ||
|
||
// TODO parse public properties | ||
// TODO Get the class' interfaces and parent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marker
(so we don't merge before it's solved)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nyholm , would you like to finalize this PR?
$newTokens[] = new Token([CT::T_CLASS_CONSTANT, 'class']); | ||
$newTokens[] = new Token(')'); | ||
$newTokens[] = new Token(';'); | ||
$newTokens[] = new Token([T_WHITESPACE, "\n"]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$newTokens[] = new Token([T_WHITESPACE, "\n"]); | |
$newTokens[] = new Token([T_WHITESPACE, $this->whitespacesConfig->getLineEnding()]); |
(you need to implement WhitespacesAwareFixerInterface
also)
Does anyone know if this PR is relevant in 2023 and PHP 8.2 (at the brink of 8.3)? @Nyholm, maybe @nicolas-grekas? 🤔 |
I was thinking of this pr the other day. Let’s close it. If someone wants to pick it up, then feel free to open. |
The idea is to help a preloader to find classes that are used by adding a bunch of
class_exists
in the file.A typical preloader uses reflection. See Symfony.
This PR is a draft to give an idea what I want to do. Please review first commit to get the idea without all complex logic.
TODO