This commit adds attribute completion to the Language Service. It completes
from 3 sources:
1. inputs/outputs of directives currently present on the element
2. inputs/outputs/attributes of directives in scope for the element, that
would become present if the input/output/attribute was added
3. DOM properties and attributes
We distinguish between completion of a property binding (`[foo|]`) and a
completion in an attribute context (`foo|`). For the latter, bindings to
the attribute are offered, as well as a property binding which adds the
square bracket notation.
To determine hypothetical matches (directives which would become present if
a binding is added), directives in scope are scanned and matched against a
hypothetical version of the element which has the attribute.
PR Close#40032
This commit expands the autocompletion capabilities of the language service
to include element tag names. It presents both DOM elements from the Angular
DOM schema as well as any components (or directives with element selectors)
that are in scope within the template as options for completion.
PR Close#40032
This commit extends the template targeting system, which determines the node
being referenced given a template position, to return additional context if
needed about the particular aspect of the node to which the position refers.
For example, a position pointing to an element node may be pointing either
to its tag name or to somewhere in the node body. This is the difference
between `<div|>` and `<div foo | bar>`.
PR Close#40032
Projects opened in the LS are often larger in scope than the compilation
units seen by the compiler when actually building. For example, in the LS
it's not uncommon for the project to include both application as well as
test files. This can create issues when the combination of files results
in errors that are not otherwise present - for example, if test files
have inline NgModules that re-declare components (a common Angular pattern).
Such code is valid when compiling the app only (test files are excluded, so
only one declaration is seen by the compiler) or when compiling tests only
(since tests run in JIT mode and are not seen by the AOT compiler), but when
both sets of files are mixed into a single compilation unit, the compiler
sees the double declaration as an error.
This commit attempts to mitigate the problem by forcing the compiler flag
`compileNonExportedClasses` to `false` in a LS context. When tests contain
duplicate declarations, often such declarations are inline in specs and not
exported from the top level, so this flag can be used to greatly improve the
IDE experience.
PR Close#40092
This commit adds support in the Ivy Language Service for autocompletion in a
global context - e.g. a {{foo|}} completion.
Support is added both for the primary function `getCompletionsAtPosition` as
well as the detail functions `getCompletionEntryDetails` and
`getCompletionEntrySymbol`. These latter operations are not used yet as an
upstream change to the extension is required to advertise and support this
capability.
PR Close#39250
This commit adds "find references" functionality to the Ivy integrated
language service. The basic approach is as follows:
1. Generate shims for all files to ensure we find references in shims
throughout the entire program
2. Determine if the position for the reference request is within a
template.
* Yes, it is in a template: Find which node in the template AST the
position refers to. Then find the position in the shim file for that
template node. Pass the shim file and position in the shim file along
to step 3.
* No, the request for references was made outside a template: Forward
the file and position to step 3.
3. (`getReferencesAtTypescriptPosition`): Call the native TypeScript LS
`getReferencesAtPosition`. For each reference that is in a shim file, map those
back to a template location, otherwise return it as-is.
PR Close#39768
Currently `readConfiguration` relies on the file system to perform disk
utilities needed to read determine a project configuration file and read
it. This poses a challenge for the language service, which would like to
use `readConfiguration` to watch and read configurations dependent on
extended tsconfigs (#39134). Challenges are at least twofold:
1. To test this, the langauge service would need to provide to the
compiler a mock file system.
2. The language service uses file system utilities primarily through
TypeScript's `Project` abstraction. In general this should correspond
to the underlying file system, but it may differ and it is better to
go through one channel when possible.
This patch alleviates the concern by directly providing to the compiler
a "ParseConfigurationHost" with read-only "file system"-like utilties.
For the language service, this host is derived from the project owned by
the language service.
For more discussion see
https://docs.google.com/document/d/1TrbT-m7bqyYZICmZYHjnJ7NG9Vzt5Rd967h43Qx8jw0/edit?usp=sharing
PR Close#39619
This commit adds new language service testing infrastructure which allows
for in-memory testing. It solves a number of issues with the previous
testing infrastructure that relied on a single integration project across
all of the tests, and also provides for much faster builds by using
the compiler-cli's mock versions of @angular/core and @angular/common.
A new `LanguageServiceTestEnvironment` class (conceptually mirroring the
compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests.
The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`,
which backs the language service infrastructure.
Since many language service tests revolve around the template, the API is
currently optimized to spin up a "skeleton" project and then override its
template for each test.
The existing Quick Info tests (quick_info_spec.ts) were ported to the new
infrastructure for validation. The tests were cleaned up a bit to remove
unnecessary initializations as well as correct legitimate template errors
which did not affect the test outcome, but caused additional validation of
test correctness to fail. They still utilize a shared project with all
fields required for each individual unit test, which is an anti-pattern, but
new tests can now easily be written independently without relying on the
shared project, which was extremely difficult previously. Future cleanup
work might refactor these tests to be more independent.
PR Close#39594
Rather than re-reading component metadata that was already interpreted
by the Ivy compiler, the Language Service should instead use the
compiler APIs to get information it needs about the metadata.
PR Close#39476
This commit takes the `HybridVisitor` in the language service and gives it
the ability to return not just a node but the template context in which it
appears. In the future, more context regarding where a node appears in the
template might become necessary (ex: the microsyntax container for binding
nodes), and this refactoring enables that.
In the process, `HybridVisitor` is renamed and the concept of a
`TemplateTarget` interface is introduced to contain the results of this
operation.
PR Close#39505
This commit enables the Ivy Language Service to 'go to definition' of a
templateUrl or styleUrl, which would jump to the template/style file
itself.
PR Close#39202
This commit fixes a bug in which a new Ivy Compiler is created every time
language service receives a new request. This is not needed if the
`ts.Program` has not changed.
A new class `CompilerFactory` is created to manage Compiler lifecycle and
keep track of template changes so that it knows when to override them.
With this change, we no longer need the method `getModifiedResourceFile()`
on the adapter. Instead, we call `overrideComponentTemplate` on the
template type checker.
This commit also changes the incremental build strategy from
`PatchedIncrementalBuildStrategy` to `TrackedIncrementalBuildStrategy`.
PR Close#39231
This PR enables `getSemanticDiagnostics()` to be called on external templates.
Several changes are needed to land this feature:
1. The adapter needs to implement two additional methods:
a. `readResource()`
Load the template from snapshot instead of reading from disk
b. `getModifiedResourceFiles()`
Inform the compiler that external templates have changed so that the
loader could invalidate its internal cache.
2. Create `ScriptInfo` for external templates in MockHost.
Prior to this, MockHost only track changes in TypeScript files. Now it
needs to create `ScriptInfo` for external templates as well.
For (1), in order to make sure we don't reload the template if it hasn't
changed, we need to keep track of its version. Since the complexity has
increased, the adapter is refactored into its own class.
PR Close#39065
The statements generated in the TCB are optimized for performance and producing diagnostics.
These optimizations can result in generating a TCB that does not have all the information
needed by the `TemplateTypeChecker` for retrieving `Symbol`s. For example, as an optimization,
the TCB will not generate variable declaration statements for directives that have no
references, inputs, or outputs. However, the `TemplateTypeChecker` always needs these
statements to be present in order to provide `ts.Symbol`s and `ts.Type`s for the directives.
This commit adds logic to the TCB generation to ensure the required
information is available in a form that the `TemplateTypeChecker` can
consume. It also adds an option to the `NgCompiler` that makes this
generation configurable.
PR Close#38618
Now that Ivy compiler has a proper `TemplateTypeChecker` interface
(see https://github.com/angular/angular/pull/38105) we no longer need to
keep the temporary compiler implementation.
The temporary compiler was created to enable testing infrastructure to
be developed for the Ivy language service.
This commit removes the whole `ivy/compiler` directory and moves two
functions `createTypeCheckingProgramStrategy` and
`getOrCreateTypeCheckScriptInfo` to the `LanguageService` class.
Also re-enable the Ivy LS test since it's no longer blocking development.
PR Close#38310
This commit removes compiler instantiation at startup.
This is because the constructor is invoked during the plugin loading phase,
in which the project has not been completely loaded.
Retrieving `ts.Program` at startup will trigger an `updateGraph` operation,
which could only be called after the Project has loaded completely.
Without this change, the Ivy LS cannot be loaded as a tsserver plugin.
Note that the whole `Compiler` class is temporary, so changes made there are
only for development. Once we have proper integration with ngtsc the
`Compiler` class would be removed.
PR Close#38120
This commit adds a Compiler interface that wraps the actual ngtsc
compiler. The language-service specific compiler manages multiple
typecheck files using the Project interface, creating and adding
ScriptInfos as necessary.
This commit also adds `overrideInlineTemplate()` method to the mock
service so that we could test the Compiler diagnostics feature.
PR Close#36930
Parse Angular compiler options in Angular language service.
In View Engine, only TypeScript compiler options are read, Angular
compiler options are not. With Ivy, there could be different modes of
compilation, most notably how strict the templates should be checked.
This commit makes the behavior of language service consistent with the
Ivy compiler.
PR Close#36922
This commit adds a new entry point for the Ivy version of language
service. The entry point is just a shell for now, implementation will be
added in subsequent PRs.
The Ivy version of language service could be loaded from the NPM package
via `require(@angular/language-service/bundles/ivy.umd.js)`
PR Close#36864