refactor(compiler-cli): remove Ivy switch transform (#43891)

Now that the core package has been cleaned up to no longer contain Ivy
switch code, the transform to switch the `PRE_R3` markers to become
`POST_R3` is deleted as well.

PR Close #43891
This commit is contained in:
JoostK
2021-10-19 19:03:48 +02:00
committed by Jessica Janiuk
parent 0ca5c5bd09
commit b281a031cc
6 changed files with 0 additions and 196 deletions
@@ -31,7 +31,6 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/scope",
"//packages/compiler-cli/src/ngtsc/shims",
"//packages/compiler-cli/src/ngtsc/shims:api",
"//packages/compiler-cli/src/ngtsc/switch",
"//packages/compiler-cli/src/ngtsc/transform",
"//packages/compiler-cli/src/ngtsc/typecheck",
"//packages/compiler-cli/src/ngtsc/typecheck/api",
@@ -25,7 +25,6 @@ import {DeclarationNode, isNamedClassDeclaration, TypeScriptReflectionHost} from
import {AdapterResourceLoader} from '../../resource';
import {ComponentScopeReader, LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver, TypeCheckScopeRegistry} from '../../scope';
import {generatedFactoryTransform} from '../../shims';
import {ivySwitchTransform} from '../../switch';
import {aliasTransformFactory, CompilationMode, declarationTransformFactory, DecoratorHandler, DtsTransformRegistry, ivyTransformFactory, TraitCompiler} from '../../transform';
import {TemplateTypeCheckerImpl} from '../../typecheck';
import {OptimizeFor, TemplateTypeChecker, TypeCheckingConfig} from '../../typecheck/api';
@@ -647,7 +646,6 @@ export class NgCompiler {
before.push(
generatedFactoryTransform(this.adapter.factoryTracker.sourceInfo, importRewriter));
}
before.push(ivySwitchTransform);
return {transformers: {before, afterDeclarations} as ts.CustomTransformers};
}
@@ -1,14 +0,0 @@
load("//tools:defaults.bzl", "ts_library")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "switch",
srcs = ["index.ts"] + glob([
"src/**/*.ts",
]),
deps = [
"//packages/compiler",
"@npm//typescript",
],
)
@@ -1,9 +0,0 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export {ivySwitchTransform} from './src/switch';
@@ -1,139 +0,0 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
const IVY_SWITCH_PRE_SUFFIX = '__PRE_R3__';
const IVY_SWITCH_POST_SUFFIX = '__POST_R3__';
export function ivySwitchTransform(_: ts.TransformationContext): ts.Transformer<ts.SourceFile> {
return flipIvySwitchInFile;
}
function flipIvySwitchInFile(sf: ts.SourceFile): ts.SourceFile {
// To replace the statements array, it must be copied. This only needs to happen if a statement
// must actually be replaced within the array, so the newStatements array is lazily initialized.
let newStatements: ts.Statement[]|undefined = undefined;
// Iterate over the statements in the file.
for (let i = 0; i < sf.statements.length; i++) {
const statement = sf.statements[i];
// Skip over everything that isn't a variable statement.
if (!ts.isVariableStatement(statement) || !hasIvySwitches(statement)) {
continue;
}
// This statement needs to be replaced. Check if the newStatements array needs to be lazily
// initialized to a copy of the original statements.
if (newStatements === undefined) {
newStatements = [...sf.statements];
}
// Flip any switches in the VariableStatement. If there were any, a new statement will be
// returned; otherwise the old statement will be.
newStatements[i] = flipIvySwitchesInVariableStatement(statement, sf.statements);
}
// Only update the statements in the SourceFile if any have changed.
if (newStatements !== undefined) {
return ts.updateSourceFileNode(sf, newStatements);
}
return sf;
}
/**
* Look for the ts.Identifier of a ts.Declaration with this name.
*
* The real identifier is needed (rather than fabricating one) as TypeScript decides how to
* reference this identifier based on information stored against its node in the AST, which a
* synthetic node would not have. In particular, since the post-switch variable is often exported,
* TypeScript needs to know this so it can write `exports.VAR` instead of just `VAR` when emitting
* code.
*
* Only variable, function, and class declarations are currently searched.
*/
function findPostSwitchIdentifier(
statements: ReadonlyArray<ts.Statement>, name: string): ts.Identifier|null {
for (const stmt of statements) {
if (ts.isVariableStatement(stmt)) {
const decl = stmt.declarationList.declarations.find(
decl => ts.isIdentifier(decl.name) && decl.name.text === name);
if (decl !== undefined) {
return decl.name as ts.Identifier;
}
} else if (ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) {
if (stmt.name !== undefined && ts.isIdentifier(stmt.name) && stmt.name.text === name) {
return stmt.name;
}
}
}
return null;
}
/**
* Flip any Ivy switches which are discovered in the given ts.VariableStatement.
*/
function flipIvySwitchesInVariableStatement(
stmt: ts.VariableStatement, statements: ReadonlyArray<ts.Statement>): ts.VariableStatement {
// Build a new list of variable declarations. Specific declarations that are initialized to a
// pre-switch identifier will be replaced with a declaration initialized to the post-switch
// identifier.
const newDeclarations = [...stmt.declarationList.declarations];
for (let i = 0; i < newDeclarations.length; i++) {
const decl = newDeclarations[i];
// Skip declarations that aren't initialized to an identifier.
if (decl.initializer === undefined || !ts.isIdentifier(decl.initializer)) {
continue;
}
// Skip declarations that aren't Ivy switches.
if (!decl.initializer.text.endsWith(IVY_SWITCH_PRE_SUFFIX)) {
continue;
}
// Determine the name of the post-switch variable.
const postSwitchName =
decl.initializer.text.replace(IVY_SWITCH_PRE_SUFFIX, IVY_SWITCH_POST_SUFFIX);
// Find the post-switch variable identifier. If one can't be found, it's an error. This is
// reported as a thrown error and not a diagnostic as transformers cannot output diagnostics.
const newIdentifier = findPostSwitchIdentifier(statements, postSwitchName);
if (newIdentifier === null) {
throw new Error(`Unable to find identifier ${postSwitchName} in ${
stmt.getSourceFile().fileName} for the Ivy switch.`);
}
newDeclarations[i] = ts.updateVariableDeclaration(
/* node */ decl,
/* name */ decl.name,
/* type */ decl.type,
/* initializer */ newIdentifier);
}
const newDeclList = ts.updateVariableDeclarationList(
/* declarationList */ stmt.declarationList,
/* declarations */ newDeclarations);
const newStmt = ts.updateVariableStatement(
/* statement */ stmt,
/* modifiers */ stmt.modifiers,
/* declarationList */ newDeclList);
return newStmt;
}
/**
* Check whether the given VariableStatement has any Ivy switch variables.
*/
function hasIvySwitches(stmt: ts.VariableStatement) {
return stmt.declarationList.declarations.some(
decl => decl.initializer !== undefined && ts.isIdentifier(decl.initializer) &&
decl.initializer.text.endsWith(IVY_SWITCH_PRE_SUFFIX));
}
@@ -6254,37 +6254,6 @@ function allTests(os: string) {
});
});
describe('ivy switch mode', () => {
it('should allow for symbols to be renamed when they use a SWITCH_IVY naming mechanism',
() => {
env.write('test.ts', `
export const FooCmp__POST_R3__ = 1;
export const FooCmp__PRE_R3__ = 2;
export const FooCmp = FooCmp__PRE_R3__;`);
env.driveMain();
const source = env.getContents('test.js');
expect(source).toContain(`export var FooCmp = FooCmp__POST_R3__`);
expect(source).not.toContain(`export var FooCmp = FooCmp__PRE_R3__`);
});
it('should allow for SWITCH_IVY naming even even if it occurs outside of core', () => {
const content = `
export const Foo__POST_R3__ = 1;
export const Foo__PRE_R3__ = 2;
export const Foo = Foo__PRE_R3__;
`;
env.write('test_outside_angular_core.ts', content);
env.write(
'test_inside_angular_core.ts', content + '\nexport const ITS_JUST_ANGULAR = true;');
env.driveMain();
const sourceTestOutsideAngularCore = env.getContents('test_outside_angular_core.js');
const sourceTestInsideAngularCore = env.getContents('test_inside_angular_core.js');
expect(sourceTestInsideAngularCore).toContain(sourceTestOutsideAngularCore);
});
});
describe('NgModule export aliasing', () => {
it('should use an alias to import a directive from a deep dependency', () => {
env.tsconfig({'_useHostForImportGeneration': true});