refactor(compiler): add flag to disable block syntax in language service (#52683)

Adds the private `_enableBlockSyntax` flag that can be used by the language service to disable blocks on apps that aren't on Angular v17.

PR Close #52683
This commit is contained in:
Kristiyan Kostadinov
2023-11-08 17:29:06 +01:00
committed by Andrew Scott
parent a46c8cbf4e
commit 227de98201
6 changed files with 39 additions and 2 deletions
@@ -83,11 +83,13 @@ export class ComponentDecoratorHandler implements
private hostDirectivesResolver: HostDirectivesResolver, private includeClassMetadata: boolean,
private readonly compilationMode: CompilationMode,
private readonly deferredSymbolTracker: DeferredSymbolTracker,
private readonly forbidOrphanRendering: boolean) {
private readonly forbidOrphanRendering: boolean,
private readonly enableBlockSyntax: boolean) {
this.extractTemplateOptions = {
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs,
usePoisonedData: this.usePoisonedData,
enableBlockSyntax: this.enableBlockSyntax,
};
}
@@ -106,6 +108,7 @@ export class ComponentDecoratorHandler implements
enableI18nLegacyMessageIdFormat: boolean,
i18nNormalizeLineEndingsInICUs: boolean,
usePoisonedData: boolean,
enableBlockSyntax: boolean,
};
readonly precedence = HandlerPrecedence.PRIMARY;
@@ -360,6 +363,7 @@ export class ComponentDecoratorHandler implements
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs,
usePoisonedData: this.usePoisonedData,
enableBlockSyntax: this.enableBlockSyntax,
},
this.compilationMode);
}
@@ -119,6 +119,7 @@ export interface ExtractTemplateOptions {
usePoisonedData: boolean;
enableI18nLegacyMessageIdFormat: boolean;
i18nNormalizeLineEndingsInICUs: boolean;
enableBlockSyntax: boolean;
}
export function extractTemplate(
@@ -237,6 +238,7 @@ function parseExtractedTemplate(
enableI18nLegacyMessageIdFormat: options.enableI18nLegacyMessageIdFormat,
i18nNormalizeLineEndingsInICUs,
alwaysAttemptHtmlToR3AstConversion: options.usePoisonedData,
enableBlockSyntax: options.enableBlockSyntax,
});
// Unfortunately, the primary parse of the template above may not contain accurate source map
@@ -264,6 +266,7 @@ function parseExtractedTemplate(
i18nNormalizeLineEndingsInICUs,
leadingTriviaChars: [],
alwaysAttemptHtmlToR3AstConversion: options.usePoisonedData,
enableBlockSyntax: options.enableBlockSyntax,
});
return {
@@ -103,6 +103,7 @@ function setup(
compilationMode,
new DeferredSymbolTracker(checker),
/* forbidOrphanRenderering */ false,
/* enableBlockSyntax */ true,
);
return {reflectionHost, handler, resourceLoader, metaRegistry};
}
@@ -66,6 +66,14 @@ export interface InternalOptions {
* @internal
*/
supportJitMode?: boolean;
/**
* Whether block syntax is enabled in the compiler. Defaults to true.
* Used in the language service to disable the new syntax for projects that aren't on v17.
*
* @internal
*/
_enableBlockSyntax?: boolean;
}
/**
@@ -258,6 +258,7 @@ export class NgCompiler {
readonly ignoreForDiagnostics: Set<ts.SourceFile>;
readonly ignoreForEmit: Set<ts.SourceFile>;
readonly enableTemplateTypeChecker: boolean;
private readonly enableBlockSyntax: boolean;
/**
* `NgCompiler` can be reused for multiple compilations (for resource-only changes), and each
@@ -322,6 +323,7 @@ export class NgCompiler {
) {
this.enableTemplateTypeChecker =
enableTemplateTypeChecker || (options['_enableTemplateTypeChecker'] ?? false);
this.enableBlockSyntax = options['_enableBlockSyntax'] ?? true;
this.constructionDiagnostics.push(
...this.adapter.constructionDiagnostics, ...verifyCompatibleTypeCheckOptions(this.options));
@@ -1106,7 +1108,7 @@ export class NgCompiler {
this.incrementalCompilation.depGraph, injectableRegistry, semanticDepGraphUpdater,
this.closureCompilerEnabled, this.delegatingPerfRecorder, hostDirectivesResolver,
supportTestBed, compilationMode, deferredSymbolsTracker,
!!this.options.forbidOrphanComponents),
!!this.options.forbidOrphanComponents, this.enableBlockSyntax),
// TODO(alxhub): understand why the cast here is necessary (something to do with `null`
// not being assignable to `unknown` when wrapped in `Readonly`).
@@ -8495,6 +8495,25 @@ function allTests(os: string) {
expect(codes).toEqual([ngErrorCode(ErrorCode.NGMODULE_BOOTSTRAP_IS_STANDALONE)]);
});
it('should be able to turn off control flow using a compiler flag', () => {
env.tsconfig({_enableBlockSyntax: false});
env.write('/test.ts', `
import { Component } from '@angular/core';
@Component({
standalone: true,
template: 'My email is foo@bar.com',
})
export class TestCmp {}
`);
env.driveMain();
// If blocks are enabled, this test will fail since `@bar.com` is an incomplete block.
const jsContents = env.getContents('test.js');
expect(jsContents).toContain('text(0, "My email is foo@bar.com")');
});
describe('InjectorDef emit optimizations for standalone', () => {
it('should not filter components out of NgModule.imports', () => {
env.write('test.ts', `