Commit graph

2291 commits

Author SHA1 Message Date
Andrew Scott
30c950f133 refactor(compiler-cli): Fix regressions caused by ts.typechecker removal
removing ts.typechecker in a prior refactor caused some regressions, particularly when multiple directives
appear on a single elemnt. this is now addressed by using an id for directives and storing that in the tcb comment
2026-04-08 08:14:44 -07:00
Kristiyan Kostadinov
ab061a7610 fix(compiler-cli): error for type parameter declarations
Fixes an error that was heppning when a generic param has type parameters of its own. There were a few different issues going on:
1. In #67707 I had changed a bit how we pass the `genericContextBehavior` which ended up ignoring the `useContextGenericType` option from the environment.
2. All directives depend on themselves, but we were overridding the `genericContextBehavior` for the directive being processed.
3. The type translator wasn't handling type parameter declarations. Technically we shouldn't be able to hit a code path that has a type parameter, however it's also easy enough to handle so we might as well.

Relates to #67704.
2026-04-07 09:29:29 -07:00
Andrew Scott
9218140348 fix(compiler-cli): resolve TCB mapping failure for safe property reads with as any
- Fixes TemplateSymbolBuilder.getTcbPositionForNode to recursively unwrap AsExpression and NonNullExpression nodes.
- Added a test case in type_checker__get_symbol_of_template_node_spec.ts to verify symbol mapping when strictSafeNavigationTypes is false.
- Note: The issue likely broke in commit 13c8df67d9.
2026-04-06 13:16:19 -07:00
Matthieu Riegler
f3c471e0d5 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-04-06 11:55:09 -07:00
Andrew Scott
13c8df67d9 refactor(compiler-cli): decouple TemplateSymbolBuilder from ts.TypeChecker
This updates the SymbolBuilder to no longer use ts.TypeChecker internally to
build symbols for the language service. These lookups are deferred/done later
using the newly expanded template type checker API.
2026-04-06 10:55:40 -07:00
Andrew Scott
5600c4fbd9 refactor(compiler-cli): tag host directives in TCB
Add HOST_DIRECTIVE expression identifier to TCB comments to identify host directives.
2026-04-06 10:55:40 -07:00
Kristiyan Kostadinov
57432f1b6a refactor(compiler-cli): merge duplicate directive matches and report conflicts
Implements the logic at the compiler level that will de-duplicate host directives and merge them together. It will also report if a conflict is detected during merging.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
22f9ee1be6 refactor(compiler): require a reference in DirectiveMeta
Requires the `DirectiveMeta` to have a `ref` so that we can find duplicates easily.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
d15ceff617 refactor(compiler-cli): move ClassPropertyMapping into compiler
Moves the `ClassPropertyMapping` into the compiler, rather than having to pass around the limited `InputOutputPropertySet` interface that is only implemented by `ClassPropertyMapping`.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
927ae3abc8 refactor(compiler): move matchSource into base metadata
Moves the `matchSource` into the base metadata so the binder can use it.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
4651b93a92 refactor(compiler-cli): pre-compute key
Updates the TCB metadata to pre-compute and store the `TcbReferenceKey`, instead of computing it on the fly.
2026-04-03 09:44:39 -07:00
Kristiyan Kostadinov
8fe025f514 feat(core): drop support for TypeScript 5.9
Drops support for TypeScript 5.9.

BREAKING CHANGE:
* TypeScript versions older than 6.0 are no longer supported.
2026-04-03 09:44:11 -07:00
SkyZeroZx
7f9450219f feat(compiler-cli): Adds warning for prefetch without main defer trigger
Emit a warning when an `@defer` block uses `prefetch` triggers but does not define an explicit main trigger.

