Add the implementation of a Template Check that ensures the correct
use of two-way binding syntax. Generates a warning when
'([foo])="bar"' is found instead of '[(foo)]="bar"'.
Refs #42966
PR Close#42984
Export `getSourceCodeForDiagnostic` from `ngtsc/testing` to make it
available for other packages. This will help confirm that the source
code is correct in other tests.
Refs #42966
PR Close#42984
This commit moves the test utils used in the typechecking tests into its
own package. This makes them available to be used in the tests of a
different package.
Refs #42966
PR Close#42984
specific
This commit makes the wrapper function `makeTemplateDiagnostic` take an
ErrorCode as a type for the `ts.Diagnostic`s to be generated.
Refs #42966
PR Close#42984
This commit introduces //packages/compiler-cli/src/ngtsc/typecheck/extended
as a container for a new phase of diagnostics generation. The API provides an
interface for new template checks to implement and generate template diagnostics.
Refs #42966
PR Close#42984
When the user tries to trigger suggestions from an interruption,
the LS should provide the global completions. For example,
`[input]="t¦"`, the `t` can be the `true` or the symbol from
the component context.
PR Close#42923
Previously, the way templates were tokenized meant that we lost information
about the location of interpolations if the template contained encoded HTML
entities. This meant that the mapping back to the source interpolated strings
could be offset incorrectly.
Also, the source-span assigned to an i18n message did not include leading
whitespace. This confused the output source-mappings so that the first text
nodes of the message stopped at the first non-whitespace character.
This commit makes use of the previous refactorings, where more fine grain
information was provided in text tokens, to enable the parser to identify
the location of the interpolations in the original source more accurately.
Fixes#41034
PR Close#42062
The compliance tests can check source-map segments against expectations
encoded into the expectation files. Previously, the encoding of the expected
segment was only delimited by whitespace, but this made it difficult to identify
segments that started or ended with whitespace.
Now these segment expectations are wrapped in double-quotes which makes
it easier to read and understand the expectation files.
PR Close#42062
Add a `makeTemplateDiagnostic` wrapper in the `TemplateTypeChecker`. This requiers less parameters to create template diagnostics, since the `TemplateTypeChecker` can get the templateId and mapping from it's scope with the `ts.ClassDeclartion`. The `TemplateTypeChecker` is often used to determine if a diagnostic should be produced, so it makes sense to have a function in it that helps create them.
Refs #42966
PR Close#42937
The compiler keeps track of how a declaration has been referenced
using absolute module imports and from which path the absolute module
should be resolved from. There was a bug in how the .d.ts metadata
extraction would incorrectly use the .d.ts file itself as resolution
context for symbols that had been imported using a relative module
specifier. This could result in module resolution failures.
For example, when extracting NgModule metadata from
`/node_modules/lib/index.d.ts` that looks like
```
import {LibDirective} from './dir';
@NgModule({
declarations: [LibDirective],
exports: [LibDirective],
})
export class LibModule {}
```
and `/app.module.ts` that contains
```
import {LibModule} from 'lib';
@NgModule({
imports: [LibModule],
})
export class AppModule {}
```
then `AppModule` would have recorded a reference to `LibModule` using
the `'lib'` module specifier. When extracting the NgModule metadata from
the `/node_modules/lib/index.d.ts` file the relative import into `./dir`
should also be assumed to be importable from `'lib'` (according to APF
where symbols need to be exported from a single entry-point)
so the reference to `LibDirective` should have `'lib'` as absolute
module specifier, but it would incorrectly have
`/node_modules/lib/index.d.ts` as resolution context path. The latter is
incorrect as `'lib'` needs to be resolved from `/app.module.ts` and not
from within the library itself.
Fixes#42810
PR Close#42879
In an incremental rebuild, the compiler attempts to reuse as much
analysis data from a prior compilation as possible to avoid doing the
analysis work again. For source files without Angular behavior however,
no analysis data would be recorded such that the source file had to be
reanalyzed each rebuild, even if it has not changed.
This commit avoids the analysis of such source files by registering
these files as not containing any Angular behavior; allowing subsequent
rebuilds to avoid the analysis work.
PR Close#42562
The static interpreter assumed that a foreign function expression would
have to be imported from the absolute module specifier that was used for
the foreign function itself. This assumption does not hold for the
`forwardRef` foreign function resolver, as that extracts the resolved
expression from the function's argument, which is not behind the
absolute module import of the `forwardRef` function.
The prior behavior has worked for the typical usage of `forwardRef`,
when it is contained within the same source file as where the static
evaluation started. In that case, the resulting reference would
incorrectly have an absolute module guess of `@angular/core`, but the
local identifier emit strategy was capable of emitting the reference
without generating an import using the absolute module guess.
In the scenario where the static interpreter would first have to follow
a reference to a different source that contained the `forwardRef` would
the compilation fail. In that case, there is no local identifier
available such that the absolute module emitter would try to locate the
imported symbol from `@angular/core`. which fails as the symbol is not
exported from there.
This commit fixes the issue by checking whether a foreign expression
occurs in the same source file as the call expression. If it does, then
the absolute module specifier that was used to resolve the call
expression is ignored.
Fixes#42865
PR Close#42887
For the compilation of a component, the compiler verifies that the
imports it needs to generate to reference the used directives and pipes
would not create an import cycle in the program. This requires visiting
the transitive import graphs of all directive/pipe usage in search of
the component file. The observation can be made that all directive/pipe
usages can leverage the exploration work in search of the component
file, thereby allowing sub-graphs of the import graph to be only visited
once instead of repeatedly per usage. Additionally, the transitive
imports of a file are no longer collected into a set to reduce memory
pressure.
PR Close#41271
In #41995 the type of `TrackByFunction` was changed such that the
declaration of a `trackBy` function did not cause the item type to be
widened to the `trackBy`'s item type, which may be a supertype of the
iterated type. This has introduced situations where the template type
checker is now reporting errors for cases where a `trackBy` function is
no longer assignable to `TrackByFunction`.
This commit fixes the error by also including the item type `T` in
addition to the constrained type parameter `U`, allowing TypeScript to
infer an appropriate `T`.
Fixes#42609
PR Close#42692
In combination with the TS `noImplicitOverride` compatibility changes,
we also want to follow the best-practice of adding `override` to
members which are implemented as part of abstract classes. This
commit fixes all instances which will be flagged as part of the
custom `no-implicit-override-abstract` TSLint rule.
PR Close#42512
Currently unless a listener inside of an embedded view tries to reference something from the parent view, or if the reference is a local ref, we don't generate the view restoration instructions and we allow for the value to be picked up from the context object in the function parameters. The problem is that the listener is only run during creation mode and the context object may have been swapped out afterwards.
These changes fix the issue by always generating the view restoration instructions for listeners inside templates.
Fixes#42698.
PR Close#42755
In #42492 the template type checker became capable of replicating a
wider range of generic type parameters for use in template type-check
files. Any literal types within a type parameter would however emit
invalid code, as TypeScript was emitting the literals using the text as
extracted from the template type-check file instead of the original
source file where the type node was taken from.
This commit works around the issue by cloning any literal types and
marking them as synthetic, signalling to TypeScript that the literal
text has to be extracted from the node itself instead from the source
file.
This commit also excludes `import()` type nodes from being supported,
as their module specifier may potentially need to be rewritten.
Fixes#42667
PR Close#42761
Updates the Bazel NodeJS rules to v4.0.0-beta.0. This is necessary
so that the Angular components repo can update, and it's generally
good to stay as up-to-date as possible with the Bazel rules as it's
easy to fall behind, and updating early allows us to discover issues
affecting our tooling earlier (where they are easier to address due to
e.g. potential breaking change policy).
PR Close#42760
Source files that contain directives or components that need an inline
type constructor or inline template type-check block would always be
considered as affected in incremental rebuilds. The inline operations
cause the source file to be updated in the TypeScript program that is
created for template type-checking, which becomes the reuse program
in a subsequent incremental rebuild.
In an incremental rebuild, the source files from the new user program
are compared to those from the reuse program. The updated source files
are not the same as the original source file from the user program, so
the incremental engine would mark the file which needed inline
operations as affected. This prevents incremental reuse for these files,
causing sub-optimal rebuild performance.
This commit attaches the original source file for source files that have
been updated with inline operations, such that the incremental engine
is able to compare source files using the original source file.
Fixes#42543
PR Close#42759
DTS bundling, will cause originally namespaced imports become namespace declarations within the same file. Example:
Before bundling
```ts
import * as i1 from './router';
export declare class RouterModule {
constructor(guard: any, router: Router);
static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet...]>;
}
```
After bundling
```
declare namespace i1 {
export {
RouterOutletContract,
RouterOutlet
}
}
export declare class RouterModule {
constructor(guard: any, router: Router);
static ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet...]>;
}
```
And therefore this commit adds support for reflecting types that are defined in such namespace declarations.
Closes#42064
PR Close#42728
When the template type checker try to get a symbol of a template node, it will
not return the directives intended for an element on a microsyntax template,
for example, `<div *ngFor="let user of users;" dir>`, the `dir` will be skipped,
but it's needed in language service.
Fixes https://github.com/angular/vscode-ng-language-service/issues/1420
PR Close#42640
As of ES2021, JavaScript allows using underscores as separators inside numbers, in order to make them more readable (e.g. `1_000_000` vs `1000000`). TypeScript has had support for separators for a while so these changes expand the template parser to handle them as well.
PR Close#42672
The previous default algorithm was `md5`, which is not compliant with FIPS.
The default is now set to `sha256`, which is compliant.
Fixes#42577
PR Close#42582
The hash algorithm for the entry-point manifest was hardcoded to `md5`.
This can now be configured by the `hashAlgorithm` property on the
ngcc.config.js project configuration.
PR Close#42582
The ngcc configuration gets hashed to be used when caching
but it was hardcoded to use the `md5` algorithm, which is
not FIPS compliant.
Now the hash algorithm can be configured in the ngcc.config.js
file at the project level.
PR Close#42582
Adds support for shorthand property declarations inside Angular templates. E.g. doing `{foo, bar}` instead of `{foo: foo, bar: bar}`.
Fixes#10277.
PR Close#42421
Previously, the template type checker would only opt-in to inline type
constructors if it could import all type references from absolute module
specifiers. This limitation was put into place in an abundance of
caution as there was a safe, but less performant, fallback available.
The language service is not capable of using this fallback, which now
means that the limitation of absolute module specifiers limits the
language service's ability to use accurate types for component/directive
classes that have generic type parameters.
This commit loosens the restriction such that type references are now
eligible for emit as long as they are exported.
PR Close#42492
When a component/directive has a generic type parameter, the template
type checker attempts to translate the type parameter such that the
type parameters can be replicated in the type constructor that is
emitted into the typecheck file.
Type parameters with a default clause would incorrectly be emitted into
the typecheck file using the original `ts.TypeNode` for the default
clause, such that `ts.TypeReferenceNode`s within the default clause
would likely be invalid (i.e. referencing a type for which no import is
present in the typecheck file). This did not result in user-facing
type-check errors as errors reported in type constructors are not
translated into template positions Regardless, this commit ensures that
`ts.TypeReferenceNode`s within defaults are properly translated into the
typecheck file.
PR Close#42492
The template type checker is capable of recreating generic type bounds
in a different context, rewriting type references along the way (if
possible). This was previously done using a visitor that only supported
a limited set of types, resulting in the inability to emit all sorts of
types (even if they don't contain type references at all).
The inability to emit generic type bounds was not critical when the type
parameter emitting logic was introduced, as the compiler also has a
fallback strategy of creating inline type constructors. However, this
fallback is not available to the language service, resulting in
inaccurate types when components/directives use a complex generic type.
To mitigate this problem, the specialized visitor has been replaced with
a generalized TypeScript transform, where only type references get
special treatment. This allows for more complex types to be emitted,
such as union and intersection types, object literal types and tuple
types.
PR Close#42492
If an implcit receiver is accessed in a listener inside of an `ng-template`, we generate some extra code in order to ensure that we're assigning to the correct object. The problem is that the logic wasn't covering keyed writes which caused it to write to the wrong object and throw an assertion error at runtime.
These changes expand the logic to cover keyed writes.
Fixes#41267.
PR Close#42603
xi18n is the operation of extracting i18n messages from templates in the
compilation. Previously, only View Engine was able to perform xi18n. This
commit implements xi18n in the Ivy compiler, and a copy of the View Engine
test for Ivy verifies that the results are identical.
PR Close#42485
This commit moves some xi18n-related functions in the View Engine
ng.Program into a new file. This is necessary in order to depend on them
from the Ivy ng.Program while avoiding a cycle.
PR Close#42485
In watch builds, the compiler attempts to reuse as much information from
a prior compilation as possible. To accomplish this, it keeps a
reference to the most recently succeeded `TraitCompiler`, which contains
all analysis data for the program. However, `TraitCompiler` has an
internal reference to an `IncrementalBuild`, which is itself built on
top of its prior state. Consequently, all prior compilations continued
to be referenced, preventing garbage collection from cleaning up these
instances.
This commit changes the `AnalyzedIncrementalState` to no longer retain
a `TraitCompiler` instance, but only the analysis data it contains. This
breaks the retainer path to the prior incremental state, allowing it to
be garbage collected.
PR Close#42537
This is based on a discussion we had a few weeks ago. Currently if a component uses `ViewEncapsulation.ShadowDom` and its selector doesn't meet the requirements for a custom element tag name, a vague error will be thrown at runtime saying something like "Element does not support attachShadowRoot".
These changes add a new diagnostic to the compiler that validates the component selector and gives a better error message during compilation.
PR Close#42245
For quite a while it is an unspoken convention to add a trailing
new-line files within the Angular repository. This was never enforced
automatically, but has been frequently raised in pull requests through
manual review. This commit sets up a lint rule so that this is
"officially" enforced and doesn't require manual review.
PR Close#42478
Updates the compiler-cli compliance goldens. The golden updates are
required due to a regression in TypeScript 4.3 that causes the emitter
to not incorrectly preserve lines when emitting a node list.
This can be reverted once https://github.com/microsoft/TypeScript/pull/44070
is available.
PR Close#42022