Skip to content

Commit

Permalink
Merge pull request #52 from phug-php/feature/improve-optimizer
Browse files Browse the repository at this point in the history
Allow Optimizer to use the cache registry
  • Loading branch information
kylekatarnls authored Nov 26, 2019
2 parents 1d28ec6 + 04b4e85 commit ede1e9f
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 155 deletions.
6 changes: 5 additions & 1 deletion src/Phug/Compiler/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ install:
- |
if [[ "$STYLECHECK" != "on" ]]; then
mkdir -p tests/Phug && \
vendor/bin/split copy https://github.com/phug-php/phug.git tests/Phug/ --filters=tests/Phug/Compiler,tests/Phug/Node,tests/Phug/AbstractCompilerTest.php,tests/Phug/CompilerModuleTest.php,tests/Phug/CompilerTest.php,tests/Phug/TestCompiler.php;
vendor/bin/split copy https://github.com/phug-php/phug.git tests/Phug/ --filters=tests/Phug/Compiler,tests/Phug/Node,tests/Phug/AbstractCompilerTest.php,tests/Phug/CompilerModuleTest.php,tests/Phug/CompilerTest.php,tests/Phug/TestCompiler.php && \
mkdir -p tests/Phug/Utils && \
vendor/bin/split copy https://github.com/phug-php/phug.git tests/Phug/Utils/ --filters=tests/Phug/Utils/SuffixLocator.php,tests/Phug/Utils/MutedExceptionCompiler.php,tests/Phug/Utils/UnknownNode.php && \
mkdir -p tests/templates && \
vendor/bin/split copy https://github.com/phug-php/phug.git tests/ --filters=tests/templates;
mkdir -p tests/composite-extensions && \
vendor/bin/split copy https://github.com/phug-php/phug.git tests/ --filters=tests/composite-extensions;
fi;
script:
Expand Down
146 changes: 112 additions & 34 deletions src/Phug/Compiler/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,23 +250,6 @@ public function __construct($options = null)
$this->addModules($this->getOption('compiler_modules'));
}

private function initializeFormatter()
{
$formatterClassName = $this->getOption('formatter_class_name');

if (!is_a($formatterClassName, Formatter::class, true)) {
throw new \InvalidArgumentException(
"Passed formatter class $formatterClassName is ".
'not a valid '.Formatter::class
);
}

$debug = $this->getOption('debug');
$this->formatters[$debug] = new $formatterClassName($this->getOptions());

return $this->formatters[$debug];
}

/**
* Reset layout and compilers cache on clone.
*/
Expand All @@ -288,11 +271,25 @@ public function __clone()
$this->reset();
}

/**
* Get parent compiler (compiler of the file that included/extended the current file)
* or null if the file is not compiled via an import.
*
* @return CompilerInterface|null
*/
public function getParentCompiler()
{
return $this->parentCompiler;
}

/**
* Set the parent compiler (should be used to declare an import relation such as
* include/extend).
*
* @param CompilerInterface $compiler
*
* @return $this
*/
public function setParentCompiler(CompilerInterface $compiler)
{
$this->parentCompiler = $compiler;
Expand Down Expand Up @@ -463,23 +460,6 @@ public function setNodeCompiler($className, $handler)
return $this;
}

/**
* Create a new compiler instance by name or return the previous
* instance with the same name.
*
* @param string $compiler name
*
* @return NodeCompilerInterface
*/
private function getNamedCompiler($compiler)
{
if (!isset($this->namedCompilers[$compiler])) {
$this->namedCompilers[$compiler] = new $compiler($this);
}

return $this->namedCompilers[$compiler];
}

/**
* Return list of blocks for a given name.
*
Expand Down Expand Up @@ -640,6 +620,8 @@ public function registerImportPath($path)
}

/**
* The the paths imported (stored in local memory) by a given path.
*
* @param string|null $path
*
* @return array
Expand All @@ -656,6 +638,8 @@ public function getImportPaths($path = null)
}

/**
* The the paths imported (stored in local memory) for the current path.
*
* @return array
*/
public function getCurrentImportPaths()
Expand Down Expand Up @@ -815,23 +799,48 @@ public function compileFileIntoElement($path)
}

/**
* Get the current file path compiling.
*
* @return string
*/
public function getPath()
{
return $this->path ?: $this->getOption('filename');
}

/**
* Get the class the compiler expects for its modules.
*
* @return string
*/
public function getModuleBaseClassName()
{
return CompilerModuleInterface::class;
}

/**
* Check if a filter is in use in the compiler.
*
* @see https://en.phug-lang.com/#filters
*
* @param string $name
*
* @return bool
*/
public function hasFilter($name)
{
return $this->getFilter($name) !== null;
}

/**
* Get a filter by name.
*
* @see https://en.phug-lang.com/#filters
*
* @param string $name
*
* @return callable|mixed|null
*/
public function getFilter($name)
{
$filters = $this->getOption('filters');
Expand All @@ -850,11 +859,30 @@ public function getFilter($name)
return null;
}

/**
* Set a filter for the current compiler.
*
* @see https://en.phug-lang.com/#filters
*
* @param string $name
* @param callable $filter
*
* @return Compiler|CompilerInterface
*/
public function setFilter($name, $filter)
{
return $this->setOption(['filters', $name], $filter);
}

