-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Start implementation of @let syntax #55848
Conversation
Not sure if there's an RFC for this but is there a performance impact to recomputing the value each time? Is there some automatic marshaling as signal that could memo-ize the value and avoid recomputing on subsequent re-renders if the parts of the expression do not change? |
IMO it's better not to support multiple variables at the same line, I see in almost every project lint rules to error it in javascript/typescript files because it's confusing and very unclear so from the begging not supporting it would save everyone's time |
To elaborate on the decision to support multiple variables in a single declaration:
|
I respectfully disagree here, it's not deviating from the JS syntax but following the best practice as per google style guide
and since we still have the exact one, just removing the ugly part of it, it won't be confusing for anyone
still not implementing it will save everyone's time |
We talked through it with the team and decided to drop the comma-separated syntax for now. |
@crisbeto FYI, I've removed the "target" label for now - it was an "rc" and I was not sure if it should be "patch" or "minor" instead. |
I'm setting it to |
Very useful feature! Thank you! |
Updates the lexer to produce tokens for `let` declarations. Currently it' behind a flag while the feature is being worked on.
Adds a new `LetDeclaration` node to the AST that captures the `LetStart`, `LetValue` and `LetEnd` tokens into a single node.
Introduces a new `LetDeclaration` into the Render3 AST, simiarly to the HTML AST, and adds an initial integration into the various visitors.
public name: string, | ||
public value: string, | ||
public sourceSpan: ParseSourceSpan, | ||
readonly nameSpan: ParseSourceSpan, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought: I wonder if we should have this be the "keyspan" to match what we have in other places for the key/value separation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was basing this on attributes that have a "name span" and a "value span".
while (this._cursor.peek() !== chars.$EOF) { | ||
const char = this._cursor.peek(); | ||
|
||
// `@let` declarations terminate with a semicolon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We continue consuming everything in the let declaration until we find a semicolon. I wonder if this is going to be annoying/problematic with the language service while you're actively typing out your variable declaration. The error span is going to reach the end of the file or until the first semicolon is found, right? I wonder if we can/should take some inspiration from some of the other "incomplete X" parsing (ex: 6ae3b68).
Not a blocker for this but probably something to adjust in the future when we're playing with it in the language service.
The way that we parse certain things in the compiler differs from TS/JS in some ways that can be problematic (ie for syntax highlighting - angular/vscode-ng-language-service#1998).
We might consider only continuing the parsing to the next line if the previous ends with a +
(we don't support template strings AFAIK). There are probably other cases that I'm forgetting...
const a = 1
2
3;
TS parses the const as just a = 1
there but does 1+2 with this
const a = 1 +
2
3;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's valid, but it would be tricky to know when to continue parsing versus when to give up. E.g. we'd also have to continue for things like &&
and ||
. That's difficult to do at the moment, because the markup lexer and expression lexer don't know about each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed-for: fw-i18n
Adds a new `LetDeclaration` node to the AST that captures the `LetStart`, `LetValue` and `LetEnd` tokens into a single node. PR Close #55848
Introduces a new `LetDeclaration` into the Render3 AST, simiarly to the HTML AST, and adds an initial integration into the various visitors. PR Close #55848
Updates the lexer to produce tokens for `let` declarations. Currently it' behind a flag while the feature is being worked on. PR Close #55848
Adds a new `LetDeclaration` node to the AST that captures the `LetStart`, `LetValue` and `LetEnd` tokens into a single node. PR Close #55848
Introduces a new `LetDeclaration` into the Render3 AST, simiarly to the HTML AST, and adds an initial integration into the various visitors. PR Close #55848
This PR was merged into the repository by commit 9eef041. |
These changes are the beginning of the new
@let
syntax that will allow Angular developers to declare local variables in templates. The PR includes the necessary changes to the lexer, as well as the HTML and R3 AST nodes integration (see the individual commits). More PRs in the future will integrate the syntax into the various parts of the framework.@let
declarations are defined as:@let
keyword.=
symbol and zero or more whitespaces.;
symbol.Example usage:
Alternative syntaxes
While we were designing the syntax, we had some proposals for alternative syntaxes. This section covers why they weren't chosen over
@let
.@const
instead of@let
Most developers are taught to use
const
overlet
in TypeScript if the value doesn't change, and since@let
can't be re-assigned, it could make sense to mirror the best practice from TypeScript. We've decided not to use@const
because the value isn't actually constant, it is re-computed every time the template function runs.A good mental model for how a
@let
variable works as part of change detection is this:Note how there is one instance of the variable myVar, which is closed over by the update operation. This pseudocode approximates how the variable's value is stored in the
LView
and used during change detection as well as accessed in event listeners.The prohibition against writing to template variables is an extra restriction that Angular enforces, not an intrinsic property of the variable.
Entirely new keyword
We don't want to come up with a completely new keyword (e.g.
@define
), because we want to maintain familiarity with the TypeScript syntax.@var
instead of@let
Using
var
may make sense since the expression value is variable, but usingvar
in JavaScript is considered an anti-pattern and we don't want to adopt the negative terminology in Angular.var also implies different hoisting semantics which we want to avoid.
Block-like syntax
There was a proposal to introduce a syntax similar to blocks for defining variables which would look something like the following:
This syntax isn't suitable, because:
Relates to #15280