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
[WIP] Move to version 1.0 #68
Conversation
- PHP8+ strictly typed - Bump dependencies to the latest version - Move render logic from builders to some Twig templates and one Twig extension - Refactor the parser to infer types both from code and docblock
Refine generator and fix the generation of method body. Add more tests. Refactor parser to infer the types from the code first, than from the docblock.
Fix all Psalm errors, up to level 5.
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.
Thanks for the huge effort you put into this. I started reviewing but had to pause (I put a comment on how far I went) and I left comments until there.
As I'm not fully through yet, my question is: What's the advantage of using twig over writer + code-profiles + code-formatter (especially as the latter two are external to this and can be developed independently)?
@@ -0,0 +1,42 @@ | |||
<?php declare(strict_types=1); |
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's the purpose of this file? A fixture?
- Why is that file in repo root?
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.
Error! I forgot to remove it. It's a fixture.
@@ -16,62 +21,12 @@ | |||
* @author Thomas Gossmann | |||
*/ | |||
class CodeFileGenerator extends CodeGenerator { |
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.
seems like, this file is kept for backwards compatibility reasons? Then mark it @deprecated
return $this->twig->render($template, ['model' => $model, 'config' => $this->config]); | ||
} | ||
|
||
protected function sortModel(GenerateableInterface $model): void { |
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 method itches me. Before with the builders, each respective builder was responsible for its own model (and what it was sorting). Now everything in one class couples this class to every, this is not very robust in terms of architecture and later maintanability as borders become blurry. Better have a SOLID arch here (see comment above).
*/ | ||
public function generate(GenerateableInterface $model): string { | ||
return $this->generator->generate($model); | ||
$this->sortModel($model); |
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.
To have clear responsibilites, what about:
$modelGenerator = ModelGeneratorFactory::create($model, $this->config);
$modelGenerator->sort();
it keeps the idea of ModelBuilder
but extracts the building part of it. Keeping it with a class that has responsibilities for each model type and what to do with each model as prep for turning code into their respective strings.
Maybe understand it as these ModelGenerators
do the meta work before generation and the CodeGenerator
(as a generic class) orchestrates the ModelGenerator
and connects it to the writer (twig now).
PS. Not necessarily name it ModelGenerator
(it was just the name been used before). I think there is a better name then.
*/ | ||
public function compare($a, $b) { | ||
public function compare(mixed $a, mixed $b): int { |
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.
Ah shooot. I was suggesting this:
public function compare(mixed $a, mixed $b): int { | |
public function compare(PhpConstant $a, PhpConstant $b): int { |
until I realized without mixed
it wouldn't match the Comparator
interface. Dang php, it's time for generics 😂
* @return $this | ||
*/ | ||
public function setRequiredFiles(array $files) { | ||
$this->requiredFiles = new Set($files); | ||
public function setRequiredFiles(array|Set $files): self { |
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 about?
public function setRequiredFiles(array|Set $files): self { | |
public function setRequiredFiles(iterable $files): self { |
I checked, that Set
uses Iterator
- dunno exactly which is the more broader typehint here (would also upstream this to phootwork then).
* @return bool | ||
*/ | ||
public function hasUseStatement(string $qualifiedName): bool { | ||
return $this->useStatements->contains($qualifiedName); | ||
} | ||
|
||
public function hasUseStatementsToRender(): bool { |
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.
public function hasUseStatementsToRender(): bool { | |
public function needsUseStatementGeneration(): bool { |
render seems a bit out of context, we want to know whether to generator them or not.
@@ -1,8 +1,17 @@ | |||
<?php | |||
declare(strict_types=1); | |||
<?php declare(strict_types=1); |
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 only got so far ---
Well, my idea was to replace code-profiles and code-formatter libraries (which are still in early state) with something else easy to maintain (for us) and easy to customize for the users. Anyway, I've submitted a work-in-progres PR just to discuss this details: it's a very big change and, maybe, from the architectural point of view, the original code is better. During the next week, I'll try to study php-code-formatter again 😅 |
hi guys, thanks for all the efforts on this PR I wondered if this is still happening and has a good chance of making it into master? |
@LTSCommerce I'm sorry I left this pr pending, I've been busy till now. Anyway, it's time to really move forward this awesome library. @gossi please, show us the way! 😄 If you like this refactor, I'll work on it to include all your suggestions, if you prefer the |
Great thanks for replying @cristianoc72 For me, I would just love to get this library working with the latest PHP Parser and PHP8 in general which it looks like this PR has mostly achieved. Note I am seeing some bugs, could open a PR against your fork if you want @cristianoc72 ... getting a bit complex though first one I found is \gossi\codegen\parser\visitor\parts\ValueParserPart::getExpression The match statement does not match all possible nodes, so I added a meaningful exception and also added the one that I found so far:
|
This is how far I got ... after ~3 hours of review: I wanted to come back, but never did - and even now, I would probably need to start from the top again for context (not detailed view). This is just sharing my current status. I'm not holding against it. I find it super nice, this is still in use and people are here to maintain it and even drive it forward - this is amazing. So, how we best make this possible? To be honest, this is too much to review in one go. An idea is to chunk this down into maintainable and reviewable ones. I have an idea: Make a new branch from master: Also thanks to @LTSCommerce for jumping in. Would you provide a helping hand for the review? Would that work? |
Happy to help if I can For now I've made a fork of the @cristianoc72 fork so that I can continue to work on updating the package I'm working on I've no deep experience with this code base beyond just being a user, but I do definitely approve of using Twig for the code templating, it's a good idea. For me the priority is something that works and I can use and so far with this version it seems to be doing that pretty much though I'm still testing. |
@gossi Great! I'll start soon the PR-splitting and, while doing it, I'll include all yours and @LTSCommerce's suggestions! When I'm ready with the first chunk, I'll close this PR and submit a new one against Thank you! |
Awesome |
Ready for the first chunk. @gossi please, could you create the |
done. Can't you do that on your own? If not I need to check permissions |
No,I can't: not enough permissions for this repo. |
Ah, I checked. For repos on personal accounts, there is only collaborator and repo owners and they have fixed access rights. I thought you were able to do this on your own, my bad. So the personal repo actually doesn't really work for this then. I think, there are some repos where you are actually maintaining them rather then me. I see them as:
* basically not all of them, but they belong to the collection of my open php repositories (and somehow they depend on each other). As I've learned, they are better worked on, on an orga account, than my personal one. I would set them free to move into an org and be assisting there. Either |
Yes, moving the libraries to an organization is a good idea, for sure! Anyway, if you like to leave phootwork as is, because it's a coherent and easily understandable repo, creating a new organization it's ok for me. Please choose the name, you are better than me! The only name that came to my mind is gossilibs 😆 |
PR #69 opened. I'll close this one, when we decide the organization for this repo. |
|
@gossi continuing on the road of breakdance, the name could be |
oh yes, please. This is brilliant !!! Please create the org, so I can start transfer over the repos |
I had no idea. And this morning I checked if there is a disney princess with |
Feeling privileged to witness the birth of something new, a piece of history... 👍 |
😄 I'm glad you like it! |
I moved all my projects to the new org. Sooo happy with the name. I'll let it up to you to figure out how to best send PRs for this new repo. Shall we close this one? |
oooh, maybe you can create a team for this org. Afair within such a team, we have a chat. So we can discuss how to organize things in this org. Dunno if helpful but at least I'd give it a try. |
Great!! |
Current Status
Changes
php-code-profiles
andphp-code-formatter
CodeFileGeneratorConfig
intoCodeGeneratorConfig
true
by defaultcodeStyle
to choose between them.Builders refactor
With this PR,
gossi\codegen\generator\CodeGenerator
class is the only responsible of the model generation: all the building and writing logic happens into Twig templates and one extensiongossi\codegen\utils\TwigExtension
.Now, it's possible to create our own code style by simply copy-paste-modify one or more templates.
You can find the templates into
resources/templates
directory.Into
resources/templates/default
there are the files to render the code with the default (phootwork) code style, while intoresources/templates/psr-12
there are the psr-12 templates.All the files have self-explained names (i.e.
class.twig
contains the logic to render thePhpClass
objects) so it's very easy to understand which template to overwrite.Let's show it by an example.
Let's suppose we like PSR-12 code style but we want the
declare(strict_types=1)
instruction on the same line, one space after<?php
.my/project/templates/dir
) into our project, to put the modified file.CodeFileGenerator
object writes the file byresources/templates/psr-12/file.twig
so let's copy-paste it intomy/project/templates/dir
.my/project/templates/dir/file.twig
, remove the first three lines and write:Now, we have to configure our
CodeFileGenerator
to use thepsr-12
code style and to search the templates in our own directory firstly:That's all! Now, the generator searches the needed templates firstly into our project directory, then into
resources/templates/psr-12
.