/**
* Remove a filter from the compiler.
*
* @see https://en.phug-lang.com/#filters
*
* @param string $name
*
* @return Compiler|CompilerInterface
*/
public function unsetFilter($name)
{
return $this->unsetOption(['filters', $name]);
Expand Down Expand Up @@ -900,10 +928,60 @@ public function throwException($message, $node = null, $code = 0, $previous = nu
);
}

/**
* Throw an exception if given condition is false.
*
* @param bool $condition condition to validate
* @param string $message message to throw if condition isn't validated
* @param null $node optional node to get code position in error details
* @param int $code optional error code
* @param null $previous optional link to previous exception
*
* @throws CompilerException
*/
public function assert($condition, $message, $node = null, $code = 0, $previous = null)
{
if (!$condition) {
$this->throwException($message, $node, $code, $previous);
} // @codeCoverageIgnore
}

/**
* Create a new compiler instance by name or return the previous
* instance with the same name.
*
* @param string $compiler name
*
* @return NodeCompilerInterface
*/
private function getNamedCompiler($compiler)
{
if (!isset($this->namedCompilers[$compiler])) {
$this->namedCompilers[$compiler] = new $compiler($this);
}

return $this->namedCompilers[$compiler];
}

/**
* Create the instance of formatter.
*
* @return Formatter
*/
private function initializeFormatter()
{
$formatterClassName = $this->getOption('formatter_class_name');

if (!is_a($formatterClassName, Formatter::class, true)) {
throw new \InvalidArgumentException(
"Passed formatter class $formatterClassName is ".
'not a valid '.Formatter::class
);
}

$debug = $this->getOption('debug');
$this->formatters[$debug] = new $formatterClassName($this->getOptions());

return $this->formatters[$debug];
}
}
70 changes: 52 additions & 18 deletions src/Phug/Compiler/Compiler/AbstractNodeCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,29 @@ abstract class AbstractNodeCompiler implements NodeCompilerInterface
*/
private $compiler;

private function compileParserNode(NodeInterface $node, ElementInterface $element = null)
{
return $node instanceof ParserNodeInterface
? $this->getCompiler()->compileNode($node, $element)
: null;
}

public function __construct(CompilerInterface $compiler)
{
$this->compiler = $compiler;
}

protected function getTextChildren(ParserNodeInterface $node)
{
$children = array_filter($node->getChildren(), function (ParserNodeInterface $node) {
return !($node instanceof CommentNode);
});

return implode("\n", array_map(function (TextNode $text) {
return $text->getValue();
}, $children));
}

/**
* Get the master compiler.
*
* @return CompilerInterface
*/
public function getCompiler()
{
return $this->compiler;
}

/**
* Compile each node of a given list and return an array of elements.
*
* @param NodeInterface[] $nodeList
* @param ElementInterface|null $element
*
* @return ElementInterface[]
*/
public function getCompiledNodeList($nodeList, ElementInterface $element = null)
{
return array_values(array_filter(array_map(
Expand All @@ -59,11 +51,26 @@ function (NodeInterface $childNode) use ($element) {
)));
}

/**
* Compile each child of a given node and return an array of elements.
*
* @param NodeInterface $node
* @param ElementInterface|null $element
*
* @return ElementInterface[]
*/
public function getCompiledChildren(NodeInterface $node, ElementInterface $element = null)
{
return $this->getCompiledNodeList($node->getChildren(), $element);
}

/**
* Compile each child of a given node and append each compiled element into the
* given parent element.
*
* @param NodeInterface $node
* @param ElementInterface|null $element
*/
public function compileNodeChildren(NodeInterface $node, ElementInterface $element = null)
{
$children = array_filter($node->getChildren());
Expand All @@ -75,10 +82,37 @@ public function compileNodeChildren(NodeInterface $node, ElementInterface $eleme
});
}

/**
* Create a variable element from a given node with a given name and expression.
*
* @param \Phug\Parser\NodeInterface $node
* @param string $name
* @param \Phug\Formatter\Element\ExpressionElement $value
*
* @return VariableElement
*/
public function createVariable($node, $name, $value)
{
$variable = new CodeElement('$'.$name, $node);

return new VariableElement($variable, $value, $node);
}

protected function getTextChildren(ParserNodeInterface $node)
{
$children = array_filter($node->getChildren(), function (ParserNodeInterface $node) {
return !($node instanceof CommentNode);
});

return implode("\n", array_map(function (TextNode $text) {
return $text->getValue();
}, $children));
}

private function compileParserNode(NodeInterface $node, ElementInterface $element = null)
{
return $node instanceof ParserNodeInterface
? $this->getCompiler()->compileNode($node, $element)
: null;
}
}
3 changes: 3 additions & 0 deletions src/Phug/Compiler/Compiler/NormalizerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* Interface NormalizerInterface.
*
* An interface for paths normalization.
*
* Locators implementing this interface can customize the path normalization on
* resolving file paths.
*/
interface NormalizerInterface
{
Expand Down
4 changes: 3 additions & 1 deletion src/Phug/Compiler/Compiler/WithUpperLocatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
* Interface WithUpperLocatorInterface.
*
* An interface for object than can have an upper locator.
* Used to get the precedence over the file locator, such
* as the cache registry locator.
*/
interface WithUpperLocatorInterface
{
/**
* Set a master locator to use before the internal one.
*
* @param LocatorInterface|null $upperLocator
* @param LocatorInterface|null $upperLocator locator strategy
*/
public function setUpperLocator($upperLocator);
}
Loading

0 comments on commit ede1e9f

Please sign in to comment.