Closes #52746
2026-04-02 12:21:09 -07:00
SkyZeroZx
b19fda0b15 refactor(compiler-cli): Add diagnostics for idle prefetch triggers
Extends the extended diagnostic for `@defer` trigger misconfiguration to include `on idle` triggers
2026-04-02 12:21:09 -07:00
Andrew Scott
75ac120493 fix(language-service): get quick info at local var location to align with TS semantics and support type narrowing
Previously, the Language Service fetched Quick Info and definitions for template variables (such as `@let` declarations) using mapping to their `initializerLocation` (the right-hand side expression). This aggressively bubbled the type, JSDoc, and definition identity of the initializer backwards onto the variable itself.

This approach had two flaws:
1. It broke type narrowing because the LS read the original un-narrowed type from the source expression rather than the type of the narrowed intermediate variable in the Type Check Block.
2. It deviated from native TypeScript semantics, where a local `let` binding (`let address = hero.address`) does not inherit the docstrings or `(property)` kind of its initializer, acting solely as a local inferred variable.

By using `localVarLocation` rather than `initializerLocation` for LetDeclaration Quick Info and Type Definitions, these intermediate variables now properly preserve type narrowing within templates and flawlessly match the standard behavior expected of TypeScript block variables. `VariableSymbol.initializerLocation` is retained solely to map the value spans of structural directive contexts (e.g., `exportAs` strings).

fixes #65491
2026-04-01 12:22:07 -07:00
Andrei Chmelev
fcd0bb0db8 fix(compiler-cli): prevent recursive scope checks for invalid NgModule imports
Avoid recursive local scope lookups when invalid NgModule imports create import cycles.
2026-03-27 16:10:01 +01:00
Kristiyan Kostadinov
d1c1bc3200 refactor(compiler-cli): decouple schema checker from typescript
Makes the `DomSchemaChecker` from TypeScript APIs.
2026-03-27 15:58:12 +01:00
Kristiyan Kostadinov
3382e8a34b refactor(compiler-cli): generalize out of band diagnostics recorder
Currently the `OutOfBandDiagnosticRecorder` is tied to producing TypeScript diagnostics, however some of our use cases might call for a different form.

These changes decouple the recorder from TypeScript and make the diagnostic type generic.
2026-03-25 12:59:11 -07:00
Matthieu Riegler
8bc31a515f feat(core): Allow other expression for exhaustive typechecking
When the switched expression is nested within a union, exhaustive typechecking needs to know which expression to check.
This change adds the possibility of specifying the expression to check:

