Commit Graph

62 Commits

Author SHA1 Message Date
Kristiyan Kostadinov dc6d40e5bc fix(compiler): handle strings inside bindings that contain binding characters (#39826)
Currently the compiler treats something like `{{  '{{a}}' }}` as a nested
binding and throws an error, because it doesn't account for quotes
when it looks for binding characters. These changes add a bit of
logic to skip over text inside quotes when parsing.

Fixes #39601.

PR Close #39826
2020-12-10 11:11:21 -08:00
Trotyl 8d613c1d42 feat(compiler): allow trailing comma in array literal (#22277)
Allows `[1, 2, ]` syntax in angular expressions.

closes #20773

PR Close #22277
2020-12-02 14:57:05 -08:00
Krzysztof Grzybek 94e790d4ee fix(compiler): report better error on interpolation in an expression (#30300)
Compiler results in weird error message when encounters interpolation inside
existing expression context, e.g. *ngIf="name {{ name }}"

PR Close #30300
2020-11-25 10:53:19 -08:00
Pete Bacon Darwin 969ad329de refactor(compiler): tidy up interpolation splitting (#39717)
When parsing for i18n messages, interpolated strings are
split into `Text` and `Placeholder` pieces.  The method that
does this `_visitTextWithInterpolation()` was becoming too
complex. This commit refactors that method along with some
associated functions that it uses.

PR Close #39717
2020-11-20 08:35:56 -08:00
Andrew Scott c33326c538 refactor(compiler-cli): add keySpan to parsed events (#39609)
Though we currently have the knowledge of where the `key` for an
event binding appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
`sourceSpan`. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.

This is essentially identical to the change from #38898, but for event
bindings rather than input bindings.

PR Close #39609
2020-11-12 15:09:17 -08:00
Kristiyan Kostadinov cbc0907bfd fix(compiler): preserve this.$event and this.$any accesses in expressions (#39323)
Currently expressions `$event.foo()` and `this.$event.foo()`, as well as `$any(foo)` and
`this.$any(foo)`, are treated as the same expression by the compiler, because `this` is considered
the same implicit receiver as when the receiver is omitted. This introduces the following issues:

1. Any time something called `$any` is used, it'll be stripped away, leaving only the first parameter.
2. If something called `$event` is used anywhere in a template, it'll be preserved as `$event`,
rather than being rewritten to `ctx.$event`, causing the value to undefined at runtime. This
applies to listener, property and text bindings.

These changes resolve the first issue and part of the second one by preserving anything that
is accessed through `this`, even if it's one of the "special" ones like `$any` or `$event`.
Furthermore, these changes only expose the `$event` global variable inside event listeners,
whereas previously it was available everywhere.

Fixes #30278.

PR Close #39323
2020-10-30 10:49:15 -07:00
ayazhafiz e3365724f2 feat(compiler): recover expression parsing in more malformed pipe cases (#39437)
This commit handles the following cases:
- incomplete pipes in a pipe chain
- incomplete arguments in a pipe chain
- incomplete arguments provided to a pipe
- nested pipes

The idea is to unconditionally recover on the presence of a pipe, which
should be okay because expression parsing can be independently between
pipes.

PR Close #39437
2020-10-29 12:38:40 -07:00
ayazhafiz 3f00c6150b test(compiler): Demonstrate recoverable parsing of unterminated pipes (#39113)
There is no actionable change in this commit other than to pretty-print
EOF tokens. Actual parsing of unterminated pipes is already supported,
this just adds a test for it.

Part of #38596

PR Close #39113
2020-10-22 13:41:51 -07:00
ayazhafiz e44e10bb81 feat(compiler): support recovery of malformed property writes (#39103)
This feature is trivial to support since
89c5255b8c has landed.

PR Close #39103
2020-10-22 13:36:50 -07:00
JoostK 4b06ef75aa refactor(compiler): associate accurate source spans with ICU expressions (#39072)
Prior to this change, expressions within ICUs would have a source span
corresponding with the whole ICU. This commit narrows down the source
spans of these expressions to the exact location in the source file, as
a prerequisite for reporting type check errors within these expressions.

PR Close #39072
2020-10-08 11:55:27 -07:00
ayazhafiz 89c5255b8c refactor(compiler): iteratively parse interpolations (#38977)
This patch refactors the interpolation parser to do so iteratively
rather than using a regex. Doing so prepares us for supporting granular
recovery on poorly-formed interpolations, for example when an
interpolation does not terminate (`{{ 1 + 2`) or is not terminated
properly (`{{ 1 + 2 {{ 2 + 3 }}`).

Part of #38596

PR Close #38977
2020-10-02 15:13:23 -07:00
ayazhafiz 3bbbf39b58 feat(compiler): Recover on malformed keyed reads and keyed writes (#39004)
This patch adds support for recovering well-formed (and near-complete)
ASTs for semantically malformed keyed reads and keyed writes. See the
added tests for details on the types of semantics we can now recover;
in particular, notice that some assumptions are made about the form of
a keyed read/write intended by a user. For example, in the malformed
expression `a[1 + = 2`, we assume that the user meant to write a binary
expression for the key of `a`, and assign that key the value `2`. In
particular, we now parse this as `a[1 + <empty expression>] = 2`. There
are some different interpretations that can be made here, but I think
this is reasonable.

The actual changes in the parser code are fairly minimal (a nice
surprise!); the biggest addition is a `writeContext` that marks whether
the `=` operator can serve as a recovery point after error detection.

Part of #38596

PR Close #39004
2020-10-02 11:37:03 -07:00
Andrew Scott ba3f4c26bb refactor(compiler): make `keySpan` available for `BoundAttributes` (#38898)
Though we currently have the knowledge of where the `key` for an
attribute binding appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
`sourceSpan`. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.

PR Close #38898
2020-09-22 15:04:30 -07:00
Pete Bacon Darwin bf31ef29f6 refactor(compiler): capture interpolation source-spans in expression parser (#38645)
The expression parser will split the expression up at the interpolation markers
into expressions and static strings. This commit also captures the positions of
these strings in the expression to be used in source-mapping later.

PR Close #38645
2020-09-08 13:17:20 -07:00
JoostK 874792dc43 feat(compiler): support unary operators for more accurate type checking (#37918)
Prior to this change, the unary + and - operators would be parsed as `x - 0`
and `0 - x` respectively. The runtime semantics of these expressions are
equivalent, however they may introduce inaccurate template type checking
errors as the literal type is lost, for example:

```ts
@Component({
  template: `<button [disabled]="isAdjacent(-1)"></button>`
})
export class Example {
  isAdjacent(direction: -1 | 1): boolean { return false; }
}
```

would incorrectly report a type-check error:

> error TS2345: Argument of type 'number' is not assignable to parameter
  of type '-1 | 1'.

Additionally, the translated expression for the unary + operator would be
considered as arithmetic expression with an incompatible left-hand side:

> error TS2362: The left-hand side of an arithmetic operation must be of
  type 'any', 'number', 'bigint' or an enum type.

To resolve this issues, the implicit transformation should be avoided.
This commit adds a new unary AST node to represent these expressions,
allowing for more accurate type-checking.

Fixes #20845
Fixes #36178

PR Close #37918
2020-08-21 12:25:53 -07:00
crisbeto 9322b9a060 fix(compiler): check more cases for pipe usage inside host bindings (#37883)
Builds on top of #34655 to support more cases that could be using a pipe inside host bindings (e.g. ternary expressions or function calls).

Fixes #37610.

PR Close #37883
2020-07-10 11:00:20 -07:00
Joey Perrott d1ea1f4c7f build: update license headers to reference Google LLC (#37205)
Update the license headers throughout the repository to reference Google LLC
rather than Google Inc, for the required license headers.

PR Close #37205
2020-05-26 14:26:58 -04:00
Ayaz Hafiz eb34aa551a feat(compiler): add name spans for property reads and method calls (#36826)
ASTs for property read and method calls contain information about
the entire span of the expression, including its receiver. Use cases
like a language service and compile error messages may be more
interested in the span of the direct identifier for which the
expression is constructed (i.e. an accessed property). To support this,
this commit adds a `nameSpan` property on

- `PropertyRead`s
- `SafePropertyRead`s
- `PropertyWrite`s
- `MethodCall`s
- `SafeMethodCall`s

The `nameSpan` property already existed for `BindingPipe`s.

This commit also updates usages of these expressions' `sourceSpan`s in
Ngtsc and the langauge service to use `nameSpan`s where appropriate.

PR Close #36826
2020-05-08 14:42:42 -07:00
Alex Rickabaugh 83a9159063 style(compiler): reformat of codebase with new clang-format version (#36520)
This commit reformats the packages/compiler tree using the new version of
clang-format.

PR Close #36520
2020-04-08 14:51:08 -07:00
ayazhafiz df890d7629 fix(compiler): record correct end of expression (#34690)
This commit fixes a bug with the expression parser wherein the end index
of an expression node was recorded as the start index of the next token,
not the end index of the current token.

Closes #33477
Closes https://github.com/angular/vscode-ng-language-service/issues/433

PR Close #34690
2020-03-20 10:19:02 -07:00
Keen Yee Liau 31bec8ce61 feat(compiler): Propagate source span and value span to Variable AST (#36047)
This commit propagates the `sourceSpan` and `valueSpan` of a `VariableBinding`
in a microsyntax expression to `ParsedVariable`, and subsequently to
View Engine Variable AST and Ivy Variable AST.

Note that this commit does not propagate the `keySpan`, because it involves
significant changes to the template AST.

PR Close #36047
2020-03-16 10:52:57 -07:00
Keen Yee Liau 06779cfe24 feat(compiler): Add sourceSpan and keySpan to TemplateBinding (#35897)
This commit adds fine-grained text spans to TemplateBinding for microsyntax expressions.

1. Source span
   By convention, source span refers to the entire span of the binding,
   including its key and value.
2. Key span
   Span of the binding key, without any whitespace or keywords like `let`

The value span is captured by the value expression AST.

This is part of a series of PRs to fix source span mapping in microsyntax expression.
For more info, see the doc https://docs.google.com/document/d/1mEVF2pSSMSnOloqOPQTYNiAJO0XQxA1H0BZyESASOrE/edit?usp=sharing

PR Close #35897
2020-03-11 14:51:56 -04:00
Keen Yee Liau 81cb54fc15 refactor(compiler): optionalOperator -> consumeOptionalOperator (#35980)
PR Close #35980
2020-03-10 13:27:37 -04:00
Ayaz Hafiz 11f7e275e6 feat(compiler): type TemplateAst values as ASTWithSource (#35892)
TemplateAst values are currently typed as the base class AST, but they
are actually constructed with ASTWithSource. Type them as such, because
ASTWithSource gives more information about the consumed expression AST
to downstream customers (namely, the expression AST source).

Unblocks #35271

PR Close #35892
2020-03-09 12:14:09 -04:00
Keen Yee Liau bef14cf424 refactor(compiler): rename _ParseAST.optionalCharacter TemplateBinding.expression (#35886)
This commit renames
1. _ParseAST.optionalCharacter -> consumeOptionalCharacter
2. TemplateBinding.expression -> value

PR Close #35886
2020-03-06 12:39:49 -05:00
Keen Yee Liau 716d50aa21 refactor(compiler): Break up parseTemplateBindings() for microsyntax (#35812)
This commit is purely a refactoring of the logic in
`parseTemplateBindings` method for parsing the microsyntax expression.
This is done to enable the introduction of `keySpan` and `valueSpan` in
subsequent PR.

For a detailed explanation of this work and the subsequent work items,
please see https://docs.google.com/document/d/1mEVF2pSSMSnOloqOPQTYNiAJO0XQxA1H0BZyESASOrE/edit?usp=sharing

PR Close #35812
2020-03-05 16:04:41 -05:00
Keen Yee Liau 208ef7bd62 refactor(compiler): Remove NullAstVisitor and visitAstChildren (#35619)
This commit removes the `NullAstVisitor` and `visitAstChildren` exported
from `packages/compiler/src/expression_parser/ast.ts` because they
contain duplicate and buggy implementation, and their use cases could be
sufficiently covered by `RecursiveAstVisitor` if the latter implements the
`visit` method. This use case is only needed in the language service.

With this change, any visitor that extends `RecursiveAstVisitor` could
just define their own `visit` function and the parent class will behave
correctly.

A bit of historical context:
In language service, we need a way to tranverse the expression AST in a
selective manner based on where the user's cursor is. This means we need a
"filtering" function to decide which node to visit and which node to not
visit. Instead of refactoring `RecursiveAstVisitor` to support this,
`visitAstChildren` was created. `visitAstChildren` duplicates the
implementation of `RecursiveAstVisitor`, but introduced some bugs along
the way. For example, in `visitKeyedWrite`, it visits
```
obj -> key -> obj
```
instead of
```
obj -> key -> value
```

Moreover, because of the following line
```
visitor.visit && visitor.visit(ast, context) || ast.visit(visitor, context);
```
`visitAstChildren` visits every node *twice*.

PR Close #35619
2020-02-28 07:13:17 -08:00
Andrew Kushnir 39ec188003 fix(ivy): more accurate detection of pipes in host bindings (#34655)
Pipes in host binding expressions are not supported in View Engine and Ivy, but in some more complex cases (like `(value | pipe) === true`) compiler was not reporting errors. This commit extends Ivy logic to detect pipes in host binding expressions and throw in cases bindings are present. View Engine behavior remains the same.

PR Close #34655
2020-01-21 13:22:00 -05:00
ayazhafiz 19944c2424 feat(compiler): record end of expression Token (#33549)
In the past, only the starting index of an expression Token has been
recorded, so a parser could demarkate the span of a token only by the
start locations of two tokens. This may lead to trailing whitespace
being included in the token span:

```html
{{ token1   + token2 }}
   ^^^^^^^^^             recorded span of `token1`
```

It's also not enough for a parser to determine the end of a token by
adding the length of the token value to the token's start location,
because lexed expression values may not exactly reflect the source code.
For example, `"d\\"e"` is lexed as a string token whose value is `d"e`.

Instead, this commit adds a `end` field to expression tokens. `end`
is one past the last index of the token source code. This will enable a
parser to determine the span of a token just by looking at that token.

This is a breaking change because the contructor interface of `Token`
has changed.

Part of #33477.

PR Close #33549
2020-01-06 11:00:15 -08:00
JoostK 8c6468a025 refactor(ivy): use absolute source spans in type checker (#34417)
Previously, the type checker would compute an absolute source span by
combining an expression AST node's `ParseSpan` (relative to the start of
the expression) together with the absolute offset of the expression as
represented in a `ParseSourceSpan`, to arrive at a span relative to the
start of the file. This information is now directly available on an
expression AST node in the `AST.sourceSpan` property, which can be used
instead.

PR Close #34417
2019-12-18 14:44:42 -08:00
Ayaz Hafiz ddc229b69b fix(ivy): record correct absolute source span for ngForOf expressions (#31813)
Expressions in an inline template binding are improperly recorded as
spaning an offset calculated from the start of the template binding
attribute key, whereas they should be calculated from the start of the
attribute value, which contains the actual binding AST.

PR Close #31813
2019-12-16 08:11:48 -08:00
JoostK 014a7137f4 perf(compiler): use a shared interpolation regex (#34332)
The template parser has a certain interpolation config associated with
it and builds a regular expression each time it needs to extract the
interpolations from an input string. Since the interpolation config is
typically the default of `{{` and `}}`, the regular expression doesn't
have to be recreated each time. Therefore, this commit creates only a
single regular expression instance that is used for the default
configuration.

In a large compilation unit with big templates, computing the regular
expression took circa 275ms. This change reduces this to effectively
zero.

PR Close #34332
2019-12-12 14:06:37 -08:00
Keen Yee Liau 10583f951d fix(compiler-cli): Fix typo $implict (#33633)
Should be $implicit instead.

PR Close #33633
2019-11-07 01:54:17 +00:00
Alex Rickabaugh 38758d856a fix(ivy): don't crash on unknown pipe (#33454)
Previously the compiler would crash if a pipe was encountered which did not
match any pipe in the scope of a template.

This commit introduces a new diagnostic error for unknown pipes instead.

PR Close #33454
2019-10-31 23:43:32 +00:00
Ayaz Hafiz b04488d692 feat(compiler): record absolute span of template expressions in parser (#31897)
Currently, the spans of expressions are recorded only relative to the
template node that they reside in, not their source file.

Introduce a `sourceSpan` property on expression ASTs that records the
location of an expression relative to the entire source code file that
it is in. This may allow for reducing duplication of effort in
ngtsc/typecheck/src/diagnostics later on as well.

Child of #31898

PR Close #31897
2019-10-14 20:14:16 +00:00
Miško Hevery 64770571b2 perf: don't create holey arrays (#32155)
Don't use `Array` constructor with the size value (ex. `new Array(5)`) - this will create a `HOLEY_ELEMENTS` array (even if this array is filled in later on!);

https://v8.dev/blog/elements-kinds
https://stackoverflow.com/questions/32054170/how-to-resize-an-array

PR Close #32155
2019-08-21 08:27:43 -07:00
JoostK 489cef6ea2 feat(ivy): include value spans for attributes, variables and references (#30181)
Template AST nodes for (bound) attributes, variables and references will
now retain a reference to the source span of their value, which allows
for more accurate type check diagnostics.

PR Close #30181
2019-07-25 16:36:32 -07:00
Ayaz Hafiz f65db20c6d feat(ivy): record absolute position of template expressions (#31391)
Currently, template expressions and statements have their location
recorded relative to the HTML element they are in, with no handle to
absolute location in a source file except for a line/column location.
However, the line/column location is also not entirely accurate, as it
points an entire semantic expression, and not necessarily the start of
an expression recorded by the expression parser.

To support record of the source code expressions originate from, add a
new `sourceSpan` field to `ASTWithSource` that records the absolute byte
offset of an expression within a source code.

Implement part 2 of [refactoring template parsing for
stability](https://hackmd.io/@X3ECPVy-RCuVfba-pnvIpw/BkDUxaW84/%2FMA1oxh6jRXqSmZBcLfYdyw?type=book).

PR Close #31391
2019-07-22 09:48:35 -07:00
Ayaz Hafiz 6aaca21c27 fix(compiler): give ASTWithSource its own visit method (#31347)
ASTWithSource contains more information that AST and should have its own
visit method, if desired. This implements that.

PR Close #31347
2019-07-08 10:29:07 -07:00
Paul Gschwendtner 70ad91ed8b refactor(compiler): recursive ast expression visitor not passing context (#31085)
Currently the `RecursiveAstVisitor` that is part of the template expression
parser does not _always_ properly pass through the context that can be
specified when visting a given expression. Only a handful of AST types
pass through the context while others are accidentally left out. This causes
unexpected and inconsistent behavior and basically makes the `context`
parameter not usable if the type of template expression is not known.

e.g. the template variable assignment migration currently depends on
the `RecursiveAstVisitor` but sometimes breaks if developers use
things like conditionals in their template variable assignments.

Fixes #31043

PR Close #31085
2019-06-20 11:12:16 -07:00
Alex Rickabaugh 09af7ea4f5 fix(compiler): fix two existing expression transformer issues (#28523)
Testing of Ivy revealed two bugs in the AstMemoryEfficientTransformer
class, a part of existing View Engine compiler infrastructure that's
reused in Ivy. These bugs cause AST expressions not to be transformed
under certain circumstances.

The fix is simple, and tests are added to ensure the specific expression
forms that trigger the issue compile properly under Ivy.

PR Close #28523
2019-02-13 19:13:10 -08:00
Pete Bacon Darwin cffd86260a fix(compiler): ensure that event handlers have the correct source spans (#28055)
When template bindings are being parsed the event handlers
were receiving a source span that included the whole attribute.

Now they get a span that is focussed on the handler itself.

PR Close #28055
2019-02-12 20:58:28 -08:00
Alexey Zuev 2bf0d1a56f fix(ivy): compile pipe in context of ternary operator (#28635)
Previously, it wasn't possible to compile template that contains pipe in context of ternary operator `{{ 1 ? 2 : 0 | myPipe }}` due to the error `Error: Illegal state: Pipes should have been converted into functions. Pipe: async`.

This PR fixes a typo in expression parser so that pipes are correctly converted into functions.

PR Close #28635
2019-02-11 14:52:13 -08:00
Andrew Grekov e6a0c45674 style(compiler): typo fix (#26934)
PR Close #26934
2018-11-05 09:49:22 -08:00
Victor Berchet 46674d5fac test(ivy): add html to ivy ast transformer tests (#23546)
PR Close #23546
2018-05-09 11:49:18 -07:00
Victor Berchet ba47997715 style(compiler): fix lint issues (#23480)
PR Close #23480
2018-04-22 11:49:49 -07:00
Victor Berchet 6761a64522 refactor(compiler): remove a dependency from the IVY AST to the template AST (#23476)
PR Close #23476
2018-04-20 17:23:02 -07:00
Victor Berchet 4662878a1f refactor(compiler): refactor template binding parsing (#23460)
A long time ago Angular used to support both those attribute notations:
- `*attr='binding'`
- `template=`attr: binding`

Because the last notation has been dropped we can refactor the binding parsing.
Source maps will benefit from that as no `attr:` prefix is added artificialy any
more.

PR Close #23460
2018-04-20 16:07:55 -07:00
Veres Lajos 0ebdb3d12f style: typo fix amendments (#22975)
PR Close #22975
2018-03-27 14:51:53 -04:00
Veres Lajos de90314304 style: typos fixed - https://github.com/vlajos/misspell-fixer (#22975)
PR Close #22975
2018-03-27 14:51:53 -04:00