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
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
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
With this change we update several dependencies to avoid Renovate creating a lot of PRs during onboarding. We also remove yarn workspaces as after further analysis these are not needed.
Certain dependencies such as `@octokit/rest`, `remark` and `@babel/*` have not been updated as they require a decent amount of work to update, and it's best to leave them for a seperate PR.
PR Close#41434
This commit refactors the generated code for class metadata in partial
compilation mode. Instead of emitting class metadata into a top-level
`ɵsetClassMetadata` call guarded by `ngDevMode` flags, the class
metadata is now declared using a top-level `ɵɵngDeclareClassMetadata`
call.
PR Close#41200
This commit marks the `compilationMode` compiler option as stable, such
that libraries can be compiled in partial compilation mode.
In partial compilation mode, the compiler's output changes from fully
compiled AOT definitions to an intermediate form using partial
declarations. This form is suitable to be published to NPM, which now
allows libraries to be compiled and published using the Ivy compiler.
Please be aware that libraries that have been compiled using this mode
can only be used in Angular 12 applications and up; they cannot be used
when Ivy is disabled (i.e. when using View Engine) or in versions of
Angular prior to 12. The `compilationMode` option has no effect if
`enableIvy: false` is used.
Closes#41496
PR Close#41518
Fixes an error that will be thrown if `DebugRenderer2.destroyNode` is called with a node that has already been destroyed. The error happened, because we had a non-null assertion, even though the value can be null.
Note that this fix applies only to ViewEngine, because Ivy doesn't provide the `DebugRenderer2`. I decided to resolve it, because it fix is straightforward and this error has been showing up in our logs for a long time now, making actual errors harder to find.
PR Close#41565
With the work done in #41291, the compiler always tracks the last known
program, so there's no need to track the program in the compiler factory
anymore.
PR Close#41517
This commit adds a base class that contains common logic for all ControlValueAccessors defined in Forms package. This allows to remove duplicated logic from all built-in ControlValueAccessor classes.
PR Close#41225
This commit removes the line to set `currentNavigation` to `null` in the
navigation transitions subscription of the router. This logic is
already handled in the `finalize` stage of the transition pipe and has
been found to cause issues if a new navigation is triggered from a
subscription to the `NavigationEnd` event.
fixes#37460
PR Close#41262
`NgCompiler` previously had a notion of the "next" `ts.Program`, which
served two purposes:
* it allowed a client using the `ts.createProgram` API to query for the
latest program produced by the previous `NgCompiler`, as a starting
point for building the _next_ program that incorporated any new user
changes.
* it allowed the old `NgCompiler` to be queried for the `ts.Program` on
which all prior state is based, which is needed to compute the delta
from the new program to ultimately determine how much of the prior
state can be reused.
This system contained a flaw: it relied on the `NgCompiler` knowing when
the `ts.Program` would be changed. This works fine for changes that
originate in `NgCompiler` APIs, but a client of the `TemplateTypeChecker`
may use that API in ways that create new `ts.Program`s without the
`NgCompiler`'s knowledge. This caused the `NgCompiler`'s concept of the
"next" program to get out of sync, causing incorrectness in future
incremental analysis.
This refactoring cleans up the compiler's `ts.Program` management in
several ways:
* `TypeCheckingProgramStrategy`, the API which controls `ts.Program`
updating, is renamed to the `ProgramDriver` and extracted to a separate
ngtsc package.
* It loses its responsibility of determining component shim filenames. That
functionality now lives exclusively in the template type-checking package.
* The "next" `ts.Program` concept is renamed to the "current" program, as
the "next" name was misleading in several ways.
* `NgCompiler` now wraps the `ProgramDriver` used in the
`TemplateTypeChecker` to know when a new `ts.Program` is created,
regardless of which API drove the creation, which actually fixes the bug.
PR Close#41291
This commit changes the partial compilation so that it outputs declarations
rather than definitions for injectables.
The JIT compiler and the linker are updated to be able to handle these
new declarations.
PR Close#41316
The other similar interfaces were renamed in https://github.com/angular/angular/pull/41119,
but this one was left since it had existed before Ivy. It looks like the interface was
never actually exposed on npm so it is safe to rename this one too.
PR Close#41316
When we deactivate a child route, we deactivate its outlet as well as
its children. We also need to clear the stored information about the
route and the associated component.
If we do not, the context will keep these references and can result in
reactivating an outlet that was deactivated by the previous navigation.
Fixes#41379
PR Close#41381
* We had a usage of `Observable.subscribe` that uses the deprecated signature with 3 arguments. These changes switch to the non-deprecated version that passes in an `Observer`.
* Avoids always creating a `complete` callback since it isn't required.
* We were repeating all of the internal callbacks twice: once for sync and once for async. These changes move them out into variables so that they're more minifier-friendly. The savings aren't huge (~100 bytes minified), but it doesn't add any maintenance effort on our end so I decided to add it.
PR Close#41450
Currently, we throw a FatalDiagnosticError when we fail to load a resource
(`templateUrl` or `styleUrl`) at various stages in the compiler. This prevents
analysis of the component from completing. This will result in in users not being
able to get any information in the component template when there is a missing
`styleUrl`, for example.
This commit simply tracks the diagnostic, marks the component as poisoned, and
continues merrily along. Environments configured to use poisoned data
(like the language service) will then be able to use other information from the analysis.
Fixes https://github.com/angular/vscode-ng-language-service/issues/1241
PR Close#41403
Add new method `historyGo`, that will let
the user navigate to a specific page from session history identified by its
relative position to the current page.
We add some tests to `location_spec.ts` to validate the behavior of the
`historyGo` and `forward` methods.
Add more tests for `location_spec` to test `location.historyGo(0)`, `location.historyGo()`,
`location.historyGo(100)` and `location.historyGo(-100)`. We also add new tests for
`Integration` spec to validate the navigation when we using
`location#historyGo`.
Update the `historyGo` function docs
Note that this was made an optional function in the abstract classes to
avoid a breaking change. Because our location classes use `implements PlatformLocation`
rather than `extends PlatformLocation`, simply adding a default
implementation was not sufficient to make this a non-breaking change.
While we could fix the classes internal to Angular, this would still have been
a breaking change for any external developers who may have followed our
implementations as an example.
PR Close#38890
Currently, fs-extra is used to delete a directory recursively, but this is already available in native Node.JS. Hence, making this dependency redundant.
See: https://nodejs.org/docs/latest-v12.x/api/fs.html
PR Close#41445
This change introduces a new hook on the `ResourceHost` interface named `transformResource`.
Resource transformation allows both external and inline resources to be transformed prior to
compilation by the AOT compiler. This provides support for tooling integrations to enable
features such as preprocessor support for inline styles.
Only style resources are currently supported. However, the infrastructure is in place to add
template support in the future.
PR Close#41307
With this change we add renovate to update dependencies in the following locations
- WORKSPACE
- integration/bazel/WORKSPACE
- package.json
- packages/**/package.json
- tools/ts-api-guardian/package.json
- aio/package.json
We also enable yarn workspaces so that dependencies in these packages are hoisting to the root and renovate doesn't created nested lock files.
Enabling auto updates is important, because quite often dependencies get out of date especially in the compiler-cli which depends on a number of external dependencies.
PR Close#41407
Introduces an **internal**, **experimental** `profiler` function, which
the runtime invokes around user code, including before and after:
- Running the template function of a component
- Executing a lifecycle hook
- Evaluating an output handler
The `profiler` function invokes a callback set with the global
`ng.ɵsetProfiler`. This API is **private** and **experimental** and
could be removed or changed at any time.
This implementation is cheap and available in production. It's cheap
because the `profiler` function is simple, which allows the JiT compiler
to inline it in the callsites. It also doesn't add up much to the
production bundle.
To listen for profiler events:
```ts
ng.ɵsetProfiler((event, ...args) => {
// monitor user code execution
});
```
PR Close#41255
This commit removes a check for the name of the generated factory
function, which is unimportant to test the behaviour of the code.
The name of these functions is generated from the name of the class
being instantiated. In IE11, there is no `function.name` property available
and so there is a shim for it in `third_party/shims_for_IE.js`, which patches
the `Function.property.name` property.
For performance reasons this shim writes the result of the computation
to the prototype of the function. Unfortunately, this means that any class
that extends the patched class will have the same value for `name`.
PR Close#41416
In #41104 the list of used directives was split into two arrays of used
directives and components, but the JIT side was not updated. This commit
fixes the JIT integration by including the list of used components.
Fixes#41318
PR Close#41353
When possible, the @angular/language-service should only provide
information related to Angular. When there is an embedded language, like
inline templates, editor extensions should have the ability to create
virtual documents and forward the requests to the relevant providers for
that language type (see https://github.com/angular/vscode-ng-language-service/pull/1212).
This commit removes all dom schema completions in both inline and
external templates and provides only the Angular syntax for property completions
on elements.
PR Close#41278
The moved `XhrFactory` still needs to be available from `@angular/common/http`
for some libraries that were built prior to 12.0.0, otherwise they cannot be
used in applications built post-12.0.0.
This commit adds back the re-export of `XhrFactory` and deprecates it.
PR Close#41393
Adds perf tracing for the public methods in LanguageService. If the log level is verbose or higher,
trace performance results to the tsServer logger. This logger is implemented on the extension side
in angular/vscode-ng-language-service.
PR Close#41319