Repository navigation
Simpla Templating Language #1
Description
Simpla Templating Language
We need a simple templating language that allows us to describe how the code generated from the AST should look like.
Why not Twig?
PHP-Printer will define an interface for the Templating Engine, allowing us to implement an adapter for any existing third party Templating Engine.
In Memio, we've done the same thing and provided by default a Twig implementation, since it is the most popular Templating Engine. However this choice made us miss the opportunity to work with Puli as they were reluctant to pull Twig dependency in all projects that'd use it, and it made phpspec core template incompatible, which is a shame since spec-gen is the main use case for Memio.
Also as it happens, Twig isn't as fantastic with generating PHP code as it is with generating HTML...
Requirements
- Our default mplementation shouldn't rely on any third party library
- It should be compatible with phpspec templates (replace
℅parameter%with value associated toparameterkey) - It should have a succinct syntax, so we can best see how the generated code should look like
Of course the tricky part is on how to make the syntax "succinct" especially in regards to the following challenges:
- Placeholders, to be replaced by given value
- Optional placeholders, to be replaced under condition (hint: if blocks can clutter the templates)
- Whitespace management including indentation, word separation, line separation, etc
Usage examples
Here's an example of generated code we'd like to be able to handle:
<?php
namespace Vendor\Project;
use Vendor\Project\Service\SayHello;
class HelloWorld
{
private $sayHello;
private static $count = 0;
public function __construct(SayHello $sayHello)
{
$this->sayHello = $sayHello;
}
public function say($name = self::WORLD)
{
$this->sayHello->to($name);
$this->count++;
}
}Notes:
- a class can be abstract or final. It can extend 0 or 1 parent and it can inherit 0 to many interfaces.
they should all be separated by a space, and if they aren't here there shouldn't be any trailing
spaces- a class can contain 0 to many constants, they shouldn't have an empty line between them but they
should have an empty line to separate them from properties or methods.
If there aren't any contstants, then there shouldn't be any empty line.
Constants are indented with 4 spaces, they can have a visibility (PHP 7.1) and a value,
they should be separated by a space and if there aren't any then there shouldn't be any trailing
whitespace, except for the indentation.- same rules for properties, except their value is optional and they can also be static
- a class can contain 0 to many methods, they should be all separated by an empty line.
Method signature shouldn't be longer than 80 characters, if it is then it should be split on many lines.
Their opening curly brace should be on their own line if the method signature is inlined,
or on the same line as the closing parenthesis if it is multiline.
Activity
gnugat commentedon Oct 6, 2016
Here's a first draft:
%placeholder%or alternatively:placeholderplaceholder?, if it is falsey then replace it with an empty string (and remove the next whitespace?)So for example:
In the above example, we have some whitespace issues:
gnugat commentedon Oct 16, 2016
Second draft without alternative syntax, and optional placeholders use a similar syntax to the required ones:
%placeholder%?optional placeholder?PhpSpec uses templates without optional placeholders, so it should work perfectly:
Pretty Printer should rely on templates that mirror PHP Parser's nodes:
With deeper templates:
But once again optional placeholders are problematic regarding surrounding whitespaces when they shouldn't print anything:
Stmt_Uses, then we expect it to be removed with its two new lines charactersextends, then we expect the previous space to be removedStmt_Constants, then we expect its indentation to be removed as well as its two new lines charactersgnugat commentedon Oct 19, 2016
Third draft adding up a collection placeholder:
+collection placeholder+Collection placeholders should received an array:
So for example the
Stmt_Interfacetemplate would look like:And
Stmt_Constant:If there are no
Stmt_Constant, interface should look like:If there's one constant:
If there's more than one constants: