refactor(compiler-cli): add compiler option for enabling source locations

Adds an internal config options that allows us to enable source locations.
This commit is contained in:
Kristiyan Kostadinov
2026-08-20 10:43:58 +02:00
committed by Leon Senft
parent 2ab5ff56de
commit f3c093df24
12 changed files with 52 additions and 25 deletions
@@ -7,6 +7,7 @@
// @public
export interface BazelAndG3Options {
annotateForClosureCompiler?: boolean;
enableTemplateSourceLocations?: boolean;
_experimentalAllowEmitDeclarationOnly?: boolean;
generateDeepReexports?: boolean;
generateExtraImportsInLocalMode?: boolean;
@@ -255,6 +255,7 @@ export class PartialComponentLinkerVersion1<
declarations,
hasDirectiveDependencies: !baseMeta.isStandalone || hasDirectiveDependencies,
foreignImports: null,
enableTemplateSourceLocations: false,
};
}
@@ -291,6 +291,7 @@ export class ComponentDecoratorHandler implements DecoratorHandler<
private readonly enableSelectorless: boolean,
private readonly emitDeclarationOnly: boolean,
private readonly legacyOptionalChaining: boolean,
private readonly enableTemplateSourceLocations: boolean,
) {
this.extractTemplateOptions = {
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
@@ -1037,6 +1038,7 @@ export class ComponentDecoratorHandler implements DecoratorHandler<
rawImports: rawImports !== null ? new o.WrappedNodeExpr(rawImports) : undefined,
relativeTemplatePath,
foreignImports: null,
enableTemplateSourceLocations: this.enableTemplateSourceLocations,
},
typeCheckMeta: extractDirectiveTypeCheckMeta(node, inputs, this.reflector),
classMetadata: this.includeClassMetadata
@@ -164,6 +164,7 @@ function setup(
/* enableSelectorless */ false,
/* emitDeclarationOnly */ false,
/* enableInlineStyles */ true,
/* enableTemplateSourceLocations */ false,
);
return {reflectionHost, handler, resourceLoader, metaRegistry};
}
@@ -340,11 +340,18 @@ export interface BazelAndG3Options {
_experimentalAllowEmitDeclarationOnly?: boolean;
/**
* Whether to follow the Javascript optional chaining specs: returning `undefined` instead of `null` for null-safe navigation operations.
* Whether to follow the Javascript optional chaining specs: returning `undefined` instead of
* `null` for null-safe navigation operations.
*
* Defaults to `false`.
*/
legacyOptionalChaining?: boolean;
/**
* Whether to generate additional code that adds the source location
* of elements to the DOM as an attribute.
*/
enableTemplateSourceLocations?: boolean;
}
/**
@@ -397,6 +397,7 @@ export class NgCompiler {
private readonly implicitStandaloneValue: boolean;
private readonly enableSelectorless: boolean;
private readonly emitDeclarationOnly: boolean;
private readonly enableTemplateSourceLocations: boolean;
/**
* `NgCompiler` can be reused for multiple compilations (for resource-only changes), and each
@@ -472,6 +473,7 @@ export class NgCompiler {
this.angularCoreVersion === null ||
coreVersionSupportsFeature(this.angularCoreVersion, '>= 18.1.0');
this.enableSelectorless = options['_enableSelectorless'] ?? false;
this.enableTemplateSourceLocations = options['enableTemplateSourceLocations'] ?? false;
this.emitDeclarationOnly =
!!options.emitDeclarationOnly && !!options._experimentalAllowEmitDeclarationOnly;
// Standalone by default is enabled since v19. We need to toggle it here,
@@ -1549,6 +1551,7 @@ export class NgCompiler {
this.enableSelectorless,
this.emitDeclarationOnly,
this.options.legacyOptionalChaining ?? LEGACY_OPTIONAL_CHAINING_DEFAULT,
this.enableTemplateSourceLocations,
),
// TODO(alxhub): understand why the cast here is necessary (something to do with `null`
@@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {setEnableTemplateSourceLocations} from '@angular/compiler';
import {runInEachFileSystem} from '../../src/ngtsc/file_system/testing';
import {loadStandardTestFiles} from '../../src/ngtsc/testing';
import {NgtscTestEnvironment} from './env';
@@ -18,16 +17,33 @@ runInEachFileSystem(() => {
let env!: NgtscTestEnvironment;
beforeEach(() => {
setEnableTemplateSourceLocations(true);
env = NgtscTestEnvironment.setup(testFiles);
env.tsconfig();
});
afterEach(() => {
setEnableTemplateSourceLocations(false);
it('should not attach template source locations by default', () => {
env.tsconfig();
env.write(
`test.ts`,
`
import {Component} from '@angular/core';
@Component({
template: \`
<div><span>
<strong>Hello</strong>
</span></div>
\`,
})
class Comp {}
`,
);
env.driveMain();
const content = env.getContents('test.js');
expect(content).not.toContain('ɵɵattachSourceLocations');
});
it('should attach the source location in an inline template', () => {
env.tsconfig({enableTemplateSourceLocations: true});
env.write(
`test.ts`,
`
@@ -52,6 +68,7 @@ runInEachFileSystem(() => {
});
it('should attach the source location in an external template', () => {
env.tsconfig({enableTemplateSourceLocations: true});
env.write(
'test.html',
`
@@ -79,6 +96,7 @@ runInEachFileSystem(() => {
});
it('should attach the source location to structural directives', () => {
env.tsconfig({enableTemplateSourceLocations: true});
env.write(
`test.ts`,
`
@@ -107,6 +125,7 @@ runInEachFileSystem(() => {
});
it('should not attach the source location to ng-container', () => {
env.tsconfig({enableTemplateSourceLocations: true});
env.write(
`test.ts`,
`
-1
View File
@@ -265,7 +265,6 @@ export {outputAst};
export {CompilerFacadeImpl} from './jit_compiler_facade';
export {FactoryTarget} from './compiler_facade_interface';
export {QueryFlags} from './render3/view/query_generation';
export {setEnableTemplateSourceLocations} from './render3/view/config';
export * from './typecheck/api';
export * from './typecheck/host_bindings';
@@ -363,6 +363,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
i18nUseExternalIds: true,
relativeTemplatePath: null,
foreignImports: null,
enableTemplateSourceLocations: false,
};
const jitExpressionSourceMap = `ng:///${facade.name}.js`;
return this.compileComponentFromMeta(angularCoreEnv, jitExpressionSourceMap, meta);
@@ -724,6 +725,7 @@ function convertDeclareComponentFacadeToMetadata(
hasDirectiveDependencies,
legacyOptionalChaining: decl.legacyOptionalChaining ?? LEGACY_OPTIONAL_CHAINING_DEFAULT,
foreignImports: null,
enableTemplateSourceLocations: false,
};
}
+7 -3
View File
@@ -310,6 +310,12 @@ export interface R3ComponentMetadata<
* Foreign components imported by the component.
*/
foreignImports: R3ForeignComponentMetadata[] | null;
/**
* Whether to generate additional code that adds the source location
* of elements to the DOM as an attribute.
*/
enableTemplateSourceLocations?: boolean;
}
/**
@@ -364,9 +370,7 @@ export interface R3TemplateDependency {
* A dependency that's used within a component template
*/
export type R3TemplateDependencyMetadata =
| R3DirectiveDependencyMetadata
| R3PipeDependencyMetadata
| R3NgModuleDependencyMetadata;
R3DirectiveDependencyMetadata | R3PipeDependencyMetadata | R3NgModuleDependencyMetadata;
/**
* Information about a directive that is used in a component template. Only the stable, public
@@ -27,7 +27,7 @@ import {
R3HostMetadata,
R3TemplateDependency,
} from './api';
import {getTemplateSourceLocationsEnabled} from './config';
import {ENABLE_TEMPLATE_SOURCE_LOCATIONS} from './config';
import {createContentQueriesFunction, createViewQueriesFunction} from './query_generation';
import {makeBindingParser} from './template';
import {asLiteral, conditionallyCreateDirectiveBindingLiteral, DefinitionMap} from './util';
@@ -214,7 +214,7 @@ export function compileComponentFromMetadata(
meta.defer,
allDeferrableDepsFn,
meta.relativeTemplatePath,
getTemplateSourceLocationsEnabled(),
meta.enableTemplateSourceLocations || ENABLE_TEMPLATE_SOURCE_LOCATIONS,
meta.legacyOptionalChaining,
meta.foreignImports,
);
+1 -13
View File
@@ -13,16 +13,4 @@
* tools enable it via a local change. Any modifications to this flag need to update the
* internal tooling as well.
*/
let ENABLE_TEMPLATE_SOURCE_LOCATIONS = false;
/**
* Utility function to enable source locations. Intended to be used **only** inside unit tests.
*/
export function setEnableTemplateSourceLocations(value: boolean): void {
ENABLE_TEMPLATE_SOURCE_LOCATIONS = value;
}
/** Gets whether template source locations are enabled. */
export function getTemplateSourceLocationsEnabled(): boolean {
return ENABLE_TEMPLATE_SOURCE_LOCATIONS;
}
export const ENABLE_TEMPLATE_SOURCE_LOCATIONS = false;