Changes to the transformation chain implementation.

This commit is contained in:
Ron Buckton 2015-10-16 16:18:06 -07:00
parent abd46f9f36
commit 9aafff669f
8 changed files with 229 additions and 172 deletions

View File

@ -79,10 +79,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
let shouldEmitJsx = (s: SourceFile) => (s.languageVariant === LanguageVariant.JSX && !jsxDesugaring);
let transformationChain = getTransformationChain(compilerOptions);
let sourceFiles: SourceFile[];
let transformationResolver: TransformationResolver;
let substitutions: TransformationSubstitutions;
if (targetSourceFile === undefined) {
({ sourceFiles, transformationResolver } = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain));
({ sourceFiles, substitutions } = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain));
forEach(sourceFiles, sourceFile => {
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js");
@ -98,11 +98,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js");
({ sourceFiles: [targetSourceFile], transformationResolver } = transformFilesIfNeeded(resolver, host, [targetSourceFile], transformationChain));
({ sourceFiles: [targetSourceFile], substitutions } = transformFilesIfNeeded(resolver, host, [targetSourceFile], transformationChain));
emitFile(jsFilePath, targetSourceFile);
}
else if (!isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) {
({ sourceFiles, transformationResolver } = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain));
({ sourceFiles, substitutions } = transformFilesIfNeeded(resolver, host, host.getSourceFiles(), transformationChain));
emitFile(compilerOptions.outFile || compilerOptions.out);
}
}
@ -8003,11 +8003,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
if (compilerOptions.experimentalTransforms) {
let result = sourceFile
? printFile(resolver, transformationResolver, host, [sourceFile], jsFilePath)
: printFile(resolver, transformationResolver, host, sourceFiles, jsFilePath);
writeFile(host, diagnostics, result.fileName, result.text, compilerOptions.emitBOM);
let nodes = sourceFile ? [sourceFile] : sourceFiles;
let text = printNodes(resolver, substitutions, host, filter(nodes, isNonDeclarationFile));
writeFile(host, diagnostics, jsFilePath, text, compilerOptions.emitBOM);
}
else {
emitJavaScript(jsFilePath, sourceFile);

View File

@ -7,6 +7,10 @@ namespace ts {
const brackets = createBracketsMap();
const delimiters = createDelimiterMap();
export interface PrintHost extends ScriptReferenceHost {
getNewLine(): string;
}
/**
* Pretty-prints a set of input source files to an output string.
* @param resolver The emit resolver.
@ -14,21 +18,17 @@ namespace ts {
* @param sourceFiles The input source files.
* @param fileName The output file name.
*/
export function printFile(resolver: EmitResolver, transformationResolver: TransformationResolver, host: EmitHost, sourceFiles: SourceFile[], fileName: string) {
console.log("called printFile!");
export function printNodes(resolver: EmitResolver, substitutions: TransformationSubstitutions, host: PrintHost, nodes: Node[]) {
let writer = createTextWriter(host.getNewLine());
let { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
let { assignmentSubstitution, bindingIdentifierSubstitution, expressionIdentifierSubstitution } = substitutions;
let compilerOptions = host.getCompilerOptions();
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
let diagnostics: Diagnostic[] = [];
let currentSourceFile: SourceFile;
let parentNode: Node;
let currentNode: Node;
let assignmentSubstitution: (node: BinaryExpression) => Expression;
let expressionIdentifierSubstitution: (node: Identifier) => LeftHandSideExpression;
let bindingIdentifierSubstitution: (node: Identifier) => Identifier;
/** Emit a node */
let emit = emitNode;
@ -52,19 +52,16 @@ namespace ts {
/** Called after coming out of the scope */
let scopeEmitEnd = function() { };
/** Sourcemap data that will get encoded */
let sourceMapData: SourceMapData;
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
// initializeEmitterWithSourceMaps();
}
for (let sourceFile of sourceFiles) {
emit(sourceFile);
for (let node of nodes) {
emit(node);
}
writeLine();
return { fileName, text: writer.getText(), sourceMapData };
return writer.getText();
function emitNode(node: Node) {
if (node) {
@ -77,7 +74,7 @@ namespace ts {
}
function tryEmitSubstitute<T extends Node>(node: T, substitution: (node: T) => Node) {
let substitute = substitution(node);
let substitute = substitution ? substitution(node) : node;
if (substitute && substitute !== node) {
let savedCurrentNode = currentNode;
emitNodeWorker(currentNode = substitute);
@ -1525,9 +1522,6 @@ namespace ts {
function emitSourceFile(node: SourceFile) {
currentSourceFile = node;
assignmentSubstitution = transformationResolver.getAssignmentSubstitution(currentSourceFile);
bindingIdentifierSubstitution = transformationResolver.getBindingIdentifierSubstitution(currentSourceFile);
expressionIdentifierSubstitution = transformationResolver.getExpressionIdentifierSubstitution(currentSourceFile);
writeLine();
emitShebang();
@ -1535,9 +1529,6 @@ namespace ts {
emitList(node, node.statements, ListFormat.SourceFileStatements);
currentSourceFile = undefined;
assignmentSubstitution = undefined;
bindingIdentifierSubstitution = undefined;
expressionIdentifierSubstitution = undefined;
}
//

View File

@ -8,44 +8,49 @@ const FORCE_TRANSFORMS = false;
namespace ts {
export let transformTime = 0;
export type TransformationChain = (node: SourceFile, transformer: Transformer) => SourceFile;
/**
* Represents a phase in a transformation chain. Used to initialize the transformation and
* return the transformation for the phase.
*/
export type TransformationPhase = (transformer: Transformer) => Transformation;
interface LexicalEnvironment {
tempFlags: TempFlags;
hoistedVariableDeclarations: VariableDeclaration[];
hoistedFunctionDeclarations: FunctionDeclaration[];
}
/**
* Represents a chain of transformation phases. Used to initialize the transformation
* chain and return a transformation used to run each transformation for each phase
* of the chain.
*/
export type TransformationChain = (transformer: Transformer) => Transformation;
const enum VisitFlags {
StatementBranch = 1 << 1,
ConciseBody = 1 << 2,
LexicalEnvironment = 1 << 3,
LexicalEnvironmentStarted = 1 << 4,
LexicalEnvironmentEnded = 1 << 5,
}
/**
* Represents a transformation.
*/
export type Transformation = (node: SourceFile) => SourceFile;
/**
* Gets the default transformation chain for the provided set of compiler options.
*/
export function getTransformationChain(options: CompilerOptions): TransformationChain {
let jsx = options.jsx;
let languageVersion = options.target || ScriptTarget.ES3;
let moduleKind = options.module || ModuleKind.None;
let phases: TransformationPhase[] = [];
let transforms: TransformationChain[] = [];
// Add the TypeScript and Module transforms to the chain.
transforms.push(transformTypeScript);
// Add the TypeScript and Module phases to the chain.
phases.push(createTypeScriptTransformation);
// // transforms.push(transformModule);
// // Add the JSX transform to the chain.
// if (jsx === JsxEmit.React) {
// transforms.push(transformJsx);
// }
// Add the JSX transform to the chain.
if (jsx === JsxEmit.React) {
phases.push(createJsxTransformation);
}
// // Add the ES6 transform to the chain.
// if (languageVersion < ScriptTarget.ES6) {
// transforms.push(transformES6);
// }
// Add the ES6 transform to the chain.
if (languageVersion < ScriptTarget.ES6) {
phases.push(createES6Transformation);
}
return chainTransformations(transforms);
// Chain the transformation phases
return chainTransformationPhases(phases);
}
export function transformFilesIfNeeded(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain): TransformationResult {
@ -58,6 +63,20 @@ namespace ts {
}
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformationChain: TransformationChain): TransformationResult {
interface LexicalEnvironment {
tempFlags: TempFlags;
hoistedVariableDeclarations: VariableDeclaration[];
hoistedFunctionDeclarations: FunctionDeclaration[];
}
const enum VisitFlags {
StatementBranch = 1 << 1,
ConciseBody = 1 << 2,
LexicalEnvironment = 1 << 3,
LexicalEnvironmentStarted = 1 << 4,
LexicalEnvironmentEnded = 1 << 5,
}
// emit output for the __extends helper function
const extendsHelper = `
var __extends = (this && this.__extends) || function (d, b) {
@ -131,9 +150,9 @@ function __export(m) {
let updatedNode: Node;
let updatedNodes: Node[];
let helpersEmitted: NodeCheckFlags;
let assignmentSubstitutions: ((node: BinaryExpression) => Expression)[] = [];
let bindingIdentifierSubstitutions: ((node: Identifier) => Identifier)[] = [];
let expressionIdentifierSubstitutions: ((node: Identifier) => LeftHandSideExpression)[] = [];
let assignmentSubstitution: (node: BinaryExpression) => Expression;
let bindingIdentifierSubstitution: (node: Identifier) => Identifier;
let expressionIdentifierSubstitution: (node: Identifier) => LeftHandSideExpression;
let transformer: Transformer = {
getEmitResolver: () => resolver,
getCompilerOptions: () => compilerOptions,
@ -182,12 +201,14 @@ function __export(m) {
}
};
let transformation = transformationChain(transformer);
return {
sourceFiles: map(sourceFiles, transformSourceFile),
transformationResolver: {
getAssignmentSubstitution,
getBindingIdentifierSubstitution,
getExpressionIdentifierSubstitution,
substitutions: {
assignmentSubstitution,
bindingIdentifierSubstitution,
expressionIdentifierSubstitution,
}
};
@ -203,7 +224,7 @@ function __export(m) {
nodeStack = createNodeStack();
helpersEmitted = undefined;
let visited = transformationChain(sourceFile, transformer);
let visited = transformation(sourceFile);
if (visited !== sourceFile) {
visited.identifiers = assign(assign(clone(sourceFile.identifiers), generatedNameSet), tempVariableNameSet);
updateFrom(sourceFile, visited);
@ -219,32 +240,28 @@ function __export(m) {
return visited;
}
function getAssignmentSubstitution(sourceFile: SourceFile): (node: BinaryExpression) => Expression {
return assignmentSubstitutions[getNodeId(getOriginalNode(sourceFile))] || identitySubstitution;
function getAssignmentSubstitution(): (node: BinaryExpression) => Expression {
return assignmentSubstitution;
}
function setAssignmentSubstitution(sourceFile: SourceFile, substitution: (node: BinaryExpression) => Expression) {
assignmentSubstitutions[getNodeId(getOriginalNode(sourceFile))] = substitution;
function setAssignmentSubstitution(substitution: (node: BinaryExpression) => Expression) {
assignmentSubstitution = substitution;
}
function getBindingIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => Identifier {
return bindingIdentifierSubstitutions[getNodeId(getOriginalNode(sourceFile))] || identitySubstitution;
function getBindingIdentifierSubstitution(): (node: Identifier) => Identifier {
return bindingIdentifierSubstitution;
}
function setBindingIdentifierSubstitution(sourceFile: SourceFile, substitution: (node: Identifier) => Identifier): void {
bindingIdentifierSubstitutions[getNodeId(getOriginalNode(sourceFile))] = substitution;
function setBindingIdentifierSubstitution(substitution: (node: Identifier) => Identifier): void {
bindingIdentifierSubstitution = substitution;
}
function getExpressionIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => LeftHandSideExpression {
return expressionIdentifierSubstitutions[getNodeId(getOriginalNode(sourceFile))] || identitySubstitution;
function getExpressionIdentifierSubstitution(): (node: Identifier) => LeftHandSideExpression {
return expressionIdentifierSubstitution;
}
function setExpressionIdentifierSubstitution(sourceFile: SourceFile, substitution: (node: Identifier) => LeftHandSideExpression) {
expressionIdentifierSubstitutions[getNodeId(getOriginalNode(sourceFile))] = substitution;
}
function identitySubstitution<T extends Node>(node: T): T {
return node;
function setExpressionIdentifierSubstitution(substitution: (node: Identifier) => LeftHandSideExpression) {
expressionIdentifierSubstitution = substitution;
}
// Return the next available name in the pattern _a ... _z, _0, _1, ...
@ -929,57 +946,74 @@ function __export(m) {
}
}
export function chainTransformations(transformations: TransformationChain[]): TransformationChain {
switch (transformations.length) {
case 0: return identityTransformation;
case 1: return createUnaryTransformationChain(transformations[0]);
case 2: return createBinaryTransformationChain(transformations[0], transformations[1]);
case 3: return createTrinaryTransformationChain(transformations[0], transformations[1], transformations[2]);
default: return createNaryTransformationChain(transformations);
export function chainTransformationPhases(phases: TransformationPhase[]): TransformationChain {
switch (phases.length) {
case 0: return identityTransformationChain;
case 1: return buildUnaryChain(phases[0]);
case 2: return buildBinaryChain(phases[0], phases[1]);
case 3: return buildTrinaryChain(phases[0], phases[1], phases[2]);
default: return buildNaryChain(phases);
}
}
function runTransformation(chain: TransformationChain, node: SourceFile, transformer: Transformer) {
let start = new Date().getTime();
let transformed = chain(node, transformer);
transformTime += new Date().getTime() - start;
return transformed;
function buildPhase(phase: TransformationPhase, transformer: Transformer) {
if (phase) {
let start = new Date().getTime();
let transformation = phase(transformer);
transformTime += new Date().getTime() - start;
return transformation;
}
return undefined;
}
function createUnaryTransformationChain(only: TransformationChain): TransformationChain {
return (node, transformer) => {
if (only) node = runTransformation(only, node, transformer);
return node;
};
}
function createBinaryTransformationChain(first: TransformationChain, second: TransformationChain): TransformationChain {
return (node, transformer) => {
if (first) node = runTransformation(first, node, transformer);
if (second) node = runTransformation(second, node, transformer);
return node;
};
}
function createTrinaryTransformationChain(first: TransformationChain, second: TransformationChain, third: TransformationChain): TransformationChain {
return (node, transformer) => {
if (first) node = runTransformation(first, node, transformer);
if (second) node = runTransformation(second, node, transformer);
if (third) node = runTransformation(third, node, transformer);
return node;
};
}
function createNaryTransformationChain(transformations: TransformationChain[]): TransformationChain {
return (node, transformer) => {
for (let transformation of transformations) {
if (transformation) node = runTransformation(transformation, node, transformer);
}
return node;
};
}
function identityTransformation(node: SourceFile, transformer: Transformer) {
function runStep(node: SourceFile, step: Transformation) {
if (step) {
let start = new Date().getTime();
let transformed = step(node);
transformTime += new Date().getTime() - start;
return transformed;
}
return node;
}
function identityTransformationChain(transformer: Transformer) {
return identityTransformationStep;
}
function identityTransformationStep(node: SourceFile) {
return node;
}
function buildUnaryChain(only: TransformationPhase): TransformationChain {
return transformer => buildUnaryTransformation(buildPhase(only, transformer));
}
function buildUnaryTransformation(only: Transformation): Transformation {
return node => runStep(node, only);
}
function buildBinaryChain(first: TransformationPhase, second: TransformationPhase): TransformationChain {
return transformer => buildBinaryTransformation(buildPhase(first, transformer), buildPhase(second, transformer));
}
function buildBinaryTransformation(first: Transformation, second: Transformation): Transformation {
return node => runStep(runStep(node, first), second);
}
function buildTrinaryChain(first: TransformationPhase, second: TransformationPhase, third: TransformationPhase): TransformationChain {
return transformer => buildTrinaryTransformation(buildPhase(first, transformer), buildPhase(second, transformer), buildPhase(third, transformer));
}
function buildTrinaryTransformation(first: Transformation, second: Transformation, third: Transformation): Transformation {
return node => runStep(runStep(runStep(node, first), second), third);
}
function buildNaryChain(phases: TransformationPhase[]): TransformationChain {
return transformer => buildNaryTransformation(phases.map(phase => buildPhase(phase, transformer)));
}
function buildNaryTransformation(steps: Transformation[]): Transformation {
return node => steps.reduce(runStep, node);
}
}

View File

@ -1,15 +1,8 @@
/// <reference path="../checker.ts" />
/*@internal*/
namespace ts {
export function transformES6(node: SourceFile, transformer: Transformer): SourceFile {
if (node.transformFlags & TransformFlags.ContainsES6) {
return transformES6Worker(node, transformer);
}
return node;
}
function transformES6Worker(node: SourceFile, transformer: Transformer): SourceFile {
export function createES6Transformation(transformer: Transformer): Transformation {
// create local aliases for transformer methods
let {
startLexicalEnvironment,
endLexicalEnvironment,
@ -41,8 +34,24 @@ namespace ts {
let compilerOptions = transformer.getCompilerOptions();
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
let resolver = transformer.getEmitResolver();
let currentSourceFile = node;
return visitSourceFile(node, visitor);
let currentSourceFile: SourceFile;
return transformES6;
function transformES6(node: SourceFile): SourceFile {
if (node.transformFlags & TransformFlags.ContainsES6) {
return transformES6Worker(node);
}
return node;
}
function transformES6Worker(node: SourceFile): SourceFile {
currentSourceFile = node;
node = visitSourceFile(node, visitor);
currentSourceFile = undefined;
return node;
}
/**
* Transforms a node from ES6 to ES5 if it requires any transformations.

View File

@ -1,15 +1,7 @@
/// <reference path="../checker.ts" />
/*@internal*/
namespace ts {
export function transformJsx(node: SourceFile, transformer: Transformer): SourceFile {
if (node.transformFlags & TransformFlags.ContainsJsx) {
return transformJsxWorker(node, transformer);
}
return node;
}
function transformJsxWorker(node: SourceFile, transformer: Transformer): SourceFile {
export function createJsxTransformation(transformer: Transformer): Transformation {
// create local aliases for transformer methods
let {
tryPushNode,
@ -21,7 +13,19 @@ namespace ts {
accept,
} = transformer;
return visitSourceFile(node, visitor);
return transformJsx;
function transformJsx(node: SourceFile): SourceFile {
if (node.transformFlags & TransformFlags.ContainsJsx) {
return transformJsxWorker(node);
}
return node;
}
function transformJsxWorker(node: SourceFile): SourceFile {
return visitSourceFile(node, visitor);
}
function visitor(node: Node, write: (node: Node) => void): void {
if (node.transformFlags & TransformFlags.Jsx) {

View File

@ -1,15 +1,7 @@
/// <reference path="../checker.ts" />
/*@internal*/
namespace ts {
export function transformTypeScript(node: SourceFile, transformer: Transformer): SourceFile {
if (node.transformFlags & TransformFlags.ContainsTypeScript) {
return transformTypeScriptWorker(node, transformer);
}
return node;
}
function transformTypeScriptWorker(node: SourceFile, transformer: Transformer): SourceFile {
export function createTypeScriptTransformation(transformer: Transformer): Transformation {
// create local aliases for transformer methods
let {
startLexicalEnvironment,
@ -41,16 +33,41 @@ namespace ts {
let compilerOptions = transformer.getCompilerOptions();
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
let moduleKind = compilerOptions.module || ModuleKind.None;
let currentSourceFile = node;
let currentSourceFile: SourceFile;
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let exportFunctionForFile: string;
let savedSubstituteExpressionIdentifier = transformer.getExpressionIdentifierSubstitution(node);
transformer.setExpressionIdentifierSubstitution(node, substituteExpressionIdentifier);
let savedSubstituteExpressionIdentifier = transformer.getExpressionIdentifierSubstitution();
transformer.setExpressionIdentifierSubstitution(substituteExpressionIdentifier);
// Mark that we are about to visit a new lexical environment.
return visitSourceFile(node, visitor);
return transformTypeScript;
function transformTypeScript(node: SourceFile): SourceFile {
if (node.transformFlags & TransformFlags.ContainsTypeScript) {
return transformTypeScriptWorker(node);
}
return node;
}
function transformTypeScriptWorker(node: SourceFile): SourceFile {
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
exportFunctionForFile = undefined;
currentSourceFile = node;
node = visitSourceFile(node, visitor);
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
exportFunctionForFile = undefined;
currentSourceFile = undefined;
return node;
}
/**
* Transforms a node from TypeScript to ES6 if it requires any transformations.
@ -1019,7 +1036,7 @@ namespace ts {
return createPropertyAccessExpression2(getGeneratedNameForNode(container), node, node);
}
return savedSubstituteExpressionIdentifier(node);
return savedSubstituteExpressionIdentifier ? savedSubstituteExpressionIdentifier(node) : node;
}
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration, write: (node: Statement) => void): void {

View File

@ -2974,16 +2974,16 @@ namespace ts {
}
// @internal
export interface TransformationResolver {
getAssignmentSubstitution(sourceFile: SourceFile): (node: BinaryExpression) => Expression;
getExpressionIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => LeftHandSideExpression;
getBindingIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => Identifier;
export interface TransformationSubstitutions {
assignmentSubstitution: (node: BinaryExpression) => Expression;
expressionIdentifierSubstitution: (node: Identifier) => LeftHandSideExpression;
bindingIdentifierSubstitution: (node: Identifier) => Identifier;
}
// @internal
export interface TransformationResult {
sourceFiles: SourceFile[];
transformationResolver?: TransformationResolver;
substitutions?: TransformationSubstitutions;
}
// @internal
@ -3015,14 +3015,14 @@ namespace ts {
emitEmitHelpers(write: (node: Statement) => void): void;
emitExportStarHelper(write: (node: Statement) => void): void;
getAssignmentSubstitution(sourceFile: SourceFile): (node: BinaryExpression) => Expression;
setAssignmentSubstitution(sourceFile: SourceFile, substitution: (node: BinaryExpression) => Expression): void;
getAssignmentSubstitution(): (node: BinaryExpression) => Expression;
setAssignmentSubstitution(substitution: (node: BinaryExpression) => Expression): void;
getExpressionIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => LeftHandSideExpression;
setExpressionIdentifierSubstitution(sourceFile: SourceFile, substitution: (node: Identifier) => LeftHandSideExpression): void;
getExpressionIdentifierSubstitution(): (node: Identifier) => LeftHandSideExpression;
setExpressionIdentifierSubstitution(substitution: (node: Identifier) => LeftHandSideExpression): void;
getBindingIdentifierSubstitution(sourceFile: SourceFile): (node: Identifier) => Identifier;
setBindingIdentifierSubstitution(sourceFile: SourceFile, substitution: (node: Identifier) => Identifier): void;
getBindingIdentifierSubstitution(): (node: Identifier) => Identifier;
setBindingIdentifierSubstitution(substitution: (node: Identifier) => Identifier): void;
startLexicalEnvironment(): void;
endLexicalEnvironment(out: ((node: Statement) => void) | Statement[]): void;

View File

@ -363,6 +363,10 @@ namespace ts {
return (file.flags & NodeFlags.DeclarationFile) !== 0;
}
export function isNonDeclarationFile(file: SourceFile): boolean {
return (file.flags & NodeFlags.DeclarationFile) === 0;
}
export function isConstEnumDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
}