refactor(compiler-cli): add compiler flag for testing let declarations (#56199)

Adds a private `_enableLetSyntax` flag that allows for let declarations to be enabled in tests.

PR Close #56199
This commit is contained in:
Kristiyan Kostadinov
2024-05-01 14:13:15 +02:00
committed by Jessica Janiuk
parent c7ede8b2f5
commit 405e4dda92
8 changed files with 34 additions and 11 deletions
+1
View File
@@ -91,6 +91,7 @@ export async function runOneBuild(
'forbidOrphanComponents',
'onlyExplicitDeferDependencyImports',
'generateExtraImportsInLocalMode',
'_enableLetSyntax',
]);
const userOverrides = Object.entries(userOptions)
@@ -246,6 +246,7 @@ export class ComponentDecoratorHandler
private readonly deferredSymbolTracker: DeferredSymbolTracker,
private readonly forbidOrphanRendering: boolean,
private readonly enableBlockSyntax: boolean,
private readonly enableLetSyntax: boolean,
private readonly localCompilationExtraImportsTracker: LocalCompilationExtraImportsTracker | null,
) {
this.extractTemplateOptions = {
@@ -253,6 +254,7 @@ export class ComponentDecoratorHandler
i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs,
usePoisonedData: this.usePoisonedData,
enableBlockSyntax: this.enableBlockSyntax,
enableLetSyntax: this.enableLetSyntax,
};
}
@@ -272,6 +274,7 @@ export class ComponentDecoratorHandler
i18nNormalizeLineEndingsInICUs: boolean;
usePoisonedData: boolean;
enableBlockSyntax: boolean;
enableLetSyntax: boolean;
};
readonly precedence = HandlerPrecedence.PRIMARY;
@@ -621,6 +624,7 @@ export class ComponentDecoratorHandler
i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs,
usePoisonedData: this.usePoisonedData,
enableBlockSyntax: this.enableBlockSyntax,
enableLetSyntax: this.enableLetSyntax,
},
this.compilationMode,
);
@@ -13,6 +13,7 @@ import {
ParsedTemplate,
ParseSourceFile,
parseTemplate,
ParseTemplateOptions,
TmplAstNode,
} from '@angular/compiler';
import ts from 'typescript';
@@ -131,6 +132,7 @@ export interface ExtractTemplateOptions {
enableI18nLegacyMessageIdFormat: boolean;
i18nNormalizeLineEndingsInICUs: boolean;
enableBlockSyntax: boolean;
enableLetSyntax: boolean;
}
export function extractTemplate(
@@ -259,16 +261,20 @@ function parseExtractedTemplate(
): ParsedComponentTemplate {
// We always normalize line endings if the template has been escaped (i.e. is inline).
const i18nNormalizeLineEndingsInICUs = escapedString || options.i18nNormalizeLineEndingsInICUs;
const parsedTemplate = parseTemplate(sourceStr, sourceMapUrl ?? '', {
preserveWhitespaces: template.preserveWhitespaces,
const commonParseOptions: ParseTemplateOptions = {
interpolationConfig: template.interpolationConfig,
range: sourceParseRange ?? undefined,
escapedString,
enableI18nLegacyMessageIdFormat: options.enableI18nLegacyMessageIdFormat,
i18nNormalizeLineEndingsInICUs,
alwaysAttemptHtmlToR3AstConversion: options.usePoisonedData,
escapedString,
enableBlockSyntax: options.enableBlockSyntax,
enableLetSyntax: options.enableLetSyntax,
};
const parsedTemplate = parseTemplate(sourceStr, sourceMapUrl ?? '', {
...commonParseOptions,
preserveWhitespaces: template.preserveWhitespaces,
});
// Unfortunately, the primary parse of the template above may not contain accurate source map
@@ -287,16 +293,10 @@ function parseExtractedTemplate(
// with the above options set to preserve source mappings.
const {nodes: diagNodes} = parseTemplate(sourceStr, sourceMapUrl ?? '', {
...commonParseOptions,
preserveWhitespaces: true,
preserveLineEndings: true,
interpolationConfig: template.interpolationConfig,
range: sourceParseRange ?? undefined,
escapedString,
enableI18nLegacyMessageIdFormat: options.enableI18nLegacyMessageIdFormat,
i18nNormalizeLineEndingsInICUs,
leadingTriviaChars: [],
alwaysAttemptHtmlToR3AstConversion: options.usePoisonedData,
enableBlockSyntax: options.enableBlockSyntax,
});
return {
@@ -142,6 +142,7 @@ function setup(
new DeferredSymbolTracker(checker, /* onlyExplicitDeferDependencyImports */ false),
/* forbidOrphanRenderering */ false,
/* enableBlockSyntax */ true,
/* enableLetSyntax */ false,
/* localCompilationExtraImportsTracker */ null,
);
return {reflectionHost, handler, resourceLoader, metaRegistry};
@@ -82,6 +82,14 @@ export interface InternalOptions {
*/
_enableBlockSyntax?: boolean;
/**
* Whether `@let` syntax is enabled in the compiler.
* Defaults to false while the feature is being developed.
*
* @internal
*/
_enableLetSyntax?: boolean;
/**
* Detected version of `@angular/core` in the workspace. Used by the
* compiler to adjust the output depending on the available symbols.
@@ -384,6 +384,7 @@ export class NgCompiler {
readonly ignoreForEmit: Set<ts.SourceFile>;
readonly enableTemplateTypeChecker: boolean;
private readonly enableBlockSyntax: boolean;
private readonly enableLetSyntax: boolean;
private readonly angularCoreVersion: string | null;
/**
@@ -454,6 +455,7 @@ export class NgCompiler {
enableTemplateTypeChecker || (options['_enableTemplateTypeChecker'] ?? false);
// TODO(crisbeto): remove this flag and base `enableBlockSyntax` on the `angularCoreVersion`.
this.enableBlockSyntax = options['_enableBlockSyntax'] ?? true;
this.enableLetSyntax = options['_enableLetSyntax'] ?? false;
this.angularCoreVersion = options['_angularCoreVersion'] ?? null;
this.constructionDiagnostics.push(
...this.adapter.constructionDiagnostics,
@@ -1397,6 +1399,7 @@ export class NgCompiler {
deferredSymbolsTracker,
!!this.options.forbidOrphanComponents,
this.enableBlockSyntax,
this.enableLetSyntax,
localCompilationExtraImportsTracker,
),
@@ -124,6 +124,9 @@ export interface ParseTemplateOptions {
/** Whether the @ block syntax is enabled. */
enableBlockSyntax?: boolean;
/** Whether the `@let` syntax is enabled. */
enableLetSyntax?: boolean;
// TODO(crisbeto): delete this option when the migration is deleted.
/**
* Whether the parser should allow invalid two-way bindings.
@@ -158,6 +161,7 @@ export function parseTemplate(
...options,
tokenizeExpansionForms: true,
tokenizeBlocks: options.enableBlockSyntax ?? true,
tokenizeLet: options.enableLetSyntax ?? false,
});
if (
@@ -225,6 +225,8 @@ function ingestNodes(unit: ViewCompilationUnit, template: t.Node[]): void {
ingestIcu(unit, node);
} else if (node instanceof t.ForLoopBlock) {
ingestForBlock(unit, node);
} else if (node instanceof t.LetDeclaration) {
// TODO(crisbeto): needs further integration
} else {
throw new Error(`Unsupported template node: ${node.constructor.name}`);
}