mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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:
@@ -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});
|
||||
|
||||
Reference in New Issue
Block a user