Update the supported range of node versions for Angular. Angular now
supports node >=12.14.1 to <16.0.0, dropping support for Node v10.
BREAKING CHANGE: Angular no longer maintains support for node v10
PR Close#41544
Upgrade local development environment for the angular repo to use node 14
dropping node 10 from supported for development within the angular repo.
PR Close#41544
With this commit, the language service will first try to locate a
pre-compiled style file with the same name when a `css` is provided in
the `styleUrls`. This prevents a missing resource diagnostic for when the
compiled file is not available in the language service environment and also
allows "go to definition" to go to that pre-compiled file.
Fixes angular/vscode-ng-language-service#1263
PR Close#41538
The language service uses an elements attributes to determine if it
matches a directive in the component scope. We do this by accumulating
all attribute bindings and matching against the selectors for the
available directives. The compiler itself does a similar thing. In
addition, the compiler does not use the value of `BoundAttribute`s to
match directives (cdf1ea1951/packages/compiler/src/render3/view/util.ts (L174-L206)). This commit changes the language
service to also ignore bound attribute values for directive matching.
Fixes https://github.com/angular/vscode-ng-language-service/issues/1278
PR Close#41597
Updates to the latest version of `rules_nodejs` that supports
the most recent NodeJS lts version v14.16.1.
Additionally the latest version of `rules_nodejs` provides
[a package for runfile resolution](https://github.com/bazelbuild/rules_nodejs/pull/2568) w/ types that we can leverage.
PR Close#41599
This commit introduces the following optimizations:
1. We return an empty array for text nodes in `getDirectives` because
Angular does not support attaching logic to them. This optimization
improves performance of `getDirectives` significantly because text nodes
often result in expensive calls to `loadLContext` since we can't resolve
it from a parent node.
1. `getDirectives` now calls `loadLContext` with second argument `false`
so it doesn't throw an error. This brings another significant
improvement because prevents the VM from deoptimizing calls.
BREAKING CHANGE:
Previously the `ng.getDirectives` function threw an error in case a
given DOM node had no Angular context associated with it (for example
if a function was called for a DOM element outside of an Angular app).
This behavior was inconsistent with other debugging utilities under `ng`
namespace, which handled this situation without raising an exception.
Now calling the `ng.getDirectives` function for such DOM nodes would
result in an empty array returned from that function.
PR Close#41525
This commit introduces a global debugging method
`ng.getDirectiveMetadata` which returns the metadata for a directive or
component instance.
PR Close#41525
This adds string literals, number literals, `true`, `false`, `null` and
`undefined` to autocomplete results in templates.
For example, when completing an input of union type.
Component: `@Input('input') input!: 'a'|'b'|null;`
Template: `[input]="|"`
Provide `'a'`, `'b'`, and `null` as autocompletion entries.
Previously we did not include literal types because we only included
results from the component context (`ctx.`) and the template scope.
PR Close#41456
There were three options being made available to users of the linker:
- ` enableI18nLegacyMessageIdFormat`
- `i18nNormalizeLineEndingsInICUs`
- ` i18nUseExternalIds`
None of these should actually be configurable at linking time
because partially-linked libraries have tighter restrictions on
what i18n options can be used.
This commit removes those options from the `LinkerOptions` interface.
It was considered to add a check for backwards compatibilty to ensure
that if these options were being passed, and were different to the expected
defaults, we would throw an informative error. But from looking at the
Angular CLI (the only known client of the linker) it has never been setting
these options so they have already always been set to the defaults.
BREAKING CHANGE:
Linked libraries no longer generate legacy i18n message ids. Any downstream
application that provides translations for these messages, will need to
migrate their message ids using the `localize-migrate` command line tool.
Closes#40673
PR Close#41554
Replace Codelyzer recommendation with Angular-ESLint in accessibility guide since that tool is deprecated and was removed from the Angular CLI.
Closes#41573
PR Close#41294
This commit has the Language Service take advantage of versioned source
files added in the compiler previously. With this change, the Language
Service's incremental compilations will now be correct even if the TS
Language service mutates `ts.SourceFile`s without changing their object
identity, as we know it does in certain corner cases.
No test is added here as it is difficult to reproduce this behavior in the
LS's artificial testing environment. A test for this case exists in the
LS extension repo, where it will be used to validate that a workaround three
is no longer necessary.
PR Close#41475
Generally, the compiler assumes that `ts.SourceFile`s are immutable objects.
If a new `ts.Program` is compared to an old one, and a `ts.SourceFile`
within that program has not changed its object identity, the compiler will
assume that its prior analysis and understanding of that source file is
still valid.
However, not all TypeScript workflows uphold this assumption. For
`ts.Program`s that originate from the `ts.LanguageService`, some source
files may be re-parsed or otherwise undergo mutations without changing their
object identity. This breaks the compiler's incremental workflow.
Within such environments, it's necessary to track source file changes
differently. In addition to object identity, it's necessary to compare a
"version" string associated with each source file, between when that file is
analyzed originally and when a new program is presented that still contains
it. It's possible for the object identity of the source file to be the same,
but the version string to have changed, indicating that the source file
should be treated as changed.
This commit adds an optional method `getSourceFileVersion` to the
`ProgramDriver`, to provide access to version information if available. When
this method is present, the compiler will build a map of source file version
strings, and use this map to augment identity comparison during incremental
compilation.
PR Close#41475
This commit replaces the `IncrementalDriver` abstraction which powered
incremental compilation in the compiler with a new `IncrementalCompilation`
design. Principally, it separates two concerns which were tied together in
the previous implementation:
1. Tracking the reusable state of a compilation at any given point that
could be reused in a subsequent future compilation.
2. Making use of a prior compilation's state to accelerate the current one.
The new abstraction adds explicit tracking and types to deal with both of
these concerns separately, which greatly reduces the complexity of the state
tracking that `IncrementalDriver` used to perform.
PR Close#41475
The compiler frequently translates TypeScript source file `fileName` strings
into absolute paths, via a `fs.resolve()` operation. This is often done via
the helper function `absoluteFromSourceFile`.
This commit adds a caching mechanism whereby the `AbsoluteFsPath` of a
source file is patched onto the object under an Angular-specific symbol
property, allowing the compiler to avoid resolving the path on subsequent
calls.
PR Close#41475
This commit implements signature help in the Language Service, on top of
TypeScript's implementation within the TCB.
A separate PR adds support for translation of signature help data from TS'
API to the LSP in the Language Service extension.
PR Close#41581
This commit changes `getTemplateAtTarget` to be able to identify when a
cursor position is specifically within the argument span of a `MethodCall`
or `SafeMethodCall` with no arguments. If the call had arguments, one of the
argument expressions would be returned instead, but in a call with no
arguments the tightest node _is_ the `MethodCall`. Adding the additional
argument context will allow for functionality that relies on tracking
argument positions, like `getSignatureHelpItems`.
PR Close#41581
`EmptyExpr` is somewhat unique, in that it's constructed in a circumstance
where the parser has been looking for a particular token or string of tokens
and has failed to find any. This means the parser state when constructing
`EmptyExpr` is fairly unique.
This gives rise to a bug where the parser constructs `EmptyExpr` with a
backwards span - a `start` value that's beyond the `end` value. This likely
happens because of the strange state the parser is in when recovering with
`EmptyExpr`.
This commit adds a backstop/workaround to avoid constructing such broken
`EmptyExpr` spans (or any other kind of span). Eventually, the parser state
should be fixed such that this does not occur, but that requires a
significant change to the parser's functionality, so a simple fix in th
interim is in order.
PR Close#41581
This commit adds a separate span to `MethodCall` and `SafeMethodCall` which
tracks the text span between the `(` and `)` tokens of the call. Tools like
the Language Service can use this span to more accurately understand a
cursor position within a method call expression.
PR Close#41581
Previously if there was a problem when building the tests, the error would
be swallowed as an unhandled promise rejection. Now these are caught and
the process is exited with a non-zero value to prevent any CI jobs from
passing incorrectly.
PR Close#41596
This is to fix the below error:
```
tools/firebase-test-utils/FirebaseRedirect.ts:17:50 - error TS2345: Argument of type '(string | RegExp)[][]' is not assignable to parameter of type 'ReplacementDetail[]'.
Type '(string | RegExp)[]' is missing the following properties from type 'ReplacementDetail': 0, 1
17 return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]);
```
https://app.circleci.com/pipelines/github/angular/angular/31076/workflows/5fd3851e-ae9e-4d77-b0ef-366ba38a9088/jobs/961795
PR Close#41596
When an Ivy NgModule is imported into a View Engine build, it doesn't have
metadata.json files that describe it as an NgModule, so it appears to VE
builds as a plain, undecorated class. The error message shown in this
situation generic and confusing, since it recommends adding an @NgModule
annotation to a class from a library.
This commit adds special detection into the View Engine compiler to give a
more specific error message when an Ivy NgModule is imported.
PR Close#41534
Fix unexpected error when following the tutorial (when going through it with stricter type checking enforced). While (+) converts a string to an integer, it does not account for the possibility that `this.route.snapshot.paramMap.get('id')` could return null (type: string | null). Since this null case is not a practical outcome, it is a matter of types; switching from (+) to the `Number` function eliminates this issue, making the tutorial more robust.
PR Close#41570
In the compiler, the `NgtscProgram` is responsible for creating the
`ts.Program` instance to use, potentially using a `ts.Program` from a
prior compilation to enable incremental compilation. It used to track
a `reuseTsProgram` for this purpose, however the `ts.Program` that
should be used as reuse program is also tracked by the `NgCompiler`
instance that is used by `NgtscProgram`. The `NgtscProgram` can leverage
the state from `NgCompiler` instead of keeping track of it by itself.
PR Close#41289
When multiple occurrences of the same package exist within a single
TypeScript compilation unit, TypeScript deduplicates the source files
by introducing redirected source file proxies. Such proxies are
recreated during an incremental compilation even if the original
declaration file did not change, which caused the compiler not to reuse
any work from the prior compilation.
This commit changes the incremental driver to recognize a redirected
source file and treat them as their unredirected source file.
PR Close#41448
In environments such as the Language Service where inline type-checking code
is not supported, the compiler would previously produce a diagnostic when a
template would require inlining to check. This happened whenever its
component class had generic parameters with bounds that could not be safely
reproduced in an external TCB. However, this created a bad user experience
for the Language Service, as its features would then not function with such
templates.
Instead, this commit changes the compiler to use the same strategy for
inline TCBs as it does for inline type constructors - falling back to `any`
for generic types when inlining isn't available. This allows the LS to
support such templates with slightly weaker type-checking semantics, which
a test verifies. There is still a case where components that aren't
exported require an inline TCB, and the compiler will still generate a
diagnostic if so.
Fixes#41395
PR Close#41513
Previously, the `DefaultImportRecorder` interface was used as follows:
1. During the analysis phase, the default import declaration of an
identifier was recorded.
2. During the emit phase each emitted identifier would be recorded.
The information from step 1 would then be used to determine the
default import declaration of the identifier which would be
registered as used.
3. A TypeScript transform would taint all default imports that were
registered as used in step 2 such that the imports are not elided
by TypeScript.
In incremental compilations, a file may have to be emitted even if its
analysis data has been reused from the prior compilation. This would
mean that step 1 is not executed, resulting in a mismatch in step 2 and
ultimately in incorrectly eliding the default. This was mitigated by
storing the mapping from identifier to import declaration on the
`ts.SourceFile` instead of a member of `DefaultImportTracker` such that
it would also be visible to the `DefaultImportRecorder` of subsequent
compiles even if step 1 had not been executed.
Ultimately however, the information that is being recorded into the
`DefaultImportRecorder` has a longer lifetime than a single
`DefaultImportRecorder` instance, as that is only valid during a single
compilation whereas the identifier to import declaration mapping
outlives a single compilation. This commit replaces the registration of
this mapping by attaching the default import declaration on the output
AST node that captures the identifier. This enables the removal of
all of the `DefaultImportRecorder` usages throughout the analysis phase
together with the `DefaultImportRecorder` interface itself.
PR Close#41557
The Angular compiler has to actively keep default import statements
alive if they were only used in type-only positions, but have been
emitted as value expressions for DI purposes. A problem occurred in
incremental recompilations, where the relationship between an identifier
usage and its corresponding default import would not be considered. This
could result in the removal of the default import statement and caused
a `ReferenceError` at runtime.
This commit fixes the issue by storing the association from an
identifier to its default import declaration on the source file itself,
instead of within the `DefaultImportTracker` instance. The
`DefaultImportTracker` instance is only valid for a single compilation,
whereas the association from an identifier to a default import
declaration is valid as long as the `ts.SourceFile` is the same
instance.
A subsequent commit refactor the `DefaultImportTracker` to no longer
be responsible for registering the association, as its lifetime is
conceptually too short to do so.
Fixes#41377
PR Close#41557
The `emitDecoratorMetadata` compiler option does not have to be enabled
as Angular decorators are transformed by the AOT compiler. Having the
option enabled in our tests can hide issues around import preservation,
as with `emitDecoratorMetadata` enabled the TypeScript compiler itself
does not elide imports even if they are only used in type-positions.
This is unlike having `emitDecoratorMetadata` disabled, however; in that
case the Angular compiler has to actively trick TypeScript into
retaining default imports when an identifier in a type-only position has
been reified into a value position for DI purposes.
A subsequent commit addresses a bug in default import preservation
that relies on this flag being `false`.
PR Close#41557