mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Merge pull request #5561 from Microsoft/oneEmitter
A few perf-related low hanging fruits
This commit is contained in:
@@ -785,7 +785,8 @@ namespace ts {
|
||||
};
|
||||
|
||||
export interface ObjectAllocator {
|
||||
getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node;
|
||||
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
|
||||
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
|
||||
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
|
||||
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
|
||||
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
|
||||
@@ -804,17 +805,17 @@ namespace ts {
|
||||
function Signature(checker: TypeChecker) {
|
||||
}
|
||||
|
||||
function Node(kind: SyntaxKind, pos: number, end: number) {
|
||||
this.kind = kind;
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
function Node(pos: number, end: number) {
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
Node.prototype = { kind };
|
||||
return <any>Node;
|
||||
},
|
||||
getNodeConstructor: () => <any>Node,
|
||||
getSourceFileConstructor: () => <any>Node,
|
||||
getSymbolConstructor: () => <any>Symbol,
|
||||
getTypeConstructor: () => <any>Type,
|
||||
getSignatureConstructor: () => <any>Signature
|
||||
|
||||
@@ -45,12 +45,15 @@ namespace ts {
|
||||
let writeLine: () => void;
|
||||
let increaseIndent: () => void;
|
||||
let decreaseIndent: () => void;
|
||||
let writeTextOfNode: (sourceFile: SourceFile, node: Node) => void;
|
||||
let writeTextOfNode: (text: string, node: Node) => void;
|
||||
|
||||
let writer = createAndSetNewTextWriterWithSymbolWriter();
|
||||
|
||||
let enclosingDeclaration: Node;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentLineMap: number[];
|
||||
let currentIdentifiers: Map<string>;
|
||||
let isCurrentFileExternalModule: boolean;
|
||||
let reportedDeclarationError = false;
|
||||
let errorNameNode: DeclarationName;
|
||||
const emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
|
||||
@@ -134,14 +137,13 @@ namespace ts {
|
||||
};
|
||||
|
||||
function hasInternalAnnotation(range: CommentRange) {
|
||||
const text = currentSourceFile.text;
|
||||
const comment = text.substring(range.pos, range.end);
|
||||
const comment = currentText.substring(range.pos, range.end);
|
||||
return comment.indexOf("@internal") >= 0;
|
||||
}
|
||||
|
||||
function stripInternal(node: Node) {
|
||||
if (node) {
|
||||
const leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos);
|
||||
const leadingCommentRanges = getLeadingCommentRanges(currentText, node.pos);
|
||||
if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
|
||||
return;
|
||||
}
|
||||
@@ -243,7 +245,7 @@ namespace ts {
|
||||
if (errorInfo.typeName) {
|
||||
diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
|
||||
errorInfo.diagnosticMessage,
|
||||
getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName),
|
||||
getTextOfNodeFromSourceText(currentText, errorInfo.typeName),
|
||||
symbolAccesibilityResult.errorSymbolName,
|
||||
symbolAccesibilityResult.errorModuleName));
|
||||
}
|
||||
@@ -321,10 +323,10 @@ namespace ts {
|
||||
|
||||
function writeJsDocComments(declaration: Node) {
|
||||
if (declaration) {
|
||||
const jsDocComments = getJsDocComments(declaration, currentSourceFile);
|
||||
emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
|
||||
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
|
||||
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
|
||||
emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +345,7 @@ namespace ts {
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return writeTextOfNode(currentSourceFile, type);
|
||||
return writeTextOfNode(currentText, type);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
|
||||
case SyntaxKind.TypeReference:
|
||||
@@ -375,14 +377,14 @@ namespace ts {
|
||||
|
||||
function writeEntityName(entityName: EntityName | Expression) {
|
||||
if (entityName.kind === SyntaxKind.Identifier) {
|
||||
writeTextOfNode(currentSourceFile, entityName);
|
||||
writeTextOfNode(currentText, entityName);
|
||||
}
|
||||
else {
|
||||
const left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
|
||||
const right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
|
||||
writeEntityName(left);
|
||||
write(".");
|
||||
writeTextOfNode(currentSourceFile, right);
|
||||
writeTextOfNode(currentText, right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +419,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTypePredicate(type: TypePredicateNode) {
|
||||
writeTextOfNode(currentSourceFile, type.parameterName);
|
||||
writeTextOfNode(currentText, type.parameterName);
|
||||
write(" is ");
|
||||
emitType(type.type);
|
||||
}
|
||||
@@ -466,9 +468,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitSourceFile(node: SourceFile) {
|
||||
currentSourceFile = node;
|
||||
currentText = node.text;
|
||||
currentLineMap = getLineStarts(node);
|
||||
currentIdentifiers = node.identifiers;
|
||||
isCurrentFileExternalModule = isExternalModule(node);
|
||||
enclosingDeclaration = node;
|
||||
emitDetachedComments(currentSourceFile, writer, writeCommentRange, node, newLine, true /* remove comments */);
|
||||
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, true /* remove comments */);
|
||||
emitLines(node.statements);
|
||||
}
|
||||
|
||||
@@ -478,13 +483,13 @@ namespace ts {
|
||||
// do not need to keep track of created temp names.
|
||||
function getExportDefaultTempVariableName(): string {
|
||||
const baseName = "_default";
|
||||
if (!hasProperty(currentSourceFile.identifiers, baseName)) {
|
||||
if (!hasProperty(currentIdentifiers, baseName)) {
|
||||
return baseName;
|
||||
}
|
||||
let count = 0;
|
||||
while (true) {
|
||||
const name = baseName + "_" + (++count);
|
||||
if (!hasProperty(currentSourceFile.identifiers, name)) {
|
||||
if (!hasProperty(currentIdentifiers, name)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -493,7 +498,7 @@ namespace ts {
|
||||
function emitExportAssignment(node: ExportAssignment) {
|
||||
if (node.expression.kind === SyntaxKind.Identifier) {
|
||||
write(node.isExportEquals ? "export = " : "export default ");
|
||||
writeTextOfNode(currentSourceFile, node.expression);
|
||||
writeTextOfNode(currentText, node.expression);
|
||||
}
|
||||
else {
|
||||
// Expression
|
||||
@@ -537,7 +542,7 @@ namespace ts {
|
||||
}
|
||||
// Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective
|
||||
else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
|
||||
(node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) {
|
||||
(node.parent.kind === SyntaxKind.SourceFile && isCurrentFileExternalModule)) {
|
||||
let isVisible: boolean;
|
||||
if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
|
||||
// Import declaration of another module that is visited async so lets put it in right spot
|
||||
@@ -593,7 +598,7 @@ namespace ts {
|
||||
|
||||
function emitModuleElementDeclarationFlags(node: Node) {
|
||||
// If the node is parented in the current source file we need to emit export declare or just export
|
||||
if (node.parent === currentSourceFile) {
|
||||
if (node.parent.kind === SyntaxKind.SourceFile) {
|
||||
// If the node is exported
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
write("export ");
|
||||
@@ -632,7 +637,7 @@ namespace ts {
|
||||
write("export ");
|
||||
}
|
||||
write("import ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
write(" = ");
|
||||
if (isInternalModuleImportEqualsDeclaration(node)) {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError);
|
||||
@@ -640,7 +645,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
write("require(");
|
||||
writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node));
|
||||
writeTextOfNode(currentText, getExternalModuleImportEqualsDeclarationExpression(node));
|
||||
write(");");
|
||||
}
|
||||
writer.writeLine();
|
||||
@@ -678,7 +683,7 @@ namespace ts {
|
||||
if (node.importClause) {
|
||||
const currentWriterPos = writer.getTextPos();
|
||||
if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
|
||||
writeTextOfNode(currentSourceFile, node.importClause.name);
|
||||
writeTextOfNode(currentText, node.importClause.name);
|
||||
}
|
||||
if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
|
||||
if (currentWriterPos !== writer.getTextPos()) {
|
||||
@@ -687,7 +692,7 @@ namespace ts {
|
||||
}
|
||||
if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
|
||||
write("* as ");
|
||||
writeTextOfNode(currentSourceFile, (<NamespaceImport>node.importClause.namedBindings).name);
|
||||
writeTextOfNode(currentText, (<NamespaceImport>node.importClause.namedBindings).name);
|
||||
}
|
||||
else {
|
||||
write("{ ");
|
||||
@@ -697,17 +702,17 @@ namespace ts {
|
||||
}
|
||||
write(" from ");
|
||||
}
|
||||
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
|
||||
writeTextOfNode(currentText, node.moduleSpecifier);
|
||||
write(";");
|
||||
writer.writeLine();
|
||||
}
|
||||
|
||||
function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) {
|
||||
if (node.propertyName) {
|
||||
writeTextOfNode(currentSourceFile, node.propertyName);
|
||||
writeTextOfNode(currentText, node.propertyName);
|
||||
write(" as ");
|
||||
}
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
}
|
||||
|
||||
function emitExportSpecifier(node: ExportSpecifier) {
|
||||
@@ -733,7 +738,7 @@ namespace ts {
|
||||
}
|
||||
if (node.moduleSpecifier) {
|
||||
write(" from ");
|
||||
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
|
||||
writeTextOfNode(currentText, node.moduleSpecifier);
|
||||
}
|
||||
write(";");
|
||||
writer.writeLine();
|
||||
@@ -748,11 +753,11 @@ namespace ts {
|
||||
else {
|
||||
write("module ");
|
||||
}
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
while (node.body.kind !== SyntaxKind.ModuleBlock) {
|
||||
node = <ModuleDeclaration>node.body;
|
||||
write(".");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
}
|
||||
const prevEnclosingDeclaration = enclosingDeclaration;
|
||||
enclosingDeclaration = node;
|
||||
@@ -772,7 +777,7 @@ namespace ts {
|
||||
emitJsDocComments(node);
|
||||
emitModuleElementDeclarationFlags(node);
|
||||
write("type ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
emitTypeParameters(node.typeParameters);
|
||||
write(" = ");
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
|
||||
@@ -796,7 +801,7 @@ namespace ts {
|
||||
write("const ");
|
||||
}
|
||||
write("enum ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
write(" {");
|
||||
writeLine();
|
||||
increaseIndent();
|
||||
@@ -808,7 +813,7 @@ namespace ts {
|
||||
|
||||
function emitEnumMemberDeclaration(node: EnumMember) {
|
||||
emitJsDocComments(node);
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
const enumMemberValue = resolver.getConstantValue(node);
|
||||
if (enumMemberValue !== undefined) {
|
||||
write(" = ");
|
||||
@@ -827,7 +832,7 @@ namespace ts {
|
||||
increaseIndent();
|
||||
emitJsDocComments(node);
|
||||
decreaseIndent();
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
// If there is constraint present and this is not a type parameter of the private method emit the constraint
|
||||
if (node.constraint && !isPrivateMethodTypeParameter(node)) {
|
||||
write(" extends ");
|
||||
@@ -958,7 +963,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
write("class ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
const prevEnclosingDeclaration = enclosingDeclaration;
|
||||
enclosingDeclaration = node;
|
||||
emitTypeParameters(node.typeParameters);
|
||||
@@ -982,7 +987,7 @@ namespace ts {
|
||||
emitJsDocComments(node);
|
||||
emitModuleElementDeclarationFlags(node);
|
||||
write("interface ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
const prevEnclosingDeclaration = enclosingDeclaration;
|
||||
enclosingDeclaration = node;
|
||||
emitTypeParameters(node.typeParameters);
|
||||
@@ -1020,7 +1025,7 @@ namespace ts {
|
||||
// If this node is a computed name, it can only be a symbol, because we've already skipped
|
||||
// it if it's not a well known symbol. In that case, the text of the name will be exactly
|
||||
// what we want, namely the name expression enclosed in brackets.
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
// If optional property emit ?
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
|
||||
write("?");
|
||||
@@ -1107,7 +1112,7 @@ namespace ts {
|
||||
emitBindingPattern(<BindingPattern>bindingElement.name);
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, bindingElement.name);
|
||||
writeTextOfNode(currentText, bindingElement.name);
|
||||
writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError);
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1162,7 @@ namespace ts {
|
||||
emitJsDocComments(accessors.getAccessor);
|
||||
emitJsDocComments(accessors.setAccessor);
|
||||
emitClassMemberDeclarationFlags(node);
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
if (!(node.flags & NodeFlags.Private)) {
|
||||
accessorWithTypeAnnotation = node;
|
||||
let type = getTypeAnnotationFromAccessor(node);
|
||||
@@ -1247,13 +1252,13 @@ namespace ts {
|
||||
}
|
||||
if (node.kind === SyntaxKind.FunctionDeclaration) {
|
||||
write("function ");
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.Constructor) {
|
||||
write("constructor");
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
if (hasQuestionToken(node)) {
|
||||
write("?");
|
||||
}
|
||||
@@ -1393,7 +1398,7 @@ namespace ts {
|
||||
emitBindingPattern(<BindingPattern>node.name);
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
}
|
||||
if (resolver.isOptionalParameter(node)) {
|
||||
write("?");
|
||||
@@ -1519,7 +1524,7 @@ namespace ts {
|
||||
// Example:
|
||||
// original: function foo({y: [a,b,c]}) {}
|
||||
// emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
|
||||
writeTextOfNode(currentSourceFile, bindingElement.propertyName);
|
||||
writeTextOfNode(currentText, bindingElement.propertyName);
|
||||
write(": ");
|
||||
}
|
||||
if (bindingElement.name) {
|
||||
@@ -1542,7 +1547,7 @@ namespace ts {
|
||||
if (bindingElement.dotDotDotToken) {
|
||||
write("...");
|
||||
}
|
||||
writeTextOfNode(currentSourceFile, bindingElement.name);
|
||||
writeTextOfNode(currentText, bindingElement.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +333,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
const jsxDesugaring = host.getCompilerOptions().jsx !== JsxEmit.Preserve;
|
||||
const shouldEmitJsx = (s: SourceFile) => (s.languageVariant === LanguageVariant.JSX && !jsxDesugaring);
|
||||
|
||||
const emitJavaScript = createFileEmitter();
|
||||
|
||||
if (targetSourceFile === undefined) {
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
|
||||
@@ -470,11 +472,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
|
||||
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
|
||||
const writer = createTextWriter(newLine);
|
||||
function createFileEmitter(): (jsFilePath: string, root?: SourceFile) => void {
|
||||
const writer: EmitTextWriter = createTextWriter(newLine);
|
||||
const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
|
||||
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentLineMap: number[];
|
||||
let currentFileIdentifiers: Map<string>;
|
||||
let renamedDependencies: Map<string>;
|
||||
let isEs6Module: boolean;
|
||||
let isCurrentFileExternalModule: boolean;
|
||||
|
||||
// name of an exporter function if file is a System external module
|
||||
// System.register([...], function (<exporter>) {...})
|
||||
// exporting in System modules looks like:
|
||||
@@ -483,17 +492,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// var x;... exporter("x", x = 1)
|
||||
let exportFunctionForFile: string;
|
||||
|
||||
const generatedNameSet: Map<string> = {};
|
||||
const nodeToGeneratedName: string[] = [];
|
||||
let generatedNameSet: Map<string>;
|
||||
let nodeToGeneratedName: string[];
|
||||
let computedPropertyNamesToGeneratedNames: string[];
|
||||
|
||||
let convertedLoopState: ConvertedLoopState;
|
||||
|
||||
let extendsEmitted = false;
|
||||
let decorateEmitted = false;
|
||||
let paramEmitted = false;
|
||||
let awaiterEmitted = false;
|
||||
let tempFlags = 0;
|
||||
let extendsEmitted: boolean;
|
||||
let decorateEmitted: boolean;
|
||||
let paramEmitted: boolean;
|
||||
let awaiterEmitted: boolean;
|
||||
let tempFlags: TempFlags;
|
||||
let tempVariables: Identifier[];
|
||||
let tempParameters: Identifier[];
|
||||
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
|
||||
@@ -547,35 +556,74 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
[ModuleKind.CommonJS]: emitCommonJSModule,
|
||||
};
|
||||
|
||||
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
|
||||
initializeEmitterWithSourceMaps();
|
||||
}
|
||||
return doEmit;
|
||||
|
||||
if (root) {
|
||||
// Do not call emit directly. It does not set the currentSourceFile.
|
||||
emitSourceFile(root);
|
||||
}
|
||||
else {
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
|
||||
emitSourceFile(sourceFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
function doEmit(jsFilePath: string, root?: SourceFile) {
|
||||
// reset the state
|
||||
writer.reset();
|
||||
currentSourceFile = undefined;
|
||||
currentText = undefined;
|
||||
currentLineMap = undefined;
|
||||
exportFunctionForFile = undefined;
|
||||
generatedNameSet = {};
|
||||
nodeToGeneratedName = [];
|
||||
computedPropertyNamesToGeneratedNames = undefined;
|
||||
convertedLoopState = undefined;
|
||||
|
||||
writeLine();
|
||||
writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM);
|
||||
return;
|
||||
extendsEmitted = false;
|
||||
decorateEmitted = false;
|
||||
paramEmitted = false;
|
||||
awaiterEmitted = false;
|
||||
tempFlags = 0;
|
||||
tempVariables = undefined;
|
||||
tempParameters = undefined;
|
||||
externalImports = undefined;
|
||||
exportSpecifiers = undefined;
|
||||
exportEquals = undefined;
|
||||
hasExportStars = undefined;
|
||||
detachedCommentsInfo = undefined;
|
||||
sourceMapData = undefined;
|
||||
isEs6Module = false;
|
||||
renamedDependencies = undefined;
|
||||
isCurrentFileExternalModule = false;
|
||||
|
||||
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
|
||||
initializeEmitterWithSourceMaps(jsFilePath, root);
|
||||
}
|
||||
|
||||
if (root) {
|
||||
// Do not call emit directly. It does not set the currentSourceFile.
|
||||
emitSourceFile(root);
|
||||
}
|
||||
else {
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
|
||||
emitSourceFile(sourceFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
writeLine();
|
||||
writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM);
|
||||
}
|
||||
|
||||
function emitSourceFile(sourceFile: SourceFile): void {
|
||||
currentSourceFile = sourceFile;
|
||||
|
||||
currentText = sourceFile.text;
|
||||
currentLineMap = getLineStarts(sourceFile);
|
||||
exportFunctionForFile = undefined;
|
||||
isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"];
|
||||
renamedDependencies = sourceFile.renamedDependencies;
|
||||
currentFileIdentifiers = sourceFile.identifiers;
|
||||
isCurrentFileExternalModule = isExternalModule(sourceFile);
|
||||
|
||||
emit(sourceFile);
|
||||
}
|
||||
|
||||
function isUniqueName(name: string): boolean {
|
||||
return !resolver.hasGlobalName(name) &&
|
||||
!hasProperty(currentSourceFile.identifiers, name) &&
|
||||
!hasProperty(currentFileIdentifiers, name) &&
|
||||
!hasProperty(generatedNameSet, name);
|
||||
}
|
||||
|
||||
@@ -667,7 +715,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node)));
|
||||
}
|
||||
|
||||
function initializeEmitterWithSourceMaps() {
|
||||
function initializeEmitterWithSourceMaps(jsFilePath: string, root?: SourceFile) {
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
@@ -771,7 +819,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function recordSourceMapSpan(pos: number) {
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
const sourceLinePos = computeLineAndCharacterOfPosition(currentLineMap, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
@@ -810,7 +858,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
|
||||
function recordEmitNodeStartSpan(node: Node) {
|
||||
// Get the token pos after skipping to the token (ignoring the leading trivia)
|
||||
recordSourceMapSpan(skipTrivia(currentSourceFile.text, node.pos));
|
||||
recordSourceMapSpan(skipTrivia(currentText, node.pos));
|
||||
}
|
||||
|
||||
function recordEmitNodeEndSpan(node: Node) {
|
||||
@@ -818,7 +866,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
|
||||
const tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
|
||||
const tokenStartPos = ts.skipTrivia(currentText, startPos);
|
||||
recordSourceMapSpan(tokenStartPos);
|
||||
const tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
|
||||
recordSourceMapSpan(tokenEndPos);
|
||||
@@ -912,9 +960,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
sourceMapNameIndices.pop();
|
||||
};
|
||||
|
||||
function writeCommentRangeWithMap(curentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
|
||||
function writeCommentRangeWithMap(currentText: string, currentLineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
|
||||
recordSourceMapSpan(comment.pos);
|
||||
writeCommentRange(currentSourceFile, writer, comment, newLine);
|
||||
writeCommentRange(currentText, currentLineMap, writer, comment, newLine);
|
||||
recordSourceMapSpan(comment.end);
|
||||
}
|
||||
|
||||
@@ -950,7 +998,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
|
||||
function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
|
||||
function writeJavaScriptAndSourceMapFile(emitOutput: string, jsFilePath: string, writeByteOrderMark: boolean) {
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
const sourceMapText = serializeSourceMapContents(
|
||||
@@ -977,7 +1025,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
// Write sourcemap url to the js file and write the js file
|
||||
writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark);
|
||||
writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark);
|
||||
}
|
||||
|
||||
// Initialize source map data
|
||||
@@ -1059,7 +1107,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
writeComment = writeCommentRangeWithMap;
|
||||
}
|
||||
|
||||
function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) {
|
||||
function writeJavaScriptFile(emitOutput: string, jsFilePath: string, writeByteOrderMark: boolean) {
|
||||
writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
|
||||
}
|
||||
|
||||
@@ -1269,7 +1317,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// If we don't need to downlevel and we can reach the original source text using
|
||||
// the node's parent reference, then simply get the text as it was originally written.
|
||||
if (node.parent) {
|
||||
return getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
|
||||
return getTextOfNodeFromSourceText(currentText, node);
|
||||
}
|
||||
|
||||
// If we can't reach the original source text, use the canonical form if it's a number,
|
||||
@@ -1300,7 +1348,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// Find original source text, since we need to emit the raw strings of the tagged template.
|
||||
// The raw strings contain the (escaped) strings of what the user wrote.
|
||||
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
|
||||
let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
|
||||
let text = getTextOfNodeFromSourceText(currentText, node);
|
||||
|
||||
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
|
||||
// thus we need to remove those characters.
|
||||
@@ -1772,7 +1820,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write((<LiteralExpression>node).text);
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, node);
|
||||
writeTextOfNode(currentText, node);
|
||||
}
|
||||
|
||||
write("\"");
|
||||
@@ -1876,7 +1924,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// Identifier references named import
|
||||
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent.parent.parent));
|
||||
const name = (<ImportSpecifier>declaration).propertyName || (<ImportSpecifier>declaration).name;
|
||||
const identifier = getSourceTextOfNodeFromSourceFile(currentSourceFile, name);
|
||||
const identifier = getTextOfNodeFromSourceText(currentText, name);
|
||||
if (languageVersion === ScriptTarget.ES3 && identifier === "default") {
|
||||
write(`["default"]`);
|
||||
}
|
||||
@@ -1902,7 +1950,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write(node.text);
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, node);
|
||||
writeTextOfNode(currentText, node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1943,7 +1991,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write(node.text);
|
||||
}
|
||||
else {
|
||||
writeTextOfNode(currentSourceFile, node);
|
||||
writeTextOfNode(currentText, node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2403,7 +2451,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
|
||||
// The name property of a short-hand property assignment is considered an expression position, so here
|
||||
// we manually emit the identifier to avoid rewriting.
|
||||
writeTextOfNode(currentSourceFile, node.name);
|
||||
writeTextOfNode(currentText, node.name);
|
||||
// If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier,
|
||||
// we emit a normal property assignment. For example:
|
||||
// module m {
|
||||
@@ -2480,11 +2528,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
|
||||
// 1 .toString is a valid property access, emit a space after the literal
|
||||
// Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal
|
||||
let shouldEmitSpace: boolean;
|
||||
let shouldEmitSpace = false;
|
||||
if (!indentedBeforeDot) {
|
||||
if (node.expression.kind === SyntaxKind.NumericLiteral) {
|
||||
// check if numeric literal was originally written with a dot
|
||||
const text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression);
|
||||
const text = getTextOfNodeFromSourceText(currentText, node.expression);
|
||||
shouldEmitSpace = text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
|
||||
}
|
||||
else {
|
||||
@@ -3815,18 +3863,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function nodeStartPositionsAreOnSameLine(node1: Node, node2: Node) {
|
||||
return getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node1.pos)) ===
|
||||
getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
|
||||
return getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node1.pos)) ===
|
||||
getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos));
|
||||
}
|
||||
|
||||
function nodeEndPositionsAreOnSameLine(node1: Node, node2: Node) {
|
||||
return getLineOfLocalPosition(currentSourceFile, node1.end) ===
|
||||
getLineOfLocalPosition(currentSourceFile, node2.end);
|
||||
return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) ===
|
||||
getLineOfLocalPositionFromLineMap(currentLineMap, node2.end);
|
||||
}
|
||||
|
||||
function nodeEndIsOnSameLineAsNodeStart(node1: Node, node2: Node) {
|
||||
return getLineOfLocalPosition(currentSourceFile, node1.end) ===
|
||||
getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
|
||||
return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) ===
|
||||
getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos));
|
||||
}
|
||||
|
||||
function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
|
||||
@@ -3948,7 +3996,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
Debug.assert(!!(node.flags & NodeFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
|
||||
// only allow export default at a source file level
|
||||
if (modulekind === ModuleKind.CommonJS || modulekind === ModuleKind.AMD || modulekind === ModuleKind.UMD) {
|
||||
if (!currentSourceFile.symbol.exports["___esModule"]) {
|
||||
if (!isEs6Module) {
|
||||
if (languageVersion === ScriptTarget.ES5) {
|
||||
// default value of configurable, enumerable, writable are `false`.
|
||||
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
|
||||
@@ -6304,8 +6352,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
* Here we check if alternative name was provided for a given moduleName and return it if possible.
|
||||
*/
|
||||
function tryRenameExternalModule(moduleName: LiteralExpression): string {
|
||||
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
|
||||
return `"${currentSourceFile.renamedDependencies[moduleName.text]}"`;
|
||||
if (renamedDependencies && hasProperty(renamedDependencies, moduleName.text)) {
|
||||
return `"${renamedDependencies[moduleName.text]}"`;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -6467,7 +6515,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// - current file is not external module
|
||||
// - import declaration is top level and target is value imported by entity name
|
||||
if (resolver.isReferencedAliasDeclaration(node) ||
|
||||
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
|
||||
(!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
|
||||
emitLeadingComments(node);
|
||||
emitStart(node);
|
||||
|
||||
@@ -6708,7 +6756,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
|
||||
const namespaceDeclaration = getNamespaceDeclarationNode(node);
|
||||
if (namespaceDeclaration && !isDefaultImport(node)) {
|
||||
return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
|
||||
return getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name);
|
||||
}
|
||||
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
|
||||
return getGeneratedNameForNode(node);
|
||||
@@ -7064,7 +7112,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function isCurrentFileSystemExternalModule() {
|
||||
return modulekind === ModuleKind.System && isExternalModule(currentSourceFile);
|
||||
return modulekind === ModuleKind.System && isCurrentFileExternalModule;
|
||||
}
|
||||
|
||||
function emitSystemModuleBody(node: SourceFile, dependencyGroups: DependencyGroup[], startIndex: number): void {
|
||||
@@ -7927,7 +7975,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
|
||||
function getLeadingCommentsWithoutDetachedComments() {
|
||||
// get the leading comments from detachedPos
|
||||
const leadingComments = getLeadingCommentRanges(currentSourceFile.text,
|
||||
const leadingComments = getLeadingCommentRanges(currentText,
|
||||
lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos);
|
||||
if (detachedCommentsInfo.length - 1) {
|
||||
detachedCommentsInfo.pop();
|
||||
@@ -7947,10 +7995,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function isTripleSlashComment(comment: CommentRange) {
|
||||
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
|
||||
// so that we don't end up computing comment string and doing match for all // comments
|
||||
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
|
||||
if (currentText.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
|
||||
comment.pos + 2 < comment.end &&
|
||||
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
|
||||
const textSubStr = currentSourceFile.text.substring(comment.pos, comment.end);
|
||||
currentText.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
|
||||
const textSubStr = currentText.substring(comment.pos, comment.end);
|
||||
return textSubStr.match(fullTripleSlashReferencePathRegEx) ||
|
||||
textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ?
|
||||
true : false;
|
||||
@@ -7968,7 +8016,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
else {
|
||||
// get the leading comments from the node
|
||||
return getLeadingCommentRangesOfNode(node, currentSourceFile);
|
||||
return getLeadingCommentRangesOfNodeFromText(node, currentText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7978,7 +8026,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments
|
||||
if (node.parent) {
|
||||
if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
|
||||
return getTrailingCommentRanges(currentSourceFile.text, node.end);
|
||||
return getTrailingCommentRanges(currentText, node.end);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8017,10 +8065,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
|
||||
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingComments(node: Node) {
|
||||
@@ -8032,7 +8080,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
const trailingComments = getTrailingCommentsToEmit(node);
|
||||
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8045,10 +8093,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
return;
|
||||
}
|
||||
|
||||
const trailingComments = getTrailingCommentRanges(currentSourceFile.text, pos);
|
||||
const trailingComments = getTrailingCommentRanges(currentText, pos);
|
||||
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitLeadingCommentsOfPositionWorker(pos: number) {
|
||||
@@ -8063,17 +8111,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
else {
|
||||
// get the leading comments from the node
|
||||
leadingComments = getLeadingCommentRanges(currentSourceFile.text, pos);
|
||||
leadingComments = getLeadingCommentRanges(currentText, pos);
|
||||
}
|
||||
|
||||
emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange) {
|
||||
const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments);
|
||||
const currentDetachedCommentInfo = emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments);
|
||||
|
||||
if (currentDetachedCommentInfo) {
|
||||
if (detachedCommentsInfo) {
|
||||
@@ -8086,7 +8134,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function emitShebang() {
|
||||
const shebang = getShebang(currentSourceFile.text);
|
||||
const shebang = getShebang(currentText);
|
||||
if (shebang) {
|
||||
write(shebang);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
/// <reference path="utilities.ts"/>
|
||||
|
||||
namespace ts {
|
||||
const nodeConstructors = new Array<new (pos: number, end: number) => Node>(SyntaxKind.Count);
|
||||
/* @internal */ export let parseTime = 0;
|
||||
|
||||
export function getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node {
|
||||
return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
|
||||
}
|
||||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
|
||||
return new (getNodeConstructor(kind))(pos, end);
|
||||
if (kind === SyntaxKind.SourceFile) {
|
||||
return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
|
||||
}
|
||||
else {
|
||||
return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
|
||||
}
|
||||
}
|
||||
|
||||
function visitNode<T>(cbNode: (node: Node) => T, node: Node): T {
|
||||
@@ -437,6 +440,10 @@ namespace ts {
|
||||
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
|
||||
const disallowInAndDecoratorContext = ParserContextFlags.DisallowIn | ParserContextFlags.Decorator;
|
||||
|
||||
// capture constructors in 'initializeState' to avoid null checks
|
||||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
let sourceFile: SourceFile;
|
||||
let parseDiagnostics: Diagnostic[];
|
||||
let syntaxCursor: IncrementalParser.SyntaxCursor;
|
||||
@@ -537,6 +544,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor) {
|
||||
NodeConstructor = objectAllocator.getNodeConstructor();
|
||||
SourceFileConstructor = objectAllocator.getSourceFileConstructor();
|
||||
|
||||
sourceText = _sourceText;
|
||||
syntaxCursor = _syntaxCursor;
|
||||
|
||||
@@ -657,10 +667,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSourceFile(fileName: string, languageVersion: ScriptTarget): SourceFile {
|
||||
const sourceFile = <SourceFile>createNode(SyntaxKind.SourceFile, /*pos*/ 0);
|
||||
// code from createNode is inlined here so createNode won't have to deal with special case of creating source files
|
||||
// this is quite rare comparing to other nodes and createNode should be as fast as possible
|
||||
const sourceFile = <SourceFile>new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length);
|
||||
nodeCount++;
|
||||
|
||||
sourceFile.pos = 0;
|
||||
sourceFile.end = sourceText.length;
|
||||
sourceFile.text = sourceText;
|
||||
sourceFile.bindDiagnostics = [];
|
||||
sourceFile.languageVersion = languageVersion;
|
||||
@@ -671,7 +682,7 @@ namespace ts {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
function setContextFlag(val: Boolean, flag: ParserContextFlags) {
|
||||
function setContextFlag(val: boolean, flag: ParserContextFlags) {
|
||||
if (val) {
|
||||
contextFlags |= flag;
|
||||
}
|
||||
@@ -991,12 +1002,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// note: this function creates only node
|
||||
function createNode(kind: SyntaxKind, pos?: number): Node {
|
||||
nodeCount++;
|
||||
if (!(pos >= 0)) {
|
||||
pos = scanner.getStartPos();
|
||||
}
|
||||
return new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(pos, pos);
|
||||
|
||||
return new NodeConstructor(kind, pos, pos);
|
||||
}
|
||||
|
||||
function finishNode<T extends Node>(node: T, end?: number): T {
|
||||
|
||||
@@ -580,7 +580,7 @@ namespace ts {
|
||||
function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
|
||||
let result: CommentRange[];
|
||||
let collecting = trailing || pos === 0;
|
||||
while (true) {
|
||||
while (pos < text.length) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
switch (ch) {
|
||||
case CharacterCodes.carriageReturn:
|
||||
@@ -650,6 +650,8 @@ namespace ts {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
|
||||
@@ -741,7 +743,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function scanNumber(): number {
|
||||
function scanNumber(): string {
|
||||
const start = pos;
|
||||
while (isDigit(text.charCodeAt(pos))) pos++;
|
||||
if (text.charCodeAt(pos) === CharacterCodes.dot) {
|
||||
@@ -761,7 +763,7 @@ namespace ts {
|
||||
error(Diagnostics.Digit_expected);
|
||||
}
|
||||
}
|
||||
return +(text.substring(start, end));
|
||||
return "" + +(text.substring(start, end));
|
||||
}
|
||||
|
||||
function scanOctalDigits(): number {
|
||||
@@ -1229,7 +1231,7 @@ namespace ts {
|
||||
return pos++, token = SyntaxKind.MinusToken;
|
||||
case CharacterCodes.dot:
|
||||
if (isDigit(text.charCodeAt(pos + 1))) {
|
||||
tokenValue = "" + scanNumber();
|
||||
tokenValue = scanNumber();
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
}
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
|
||||
@@ -1343,7 +1345,7 @@ namespace ts {
|
||||
case CharacterCodes._7:
|
||||
case CharacterCodes._8:
|
||||
case CharacterCodes._9:
|
||||
tokenValue = "" + scanNumber();
|
||||
tokenValue = scanNumber();
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
case CharacterCodes.colon:
|
||||
return pos++, token = SyntaxKind.ColonToken;
|
||||
|
||||
@@ -421,18 +421,26 @@ namespace ts {
|
||||
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
|
||||
}
|
||||
|
||||
export function getLeadingCommentRangesOfNodeFromText(node: Node, text: string) {
|
||||
return getLeadingCommentRanges(text, node.pos);
|
||||
}
|
||||
|
||||
export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
|
||||
return getJsDocCommentsFromText(node, sourceFileOfNode.text);
|
||||
}
|
||||
|
||||
export function getJsDocCommentsFromText(node: Node, text: string) {
|
||||
const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ?
|
||||
concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
|
||||
getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) :
|
||||
getLeadingCommentRangesOfNode(node, sourceFileOfNode);
|
||||
concatenate(getTrailingCommentRanges(text, node.pos),
|
||||
getLeadingCommentRanges(text, node.pos)) :
|
||||
getLeadingCommentRangesOfNodeFromText(node, text);
|
||||
return filter(commentRanges, isJsDocComment);
|
||||
|
||||
function isJsDocComment(comment: CommentRange) {
|
||||
// True if the comment starts with '/**' but not if it is '/**/'
|
||||
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
|
||||
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
|
||||
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
|
||||
return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
|
||||
text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
|
||||
text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1383,8 +1391,8 @@ namespace ts {
|
||||
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
|
||||
const simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
|
||||
const isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
|
||||
if (simpleReferenceRegEx.exec(comment)) {
|
||||
if (isNoDefaultLibRegEx.exec(comment)) {
|
||||
if (simpleReferenceRegEx.test(comment)) {
|
||||
if (isNoDefaultLibRegEx.test(comment)) {
|
||||
return {
|
||||
isNoDefaultLib: true
|
||||
};
|
||||
@@ -1689,7 +1697,7 @@ namespace ts {
|
||||
|
||||
export interface EmitTextWriter {
|
||||
write(s: string): void;
|
||||
writeTextOfNode(sourceFile: SourceFile, node: Node): void;
|
||||
writeTextOfNode(text: string, node: Node): void;
|
||||
writeLine(): void;
|
||||
increaseIndent(): void;
|
||||
decreaseIndent(): void;
|
||||
@@ -1700,6 +1708,7 @@ namespace ts {
|
||||
getLine(): number;
|
||||
getColumn(): number;
|
||||
getIndent(): number;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
const indentStrings: string[] = ["", " "];
|
||||
@@ -1715,11 +1724,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createTextWriter(newLine: String): EmitTextWriter {
|
||||
let output = "";
|
||||
let indent = 0;
|
||||
let lineStart = true;
|
||||
let lineCount = 0;
|
||||
let linePos = 0;
|
||||
let output: string;
|
||||
let indent: number;
|
||||
let lineStart: boolean;
|
||||
let lineCount: number;
|
||||
let linePos: number;
|
||||
|
||||
function write(s: string) {
|
||||
if (s && s.length) {
|
||||
@@ -1731,6 +1740,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function reset(): void {
|
||||
output = "";
|
||||
indent = 0;
|
||||
lineStart = true;
|
||||
lineCount = 0;
|
||||
linePos = 0;
|
||||
}
|
||||
|
||||
function rawWrite(s: string) {
|
||||
if (s !== undefined) {
|
||||
if (lineStart) {
|
||||
@@ -1760,10 +1777,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeTextOfNode(sourceFile: SourceFile, node: Node) {
|
||||
write(getSourceTextOfNodeFromSourceFile(sourceFile, node));
|
||||
function writeTextOfNode(text: string, node: Node) {
|
||||
write(getTextOfNodeFromSourceText(text, node));
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
return {
|
||||
write,
|
||||
rawWrite,
|
||||
@@ -1777,6 +1796,7 @@ namespace ts {
|
||||
getLine: () => lineCount + 1,
|
||||
getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
|
||||
getText: () => output,
|
||||
reset
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1809,6 +1829,10 @@ namespace ts {
|
||||
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
|
||||
}
|
||||
|
||||
export function getLineOfLocalPositionFromLineMap(lineMap: number[], pos: number) {
|
||||
return computeLineAndCharacterOfPosition(lineMap, pos).line;
|
||||
}
|
||||
|
||||
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
|
||||
return forEach(node.members, member => {
|
||||
if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) {
|
||||
@@ -1883,23 +1907,23 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function emitNewLineBeforeLeadingComments(currentSourceFile: SourceFile, writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
|
||||
export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
|
||||
// If the leading comments start on different line than the start of node, write new line
|
||||
if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
|
||||
getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
|
||||
getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
export function emitComments(currentSourceFile: SourceFile, writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
|
||||
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
|
||||
export function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
|
||||
writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
|
||||
let emitLeadingSpace = !trailingSeparator;
|
||||
forEach(comments, comment => {
|
||||
if (emitLeadingSpace) {
|
||||
writer.write(" ");
|
||||
emitLeadingSpace = false;
|
||||
}
|
||||
writeComment(currentSourceFile, writer, comment, newLine);
|
||||
writeComment(text, lineMap, writer, comment, newLine);
|
||||
if (comment.hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1917,8 +1941,8 @@ namespace ts {
|
||||
* Detached comment is a comment at the top of file or function body that is separated from
|
||||
* the next statement by space.
|
||||
*/
|
||||
export function emitDetachedComments(currentSourceFile: SourceFile, writer: EmitTextWriter,
|
||||
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void,
|
||||
export function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter,
|
||||
writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void,
|
||||
node: TextRange, newLine: string, removeComments: boolean) {
|
||||
let leadingComments: CommentRange[];
|
||||
let currentDetachedCommentInfo: {nodePos: number, detachedCommentEndPos: number};
|
||||
@@ -1929,12 +1953,12 @@ namespace ts {
|
||||
//
|
||||
// var x = 10;
|
||||
if (node.pos === 0) {
|
||||
leadingComments = filter(getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment);
|
||||
leadingComments = filter(getLeadingCommentRanges(text, node.pos), isPinnedComment);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// removeComments is false, just get detached as normal and bypass the process to filter comment
|
||||
leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos);
|
||||
leadingComments = getLeadingCommentRanges(text, node.pos);
|
||||
}
|
||||
|
||||
if (leadingComments) {
|
||||
@@ -1943,8 +1967,8 @@ namespace ts {
|
||||
|
||||
for (const comment of leadingComments) {
|
||||
if (lastComment) {
|
||||
const lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end);
|
||||
const commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos);
|
||||
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end);
|
||||
const commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos);
|
||||
|
||||
if (commentLine >= lastCommentLine + 2) {
|
||||
// There was a blank line between the last comment and this comment. This
|
||||
@@ -1962,12 +1986,12 @@ namespace ts {
|
||||
// All comments look like they could have been part of the copyright header. Make
|
||||
// sure there is at least one blank line between it and the node. If not, it's not
|
||||
// a copyright header.
|
||||
const lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastOrUndefined(detachedComments).end);
|
||||
const nodeLine = getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node.pos));
|
||||
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastOrUndefined(detachedComments).end);
|
||||
const nodeLine = getLineOfLocalPositionFromLineMap(lineMap, skipTrivia(text, node.pos));
|
||||
if (nodeLine >= lastCommentLine + 2) {
|
||||
// Valid detachedComments
|
||||
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
|
||||
emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments);
|
||||
emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end };
|
||||
}
|
||||
}
|
||||
@@ -1976,25 +2000,26 @@ namespace ts {
|
||||
return currentDetachedCommentInfo;
|
||||
|
||||
function isPinnedComment(comment: CommentRange) {
|
||||
return currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
|
||||
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
|
||||
return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
|
||||
text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function writeCommentRange(currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
|
||||
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
|
||||
const firstCommentLineAndCharacter = getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
|
||||
const lineCount = getLineStarts(currentSourceFile).length;
|
||||
export function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
|
||||
if (text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
|
||||
const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, comment.pos);
|
||||
const lineCount = lineMap.length;
|
||||
let firstCommentLineIndent: number;
|
||||
for (let pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
|
||||
const nextLineStart = (currentLine + 1) === lineCount
|
||||
? currentSourceFile.text.length + 1
|
||||
: getStartPositionOfLine(currentLine + 1, currentSourceFile);
|
||||
? text.length + 1
|
||||
: lineMap[currentLine + 1];
|
||||
|
||||
if (pos !== comment.pos) {
|
||||
// If we are not emitting first line, we need to write the spaces to adjust the alignment
|
||||
if (firstCommentLineIndent === undefined) {
|
||||
firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
|
||||
firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos);
|
||||
}
|
||||
|
||||
// These are number of spaces writer is going to write at current indent
|
||||
@@ -2014,7 +2039,7 @@ namespace ts {
|
||||
// More right indented comment */ --4 = 8 - 4 + 11
|
||||
// class c { }
|
||||
// }
|
||||
const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
|
||||
const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart);
|
||||
if (spacesToEmit > 0) {
|
||||
let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
|
||||
const indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
|
||||
@@ -2035,47 +2060,47 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Write the comment line text
|
||||
writeTrimmedCurrentLine(pos, nextLineStart);
|
||||
writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart);
|
||||
|
||||
pos = nextLineStart;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Single line comment of style //....
|
||||
writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
|
||||
writer.write(text.substring(comment.pos, comment.end));
|
||||
}
|
||||
}
|
||||
|
||||
function writeTrimmedCurrentLine(pos: number, nextLineStart: number) {
|
||||
const end = Math.min(comment.end, nextLineStart - 1);
|
||||
const currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, "");
|
||||
if (currentLineText) {
|
||||
// trimmed forward and ending spaces text
|
||||
writer.write(currentLineText);
|
||||
if (end !== comment.end) {
|
||||
writer.writeLine();
|
||||
}
|
||||
function writeTrimmedCurrentLine(text: string, comment: CommentRange, writer: EmitTextWriter, newLine: string, pos: number, nextLineStart: number) {
|
||||
const end = Math.min(comment.end, nextLineStart - 1);
|
||||
const currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, "");
|
||||
if (currentLineText) {
|
||||
// trimmed forward and ending spaces text
|
||||
writer.write(currentLineText);
|
||||
if (end !== comment.end) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Empty string - make sure we write empty line
|
||||
writer.writeLiteral(newLine);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateIndent(text: string, pos: number, end: number) {
|
||||
let currentLineIndent = 0;
|
||||
for (; pos < end && isWhiteSpace(text.charCodeAt(pos)); pos++) {
|
||||
if (text.charCodeAt(pos) === CharacterCodes.tab) {
|
||||
// Tabs = TabSize = indent size and go to next tabStop
|
||||
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
|
||||
}
|
||||
else {
|
||||
// Empty string - make sure we write empty line
|
||||
writer.writeLiteral(newLine);
|
||||
// Single space
|
||||
currentLineIndent++;
|
||||
}
|
||||
}
|
||||
|
||||
function calculateIndent(pos: number, end: number) {
|
||||
let currentLineIndent = 0;
|
||||
for (; pos < end && isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
|
||||
if (currentSourceFile.text.charCodeAt(pos) === CharacterCodes.tab) {
|
||||
// Tabs = TabSize = indent size and go to next tabStop
|
||||
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
|
||||
}
|
||||
else {
|
||||
// Single space
|
||||
currentLineIndent++;
|
||||
}
|
||||
}
|
||||
|
||||
return currentLineIndent;
|
||||
}
|
||||
return currentLineIndent;
|
||||
}
|
||||
|
||||
export function modifierToFlag(token: SyntaxKind): NodeFlags {
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace ts {
|
||||
let jsDocCompletionEntries: CompletionEntry[];
|
||||
|
||||
function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
|
||||
let node = <NodeObject> new (getNodeConstructor(kind))(pos, end);
|
||||
let node = new NodeObject(kind, pos, end);
|
||||
node.flags = flags;
|
||||
node.parent = parent;
|
||||
return node;
|
||||
@@ -188,6 +188,14 @@ namespace ts {
|
||||
public parent: Node;
|
||||
private _children: Node[];
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
this.kind = kind;
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
@@ -805,6 +813,10 @@ namespace ts {
|
||||
public imports: LiteralExpression[];
|
||||
private namedDeclarations: Map<Declaration[]>;
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
super(kind, pos, end)
|
||||
}
|
||||
|
||||
public update(newText: string, textChangeRange: TextChangeRange): SourceFile {
|
||||
return updateSourceFile(this, newText, textChangeRange);
|
||||
}
|
||||
@@ -7970,18 +7982,8 @@ namespace ts {
|
||||
|
||||
function initializeServices() {
|
||||
objectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
function Node(pos: number, end: number) {
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
let proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject();
|
||||
proto.kind = kind;
|
||||
Node.prototype = proto;
|
||||
return <any>Node;
|
||||
},
|
||||
getNodeConstructor: () => NodeObject,
|
||||
getSourceFileConstructor: () => SourceFileObject,
|
||||
getSymbolConstructor: () => SymbolObject,
|
||||
getTypeConstructor: () => TypeObject,
|
||||
getSignatureConstructor: () => SignatureObject,
|
||||
|
||||
Reference in New Issue
Block a user