Comments (12)
And for templates..
$blueprint = $engine->classFromTemplate('MyClassTemplate');
$blueprint->addMethod(..);
from php-parser.
Arguments are tricky, because they could break the fluid chain.
So let's try to squeeze it all in one method "addArgument" (or "addParam" if you like).
$classBlueprint->addMethod('foo')
->makeProtected()
// Argument with type hint and doc block.
->addArgument('arg0', 'Arg0Interface', 'This argument is required.')
// Argument with default value, type hint and doc block.
->addOptionalArgument('arg1', NULL, 'Arg1Interface', 'This argument is optional.')
->setBody(..)
;
The following code would trigger an exception, because optional arguments cannot be followed by required arguments:
$classBlueprint->addMethod('foo')
->addOptionalArgument('arg0', NULL)
->addArgument('arg1')
;
from php-parser.
Did some code.
https://github.com/donquixote/PHP-Parser/tree/fluid
FluidBuilderFactory:
https://github.com/donquixote/PHP-Parser/blob/fluid/lib/PHPParser/FluidBuilderFactory.php
FluidBuilder_Class, _Method and _Function:
https://github.com/donquixote/PHP-Parser/tree/fluid/lib/PHPParser/FluidBuilder
How to use:
(equivalent to example in https://github.com/nikic/PHP-Parser/blob/master/doc/4_Code_generation.markdown)
require_once 'PHP-Parser/vendor/autoload.php';
$prettyPrinter = new PHPParser_PrettyPrinter_Default();
$factory = new PHPParser_FluidBuilderFactory();
$class = $factory->class('SomeClass')
->extend('SomeOtherClass')
->implement('A\Few', 'Interfaces')
->makeAbstract()
;
$class->addMethod('someMethod')
->makeAbstract()
->addRequiredParam('someParam', 'SomeClass')
;
$class->addMethod('anotherMethod')
->makeProtected() // ->makePublic() [default], ->makePrivate()
->addOptionalParam('someParam', 'test')
// it is possible to add manually created nodes
->addStmt(new PHPParser_Node_Expr_Print(new PHPParser_Node_Expr_Variable('someParam')))
;
// properties will be correctly reordered above the methods
$class->addProperty('someProperty')
->makeProtected()
;
$class->addProperty('anotherProperty')
->makePrivate()
->setDefault(array(1, 2, 3))
;
$node = $class->getNode();
$stmts = array($node);
echo $prettyPrinter->prettyPrint($stmts);
from php-parser.
Hm, to make it more fluid
$factory->class('SomeClass')
->extend('SomeOtherClass')
->addMethod('someMethod')
->makeAbstract()
->addRequiredParam('someParam')
->setTypeHint('SomeClass')
->makeByRef()
->END_PARAM()
->END_METHOD()
->addMethod(..)
[..]
from php-parser.
Ideally, it would also wrap the actual "saving to PHP file" in the fluid syntax, so you don't have to juggle around with different services for that.
E.g.
// Specify PSR-0 root dir where classes are to be saved.
$engine = new PSR0GeneratorEngine('/var/projects/mylib/generated');
$instance = $engine->namespace('My\Library')->class('MyClass')
->method(..)
->save()
->newInstance(..)
from php-parser.
Quite a lot here, I'll start with this:
<?php
$class->addMethod('someMethod')
->makeAbstract()
->addRequiredParam('someParam', 'SomeClass')
;
If I got it right, there are two things here:
a) This uses a $class->addMethod('foo')->...
pattern, rather than the existing $class->addStmt($factor->method('foo')->...)
one. Why do you want to make this change? Some of the thoughts behind the current design are:
- You can add the statements from any source, you are not forced to create them inline using the fluid interface. In particular you also have the possibility to create a method once using $factory->method() and then use the same method in multiple classes.
- If you want to stay in the fluid interface after the method you have something like the
END_METHOD()
calls you already introduces above. Imho that's not particularly nice. - You do not need to explicitly add a method for every kind of node one can add. In a class body you can have methods, you can have properties, you can have constants and you can have trait uses.
addStmts
covers all these cases, without requiring individual methods for the different types. It also allows the reuse of generation methods e.g. a class constant and methods can be used both by classes and interfaces (note: there are currently builders neither for interfaces nor for class constants ^^).
If the main concern here is keeping things short, then I have two suggestions:
- To make it a bit shorter one could rename
addStmt
toadd
. So the code would be->add($factory->method())
, which I guess reads a bit nicer. - Apart from
->addStmt()
the builders also have->addStmts()
methods. If you are adding multiple "things", you can avoid the boilerplate:
<?php
$class = $factory->class('SomeClass')->addStmts([
$factory->method('method1')->...,
$factory->method('method2')->...,
$factory->method('method3')->...,
$factory->property('prop1')->...,
$factory->property('prop2')->...,
])->getNode();
b) The code uses ->addRequiredParam('someParam', 'SomeClass')
which creates a parameter in a single method call, rather than the multiple calls on $factory->param()
. Apart from the comments from a) [regarding reusability and stuff] the issue here is order of optional bits of information (as you already point out in your second comment). You basically have to decide on some arbitrary order, which I personally don't like much (because it usually leads to the , null, null, null, 'foo'
pattern and because the meaning of a certain parameter often becomes unclear.)
Regarding this:
$classBlueprint->addMethod('foo')
->addOptionalArgument('arg0', NULL)
->addArgument('arg1')
;
I don't think that this need to throw an exception as PHP itself accepts optional arguments before required arguments. This can be used to create (required) parameters with nullable object type hints.
Thoughts? I'm leaving the rest for later. In any case, thanks for bringing up the topic again. Long time since I looked at the code generation APIs.
from php-parser.
Hi,
sorry, I also was busy with other things..
If it is all about brevity, then I think your points makes my suggestion obsolete.
But I have another motivation: Passing objects around.
E.g. you have a main component that starts with the code generation, but it passes some of the code generation work on to helper components.
$classBlueprint = $factory->class('MyClass');
$helper = ...
$helper->modifyClass($classBlueprint, $factory);
So, the helper needs the factory.
Either we pass the factory as an argument, or the helper needs to create one.
In the suggested version, the helper does not need to know the factory or how to create it. It only gets the class.
This would allow the helper to work with different implementations of the factory.
from php-parser.
b) The code uses ->addRequiredParam('someParam', 'SomeClass') which creates a parameter in a single method call, rather than the multiple calls on $factory->param(). Apart from the comments from a) [regarding reusability and stuff] the issue here is order of optional bits of information (as you already point out in your second comment). You basically have to decide on some arbitrary order, which I personally don't like much (because it usually leads to the , null, null, null, 'foo' pattern and because the meaning of a certain parameter often becomes unclear.)
Yes. This is the ugliest part of the proposal, I think.
from php-parser.
Although you will rarely get the null, null, null, 'foo'.
The suggested order is the best we could get if we squeeze it in one method.
from php-parser.
Is this issue still valid?
from php-parser.
I currently do not have an active interest in this issue.
I suggest to treat it as an idea, which can be considered for future development, or not.
No problem if you want to close it.
from php-parser.
Thanks for your clear and fast response.
In that case I suggest closing it, so there is more space for active issues.
from php-parser.
Related Issues (20)
- Special constants/keywords `self`, `static`, `parent`, `null`, `false`, `true` handled as normal constants with names. HOT 2
- Specific docblock not parsed after upgrading to 5.0 HOT 2
- Spelling issue: dereferenceable vs dereferencable HOT 1
- Preserve heredoc/nowdoc formatting HOT 11
- Allow opting in to multiline arrays explicitly HOT 7
- Inconsistent parens behaviour for ternary
- How to create an array item with a boolean value? HOT 2
- NameResolver will not work on Throws subnodes HOT 3
- Question: setting default value for properties or declaring them possibly null HOT 5
- Hexadecimal representation of strings HOT 2
- ValueError thrown when using PrettyPrinterAbstract::printFormatPreserving()
- TokenPolyfill issue on PHP 7.4 platform HOT 25
- Pretty printing removes leading whitespace from class declaration on first line HOT 6
- php-parser v4.19.0 got deprecated Optional parameter before required parameter on PrintableNewAnonClassNode.php HOT 1
- Is there a way to modify or remove comments? HOT 1
- Error "Syntax error, unexpected EOF on line" when parse valid php file HOT 1
- Is there a way to find places from where specific class/object methods are called HOT 6
- Confusing docs about the usage of NodeTraverser
- parse `$result = &($context->getPageData());` not ok,have any idea ? HOT 2
- Attempted to load class \"LNumber\" ... HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from php-parser.