```
@Component({
  selector: 'app-root',
  imports: [],
  template: `
    @switch (state.mode) {
      @case ('show') { {{ state.menu }}; }
      @case ('hide') {}
      @default never(state);
    }
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
  state!: { mode: 'hide' } | { mode: 'show'; menu: number };;
}
```

fixes #67406
2026-03-24 14:42:28 -07:00
Matthieu Riegler
f46e8bd440 refactor(compiler): remove fullTemplateTypeCheck compiler option.
The option was deprecated back in v13. Users should use `strictTemplates: true`.
2026-03-23 11:33:15 -07:00
Kristiyan Kostadinov
63ac1bd2fd refactor(compiler-cli): decouple host element creation logic from TypeScript
Reworks the logic for constructing a `HostElement` node so that we can reuse it without depending on TypeScript APIs.
2026-03-23 11:16:39 -07:00
SkyZeroZx
ca67828ee2 refactor(compiler-cli): introduce NG8023 compile-time diagnostic for duplicate selectors
Add NG8023 extended diagnostic to report duplicate component selectors
during compilation.

This replaces the former NG0300 runtime error, ensuring the failure
occurs at build time instead of runtime.

Closes  angular#48377

BREAKING CHANGE: Elements with multiple matching selectors will now throw at compile time.
2026-03-19 16:12:02 -07:00
Alex Rickabaugh
41b1410cb8 feat(forms): support binding number|null to <input type="text">
`<input type="number">` often does not provide the desired user experience when editing numbers in
a form. MDN even [describes](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number#using_number_inputs)
how text inputs should be used in many cases instead, via `<input type="text" inputmode="numeric">`
or similar configurations. Previously, this did not work with Signal Forms without a custom input
component/directive.

This PR builds support for binding `number|null` models directly to `<input type="text">` native
controls via `[formField]`. When a model has a number or `null` value, signal forms will preserve
that status when the user makes edits/changes. Empty string values are converted to `null`, other
values are parsed as numbers, and a parse error is raised when a non-numeric value is entered.

Note that it's up to the UI developer to configure additional UI affordances such as setting an
appropriate `inputmode`, rejecting non-numeric keypresses, etc.

Fixes #66903
Fixes #66157
2026-03-19 15:26:34 -07:00
Kristiyan Kostadinov
9769560da7 fix(compiler-cli): generic types not filled out correctly in type check block
Fixes a regression caused by the recent TCB changes where we moved the type parameter processing earlier in the pipeline and stopped properly accounting for the `TcbGenericContextBehavior`.

Fixes #67704.
2026-03-17 13:21:27 -06:00
Andrew Scott
470cf430ce test(language-service): optimize language service test environment and flatten test setup
Optimization Goals:
The primary goals of this optimization are to dramatically reduce the execution time of the language-service test suite and stabilize the mock file system infrastructure. Previously, the suite suffered from significant overhead due to recreating the `MockFileSystem`, `MockServerHost`, and TypeScript `ProjectService` for every single test block, leading to redundant parsing operations, slow test initialization, and reduced spec performance.

How the Goals Were Achieved:
1. **Mock File System Optimizations (Shared State)**:
   - Evaluated that standard test files (e.g., TS/Angular lib definitions) are immutable across tests.
   - Introduced and utilized `lockMockFileSystem()` to initialize the mock `FileSystem` with `loadStandardTestFiles()` only once per test suite run rather than repeatedly per test.
   - Refactored `LanguageServiceTestEnv.setup()` to reuse the singleton file system, completely skipping redundant module loading by eagerly flagging `fsInitialized = true`.

2. **Language Service Test Environment Enhancements (TypeScript Project Reuse)**:
   - Implemented partial configuration reloads in the `Project` class via the `update()` method, removing the need to tear down and rebuild the entire `MockServerHost` and TypeScript `ProjectService` from scratch when minimal file changes (like HTML templates or local TS edits) are made dynamically by a test.
   - Applied `projectService.reloadProjects()` and `scriptInfo.reloadFromFile()` to synchronously push mock file tree invalidations to the active TS program, skipping expensive environment initialization and saving considerable latency across tests.
   - Added `projectName` identifiers inside complex isolate tests (e.g. module alias aliasing) so custom environment injections can sandbox safely without invalidating the global default environment cache.

3. **Test Suite Unification**:
   - Flattened fragmented test groups (`grp1`, `grp3`, `grp4`) into a cohesive single directory at `packages/language-service/test/`. This simplifies execution config, improves test runner concurrency, and unifies local development targeting.
   - Cleaned out broken inline debug logging and unneeded config reloading loops.

4. **Maintaining Test Isolation**:
   - **Explicit TypeScript Configuration**: While the underlying `MockFileSystem` ("disk") is aggressively reused across tests, the TypeScript `ProjectService` and its execution environment are entirely recreated for every test run to ensure isolated ASTs and module resolution caches.
   - **Strict tsconfig.json Files Array**: When a project is initialized, it explicitly defines its boundary using the strict `files: [ ... ]` array in `tsconfig.json`. This ensures that any leftover files physically on the mock disk from an older test run are completely invisible to the TS Compiler.
   - **Namespace Sandboxing**: For tests doing custom modifications (e.g., overriding module resolution paths), they utilize localized `projectName` arguments (like `"test_alias_completions"`) to configure sandboxed working directories.
2026-03-16 14:49:34 -06:00
Kristiyan Kostadinov
2bd708fb6b fix(compiler-cli): escape template literal in TCB
Fixes a regression introduced by #67381 where we weren't escaping backticks in template literals.

Fixes #67675.
2026-03-16 10:47:25 -06:00
Kristiyan Kostadinov
4636218395 refactor(compiler-cli): avoid typescript errors from debugName transform
In some cases the `debugName` transform generates a spread into the signal function parameters. This can cause compiler errors, because the functions don't have rest parameters.

These changes work around it by adding a `@ts-ignore` above it.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov
4b80227efa refactor(compiler): allow leading comments on expressions
Updates the output AST to allow leading comments to be attached to expression nodes.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov
7a0d6b8df2 fix(compiler-cli): transform dropping exclamationToken from properties
Fixes that the Ivy transform was dropping the `exclamationToken` from properties.
2026-03-16 09:58:18 -06:00
Kristiyan Kostadinov
ed9750d6d7 refactor(compiler-cli): update ast factories to account for type nodes
Updates the Babel and TypeScript AST factories to account to produce type nodes.
2026-03-13 11:13:03 -06:00
Kristiyan Kostadinov
1639fc565b refactor(compiler-cli): add type nodes to translator
Updates the translator and AST factories to account for type nodes.
2026-03-13 11:13:03 -06:00
Kristiyan Kostadinov
2831ff2330 refactor(compiler-cli): add generic for type nodes to AST factories
Updates the type factories and various usage sites to add a generic for type nodes.
2026-03-13 11:13:03 -06:00
SkyZeroZx
8edcf41760 refactor(compiler-cli): add warning for matching viewport @defer trigger options
Ensures that viewport `@defer` trigger prefetch warnings occur when the viewport options are identical, including cases with empty or no parameters.
2026-03-12 16:21:02 -06:00
Alan Agius
4febb8ad31 build: update aspect_rules_js to 3.0.2 (#67518)
This updates the major version of `aspect_rules_js`.

PR Close #67518
2026-03-11 13:37:33 -07:00
SkyZeroZx
66e72efef4 refactor(compiler-cli): simplifies IncrementalCompilation.fresh
Removes the `ts.Program` argument from the `IncrementalCompilation.fresh` method.
2026-03-11 09:41:02 -07:00
Ibrahim Hussien
903d51e855 docs: combine multiple documentation improvements into one PR 2026-03-11 09:29:45 -07:00
Kristiyan Kostadinov
1866bf5d61 refactor(compiler-cli): remove more unused code
Cleans up some more usages of TS factory APIs and some unused functions.
2026-03-10 10:57:30 -07:00
Kristiyan Kostadinov
82b758e934 refactor(compiler-cli): replace typescript usage in type reference emits
Replaces our usage of TypeScript APIs in several places that emit references to type nodes. Also deletes some unused code.
2026-03-09 11:22:53 -07:00
Andrew Scott
8217ef9b24 refactor(compiler-cli): abstract type check block metadata to be AST-free
This commit refactors the template type checking metadata interfaces to use detached, serializable metadata rather than retaining direct references to ts.Node or ts.Declaration instances.

A new tcb_adapter translates traditional TypeScript AST-bound metadata into these decoupled structures. This abstraction lays the groundwork for supporting native preprocessors (such as Rust or ts-go) which serialize metadata over JSON rather than passing live TypeScript objects.

Key changes:
- Introduced TcbDirectiveMetadata, TcbComponentMetadata, TcbReferenceMetadata, and TcbPipeMetadata to replace TypeCheckableDirectiveMeta where appropriate.
- Substituted deep TS compilation AST references with string module names and source spans to preserve out-of-band diagnostic capabilities.
- Detached generic typeParameters and transformType properties into synthesized, standalone TS mappings.
- Updated generateTypeCheckBlock and corresponding Operations to consume the new metadata.
2026-03-05 13:31:36 -08:00
Doug Parker
dc4cf649b6 fix(compiler-cli): ignore generated ngDevMode signal branch for code coverage
The Angular compiler unconditionally adds a debug name transform for signals
which generates a conditional on `ngDevMode` (e.g., `ngDevMode ? { debugName: "xyz" } : []`).
During testing, `ngDevMode` is true, so the true branch executes but the
false branch is never executed. Consequently, coverage tools report the
false branch as an untested line/branch, preventing 100% test coverage.

This commit adds a synthetic `/* istanbul ignore next */` comment to the
generated false branch so that Istanbul ignores it. We only include the
istanbul comment (instead of additionally including c8) to focus on the
established standard for Angular CLI/Karma coverage while maintaining
compatibility with modern Vitest setups, since @vitest/coverage-v8 now
natively respects the fallback istanbul comment.

Fixes #64583
2026-03-04 14:42:53 -08:00
Kristiyan Kostadinov
2c87f21abe fix(compiler-cli): always parenthesize object literals in TCB
This is a follow-up to #67381 which introduced a subtle bug where depending on the type checking configuration, we may put an object literal directly in the TCB body which the TS compiler ends up interpreting as a block. These changes resolve the issue by always wrapping the literal in parentheses.
2026-03-04 08:00:00 -08:00
Krueger01
0e9d58ef09 refactor(compiler-cli): update old angular.io references to angular.dev
Update comment references from the old site angular.io to the new site
angular.dev.
2026-03-03 14:22:20 -08:00
Kristiyan Kostadinov
f28b8f621d refactor(compiler-cli): resolve presubmit issues
Resolves issues caught during the presubmit.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov
f26308813b refactor(compiler-cli): escape quotes used in string expressions
TypeScript has functionality that automatically escapes quotes in string literals. These changes update the places where we may need to do the same ourselves.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov
b37fce6066 refactor(compiler-cli): delete unused utilities
Deletes utilities that we no longer use.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov
befbae0dcf refactor(compiler-cli): initial decoupling from TypeScript factory APIs
Initial pass to move usages of TS `factory` APIs to the new `TcbExpr`.
2026-03-03 11:02:49 -08:00
Kristiyan Kostadinov
3828ef1917 refactor(compiler-cli): introduce new primitive for generating TCB code
Introduces the `TcbExpr` class that will be used to generate TCB code without going through TypeScript's factory APIs.
2026-03-03 11:02:49 -08:00
Matthieu Riegler
03db2aefaa fix(compiler): throw on duplicate input/outputs
inputs & outputs cannot be binded to 2 different directives/components properties

Eg
```
data = model();
dataChange = output(); // throws because model already emits on the `dataChange` output

userSomething = input({alias 'user'});
user = input(); // throws because userSomething already binds to the `user` input
````

fixes #65844

BREAKING CHANGE: The compiler will throw when there a when inputs, outputs or model are binding to the same input/outputs.
2026-02-26 13:47:37 -08:00
splincode
66b472e2bc refactor(compiler-cli): improve diagnostic with help link
Add help link to extended template diagnostic messages to provide
users with additional guidance and documentation resources. This
enhancement improves developer experience by making it easier to
understand and resolve complex template issues through direct
access to relevant Angular documentation with detailed examples
and explanations for each diagnostic type.
2026-02-20 09:40:18 -08:00
SkyZeroZx
f90e5565e0 fix(compiler-cli): detect uninvoked functions in defer trigger expressions
Wrap `@defer` trigger expressions (`when`, `prefetch when`, `hydrate when`)
in a conditional context within the TCB to enable TypeScript's TS2774
diagnostic for detecting functions used without invocation.

Previously, signals and functions passed to `when` triggers without
parentheses would silently evaluate to truthy, causing unexpected behavior.
Now the compiler reports an error when a function is used as a condition
without being called.
2026-02-20 08:57:03 -08:00