Skip to content
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

πŸ’‘ Node assert❔ #4231

Open
wants to merge 2 commits into
base: 3.x
Choose a base branch
from
Open

Conversation

smnandre
Copy link
Contributor

Acting as a spinoff to #4165 Add tag to declare variable types
(as I don't want to disrupt the main conversation too much πŸ˜…)

The idea is to introduce assertions.

I'm opening this to gather feedback and ideas. I'd like to see if there's something interesting hereβ€”or not. :)

This could enhance static analysis, define contracts in templates, and serve as a validator during includes/rendering.

{% assert name string %}
{% assert size in ['sm', 'md', 'lg'] %}

Open to any feedback :)

@smnandre
Copy link
Contributor Author

Usage / syntax examples

Langage Code example
PHP assert(in_array($size, ['sm', 'md']));
Python assert size in ['sm', 'md']
Java assert java.util.Arrays.asList("sm", "md").contains(size);
C assert(strcmp(size, "sm") == 0 || strcmp(size, "md") == 0);
JavaScript console.assert(["sm", "md"].includes(size));
C++ assert(size == "sm" || size == "md");
Ruby raise 'Assertion failed' unless ['sm', 'md'].include?(size)

(Table made with some gpt - for representational purposes only)

Comment on lines +33 to +44
$compiler->addDebugInfo($this);
// TODO disable in production(?)

$compiler
->write(' if (!')
->subcompile($this->getNode('expr'))
->raw(") {\n")
->indent()
->write("throw new RuntimeError('Failed');\n")
->outdent()
->raw("}\n")
;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using assert() function?
With OPcache configuration, you can literally remove assert() calls from the code... or here you planned to not write anything if production?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an idea too ! I would say a node would be easier to parse / use by node visitors but i may be wrong here πŸ˜…

or here you planned to not write anything if production?

I planned... nothing πŸ™ƒ the "idea" just emerged earlier tonight during the "var/type" discussion

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestion is about the compiled code, not about the Twig API

Actually, to be able to use PHP's assert function which is a no-op at runtime in production mode, it needs to be a Twig tag and not Twig function usable in an expression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘

@drjayvee
Copy link
Contributor

When it comes to asserting variable types, that can be left over to extensions like TwigStan, once types is merged.

I do like the idea of using assert for expressions.

There's currently no way to intentionally throw an Exception of trigger a warning (aside from something silly like {{ [].foo }}).

I'd propose that the assert tag should have an optional message as part of its spec:

{% assert <expression> [message string] %}

@ruudk is working on compiling Twig templates to PHP in such a way that PHPStan can work its magic. If the assert tag gets a similar treatment, with properly typed variables, we can take a huge leap in template quality.

@fabpot
Copy link
Contributor

fabpot commented Aug 26, 2024

@ruudk is working on compiling Twig templates to PHP in such a way that PHPStan can work its magic. If the assert tag gets a similar treatment, with properly typed variables, we can take a huge leap in template quality.

I'm curious to see how that would look like... but also if that's something we can include in the "default" Twig compilation (I suppose this is based on attributes/annotations with no runtime side-effects).

@ruudk
Copy link
Contributor

ruudk commented Aug 26, 2024

You can read more about TwigStan here: #4233

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

6 participants