Giter Club home page Giter Club logo

Comments (12)

donquixote avatar donquixote commented on August 17, 2024

And for templates..

$blueprint = $engine->classFromTemplate('MyClassTemplate');
$blueprint->addMethod(..);

from php-parser.

donquixote avatar donquixote commented on August 17, 2024

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.

donquixote avatar donquixote commented on August 17, 2024

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.

donquixote avatar donquixote commented on August 17, 2024

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.

donquixote avatar donquixote commented on August 17, 2024

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.

nikic avatar nikic commented on August 17, 2024

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:

  1. 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.
  2. 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.
  3. 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:

  1. To make it a bit shorter one could rename addStmt to add. So the code would be ->add($factory->method()), which I guess reads a bit nicer.
  2. 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.

donquixote avatar donquixote commented on August 17, 2024

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.

donquixote avatar donquixote commented on August 17, 2024

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.

donquixote avatar donquixote commented on August 17, 2024

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.

TomasVotruba avatar TomasVotruba commented on August 17, 2024

Is this issue still valid?

from php-parser.

donquixote avatar donquixote commented on August 17, 2024

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.

TomasVotruba avatar TomasVotruba commented on August 17, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.