diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 91613bd5bff..bc218f54232 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -4,100 +4,6 @@
///
module ts {
- function getSourceFilePathInNewDir(newDirPath: string, sourceFile: SourceFile, program: Program, compilerHost: CompilerHost) {
- var sourceFilePath = getNormalizedPathFromPathCompoments(getNormalizedPathComponents(sourceFile.filename, compilerHost.getCurrentDirectory()));
- sourceFilePath = sourceFilePath.replace(program.getCommonSourceDirectory(), "");
- return combinePaths(newDirPath, sourceFilePath);
- }
-
- function emitToOwnOutputFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
- if (!(sourceFile.flags & NodeFlags.DeclarationFile)) {
- if ((sourceFile.flags & NodeFlags.ExternalModule || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
- return true;
- }
- }
- }
-
- function getOwnEmitOutputFilePath(sourceFile: SourceFile, program: Program, extension: string) {
- if (program.getCompilerOptions().outDir) {
- var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(getSourceFilePathInNewDir(program.getCompilerOptions().outDir, sourceFile, program, program.getCompilerHost()));
- }
- else {
- var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(sourceFile.filename);
- }
-
- return emitOutputFilePathWithoutExtension + extension;
- }
-
- function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
- return !!(sourceFile.flags & (NodeFlags.ExternalModule | NodeFlags.DeclarationFile));
- }
-
- function getFirstConstructorWithBody(node: ClassDeclaration): ConstructorDeclaration {
- return forEach(node.members, member => {
- if (member.kind === SyntaxKind.Constructor && (member).body) {
- return member;
- }
- });
- }
-
- function getAllAccessorDeclarations(node: ClassDeclaration, accessor: AccessorDeclaration) {
- var firstAccessor: AccessorDeclaration;
- var getAccessor: AccessorDeclaration;
- var setAccessor: AccessorDeclaration;
- forEach(node.members, (member: Declaration) => {
- if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) &&
- member.name.text === accessor.name.text &&
- (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
- if (!firstAccessor) {
- firstAccessor = member;
- }
-
- if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
- getAccessor = member;
- }
-
- if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
- setAccessor = member;
- }
- }
- });
- return {
- firstAccessor: firstAccessor,
- getAccessor: getAccessor,
- setAccessor: setAccessor
- };
- }
-
- export function emitFiles(resolver: EmitResolver): EmitResult {
- var program = resolver.getProgram();
- var compilerHost = program.getCompilerHost();
- var compilerOptions = program.getCompilerOptions();
- var shouldEmitDeclarations = resolver.shouldEmitDeclarations();
- var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
- var diagnostics: Diagnostic[] = [];
-
- forEach(program.getSourceFiles(), sourceFile => {
- if (emitToOwnOutputFile(sourceFile, compilerOptions)) {
- var jsFilePath = getOwnEmitOutputFilePath(sourceFile, program, ".js");
- emitJavaScript(resolver, jsFilePath, diagnostics, sourceMapDataList, sourceFile);
- if (shouldEmitDeclarations) {
- emitDeclarations(resolver, jsFilePath, diagnostics, sourceFile);
- }
- }
- });
- if (compilerOptions.out) {
- emitJavaScript(resolver, compilerOptions.out, diagnostics, sourceMapDataList);
- if (shouldEmitDeclarations) {
- emitDeclarations(resolver, compilerOptions.out, diagnostics);
- }
- }
- return {
- errors: diagnostics,
- sourceMaps: sourceMapDataList
- };
- }
-
interface EmitTextWriter extends TextWriter {
writeLiteral(s: string): void;
getTextPos(): number;
@@ -105,125 +11,149 @@ module ts {
getColumn(): number;
}
- function createTextWriter(): EmitTextWriter {
- var output = "";
- var indent = 0;
- var lineStart = true;
- var lineCount = 0;
- var linePos = 0;
-
- function write(s: string) {
- if (s && s.length) {
- if (lineStart) {
- output += getIndentString(indent);
- lineStart = false;
- }
- output += s;
- }
- }
-
- function writeLiteral(s: string) {
- if (s && s.length) {
- write(s);
- var pos = 0;
- while (pos < s.length) {
- switch (s.charCodeAt(pos++)) {
- case CharacterCodes.carriageReturn:
- if (pos < s.length && s.charCodeAt(pos) === CharacterCodes.lineFeed) {
- pos++;
- }
- case CharacterCodes.lineFeed:
- lineCount++;
- linePos = output.length - s.length + pos;
- break;
- }
- }
- }
- }
-
- function writeLine() {
- if (!lineStart) {
- output += sys.newLine;
- lineCount++;
- linePos = output.length;
- lineStart = true;
- }
- }
-
- return {
- write: write,
- writeLiteral: writeLiteral,
- writeLine: writeLine,
- increaseIndent: () => indent++,
- decreaseIndent: () => indent--,
- getTextPos: () => output.length,
- getLine: () => lineCount + 1,
- getColumn: () => lineStart ? indent * 4 + 1 : output.length - linePos + 1,
- getText: () => output
- };
- }
-
var indentStrings: string[] = [];
-
function getIndentString(level: number) {
return indentStrings[level] || (indentStrings[level] = level === 0 ? "" : getIndentString(level - 1) + " ");
}
- // Get source text of node in the current source file. Unlike getSourceTextOfNode this function
- // doesn't walk the parent chain to find the containing source file, rather it assumes the node is
- // in the source file currently being processed.
- var currentSourceFile: SourceFile;
- function getSourceTextOfLocalNode(node: Node): string {
- var text = currentSourceFile.text;
- return text.substring(skipTrivia(text, node.pos), node.end);
- }
-
- function emitJavaScript(resolver: EmitResolver, jsFilePath: string, diagnostics: Diagnostic[], sourceMapDataList: SourceMapData[], root?: SourceFile) {
+ export function emitFiles(resolver: EmitResolver): EmitResult {
var program = resolver.getProgram();
var compilerHost = program.getCompilerHost();
var compilerOptions = program.getCompilerOptions();
+ var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
+ var diagnostics: Diagnostic[] = [];
- var writer = createTextWriter();
- var write = writer.write;
- var writeLine = writer.writeLine;
- var increaseIndent = writer.increaseIndent;
- var decreaseIndent = writer.decreaseIndent;
+ function getSourceFilePathInNewDir(newDirPath: string, sourceFile: SourceFile) {
+ var sourceFilePath = getNormalizedPathFromPathCompoments(getNormalizedPathComponents(sourceFile.filename, compilerHost.getCurrentDirectory()));
+ sourceFilePath = sourceFilePath.replace(program.getCommonSourceDirectory(), "");
+ return combinePaths(newDirPath, sourceFilePath);
+ }
- var extendsEmitted = false;
+ function emitToOwnOutputFile(sourceFile: SourceFile) {
+ if (!(sourceFile.flags & NodeFlags.DeclarationFile)) {
+ if ((sourceFile.flags & NodeFlags.ExternalModule || !compilerOptions.out) && !fileExtensionIs(sourceFile.filename, ".js")) {
+ return true;
+ }
+ }
+ }
- /** write emitted output to disk*/
- var writeEmittedFiles = writeJavaScriptFile;
+ function getOwnEmitOutputFilePath(sourceFile: SourceFile, extension: string) {
+ if (program.getCompilerOptions().outDir) {
+ var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(getSourceFilePathInNewDir(program.getCompilerOptions().outDir, sourceFile));
+ }
+ else {
+ var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(sourceFile.filename);
+ }
- /** Emit a node */
- var emit = emitNode;
+ return emitOutputFilePathWithoutExtension + extension;
+ }
- /** Called just before starting emit of a node */
- var emitStart = function (node: Node) { }
+ function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
+ return !!(sourceFile.flags & (NodeFlags.ExternalModule | NodeFlags.DeclarationFile));
+ }
- /** Called once the emit of the node is done */
- var emitEnd = function (node: Node) { }
+ function getFirstConstructorWithBody(node: ClassDeclaration): ConstructorDeclaration {
+ return forEach(node.members, member => {
+ if (member.kind === SyntaxKind.Constructor && (member).body) {
+ return member;
+ }
+ });
+ }
- /** Emit the text for the given token that comes after startPos
- * This by default writes the text provided with the given tokenKind
- * but if optional emitFn callback is provided the text is emitted using the callback instead of default text
- * @param tokenKind the kind of the token to search and emit
- * @param startPos the position in the source to start searching for the token
- * @param emitFn if given will be invoked to emit the text instead of actual token emit */
- var emitToken = emitTokenText;
+ function getAllAccessorDeclarations(node: ClassDeclaration, accessor: AccessorDeclaration) {
+ var firstAccessor: AccessorDeclaration;
+ var getAccessor: AccessorDeclaration;
+ var setAccessor: AccessorDeclaration;
+ forEach(node.members, (member: Declaration) => {
+ if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) &&
+ member.name.text === accessor.name.text &&
+ (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
+ if (!firstAccessor) {
+ firstAccessor = member;
+ }
- /** Called to notify start of new source file emit */
- var emitNewSourceFileStart = function (node: SourceFile) { }
+ if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
+ getAccessor = member;
+ }
- /** Called to before starting the lexical scopes as in function/class in the emitted code because of node
- * @param scopeDeclaration node that starts the lexical scope
- * @param scopeName Optional name of this scope instead of deducing one from the declaration node */
- var scopeEmitStart = function (scopeDeclaration: Node, scopeName?: string) { }
+ if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
+ setAccessor = member;
+ }
+ }
+ });
+ return {
+ firstAccessor: firstAccessor,
+ getAccessor: getAccessor,
+ setAccessor: setAccessor
+ };
+ }
- /** Called after coming out of the scope */
- var scopeEmitEnd = function () { }
+ function createTextWriter(): EmitTextWriter {
+ var output = "";
+ var indent = 0;
+ var lineStart = true;
+ var lineCount = 0;
+ var linePos = 0;
- /** Sourcemap data that will get encoded */
- var sourceMapData: SourceMapData;
+ function write(s: string) {
+ if (s && s.length) {
+ if (lineStart) {
+ output += getIndentString(indent);
+ lineStart = false;
+ }
+ output += s;
+ }
+ }
+
+ function writeLiteral(s: string) {
+ if (s && s.length) {
+ write(s);
+ var pos = 0;
+ while (pos < s.length) {
+ switch (s.charCodeAt(pos++)) {
+ case CharacterCodes.carriageReturn:
+ if (pos < s.length && s.charCodeAt(pos) === CharacterCodes.lineFeed) {
+ pos++;
+ }
+ case CharacterCodes.lineFeed:
+ lineCount++;
+ linePos = output.length - s.length + pos;
+ break;
+ }
+ }
+ }
+ }
+
+ function writeLine() {
+ if (!lineStart) {
+ output += sys.newLine;
+ lineCount++;
+ linePos = output.length;
+ lineStart = true;
+ }
+ }
+
+ return {
+ write: write,
+ writeLiteral: writeLiteral,
+ writeLine: writeLine,
+ increaseIndent: () => indent++,
+ decreaseIndent: () => indent--,
+ getTextPos: () => output.length,
+ getLine: () => lineCount + 1,
+ getColumn: () => lineStart ? indent * 4 + 1 : output.length - linePos + 1,
+ getText: () => output
+ };
+ }
+
+ // Get source text of node in the current source file. Unlike getSourceTextOfNode this function
+ // doesn't walk the parent chain to find the containing source file, rather it assumes the node is
+ // in the source file currently being processed.
+ var currentSourceFile: SourceFile;
+ function getSourceTextOfLocalNode(node: Node): string {
+ var text = currentSourceFile.text;
+ return text.substring(skipTrivia(text, node.pos), node.end);
+ }
function writeFile(filename: string, data: string) {
compilerHost.writeFile(filename, data, hostErrorMessage => {
@@ -231,2075 +161,2131 @@ module ts {
});
}
- function initializeEmitterWithSourceMaps() {
- var sourceMapDir: string; // The directory in which sourcemap will be
+ function emitJavaScript(jsFilePath: string, root?: SourceFile) {
+ var writer = createTextWriter();
+ var write = writer.write;
+ var writeLine = writer.writeLine;
+ var increaseIndent = writer.increaseIndent;
+ var decreaseIndent = writer.decreaseIndent;
- // Current source map file and its index in the sources list
- var sourceMapSourceIndex = -1;
+ var extendsEmitted = false;
- // Names and its index map
- var sourceMapNameIndexMap: Map = {};
- var sourceMapNameIndices: number[] = [];
- function getSourceMapNameIndex() {
- return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
- }
+ /** write emitted output to disk*/
+ var writeEmittedFiles = writeJavaScriptFile;
- // Last recorded and encoded spans
- var lastRecordedSourceMapSpan: SourceMapSpan;
- var lastEncodedSourceMapSpan: SourceMapSpan = {
- emittedLine: 1,
- emittedColumn: 1,
- sourceLine: 1,
- sourceColumn: 1,
- sourceIndex: 0
- };
- var lastEncodedNameIndex = 0;
+ /** Emit a node */
+ var emit = emitNode;
- // Encoding for sourcemap span
- function encodeLastRecordedSourceMapSpan() {
- if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
- return;
+ /** Called just before starting emit of a node */
+ var emitStart = function (node: Node) { }
+
+ /** Called once the emit of the node is done */
+ var emitEnd = function (node: Node) { }
+
+ /** Emit the text for the given token that comes after startPos
+ * This by default writes the text provided with the given tokenKind
+ * but if optional emitFn callback is provided the text is emitted using the callback instead of default text
+ * @param tokenKind the kind of the token to search and emit
+ * @param startPos the position in the source to start searching for the token
+ * @param emitFn if given will be invoked to emit the text instead of actual token emit */
+ var emitToken = emitTokenText;
+
+ /** Called to notify start of new source file emit */
+ var emitNewSourceFileStart = function (node: SourceFile) { }
+
+ /** Called to before starting the lexical scopes as in function/class in the emitted code because of node
+ * @param scopeDeclaration node that starts the lexical scope
+ * @param scopeName Optional name of this scope instead of deducing one from the declaration node */
+ var scopeEmitStart = function (scopeDeclaration: Node, scopeName?: string) { }
+
+ /** Called after coming out of the scope */
+ var scopeEmitEnd = function () { }
+
+ /** Sourcemap data that will get encoded */
+ var sourceMapData: SourceMapData;
+
+ function initializeEmitterWithSourceMaps() {
+ var sourceMapDir: string; // The directory in which sourcemap will be
+
+ // Current source map file and its index in the sources list
+ var sourceMapSourceIndex = -1;
+
+ // Names and its index map
+ var sourceMapNameIndexMap: Map = {};
+ var sourceMapNameIndices: number[] = [];
+ function getSourceMapNameIndex() {
+ return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
}
- var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
- // Line/Comma deliminators
- if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
- // Emit comma to separate the entry
- if (sourceMapData.sourceMapMappings) {
- sourceMapData.sourceMapMappings += ",";
+ // Last recorded and encoded spans
+ var lastRecordedSourceMapSpan: SourceMapSpan;
+ var lastEncodedSourceMapSpan: SourceMapSpan = {
+ emittedLine: 1,
+ emittedColumn: 1,
+ sourceLine: 1,
+ sourceColumn: 1,
+ sourceIndex: 0
+ };
+ var lastEncodedNameIndex = 0;
+
+ // Encoding for sourcemap span
+ function encodeLastRecordedSourceMapSpan() {
+ if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
+ return;
}
- }
- else {
- // Emit line deliminators
- for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
- sourceMapData.sourceMapMappings += ";";
- }
- prevEncodedEmittedColumn = 1;
- }
- // 1. Relative Column 0 based
- sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
-
- // 2. Relative sourceIndex
- sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
-
- // 3. Relative sourceLine 0 based
- sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
-
- // 4. Relative sourceColumn 0 based
- sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
-
- // 5. Relative namePosition 0 based
- if (lastRecordedSourceMapSpan.nameIndex >= 0) {
- sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
- lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
- }
-
- lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
- sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
-
- function base64VLQFormatEncode(inValue: number) {
- function base64FormatEncode(inValue: number) {
- if (inValue < 64) {
- return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
+ var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
+ // Line/Comma deliminators
+ if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
+ // Emit comma to separate the entry
+ if (sourceMapData.sourceMapMappings) {
+ sourceMapData.sourceMapMappings += ",";
}
- throw TypeError(inValue + ": not a 64 based value");
- }
-
- // Add a new least significant bit that has the sign of the value.
- // if negative number the least significant bit that gets added to the number has value 1
- // else least significant bit value that gets added is 0
- // eg. -1 changes to binary : 01 [1] => 3
- // +1 changes to binary : 01 [0] => 2
- if (inValue < 0) {
- inValue = ((-inValue) << 1) + 1;
}
else {
- inValue = inValue << 1;
+ // Emit line deliminators
+ for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
+ sourceMapData.sourceMapMappings += ";";
+ }
+ prevEncodedEmittedColumn = 1;
}
- // Encode 5 bits at a time starting from least significant bits
- var encodedStr = "";
- do {
- var currentDigit = inValue & 31; // 11111
- inValue = inValue >> 5;
- if (inValue > 0) {
- // There are still more digits to decode, set the msb (6th bit)
- currentDigit = currentDigit | 32;
- }
- encodedStr = encodedStr + base64FormatEncode(currentDigit);
- } while (inValue > 0);
+ // 1. Relative Column 0 based
+ sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
- return encodedStr;
- }
- }
+ // 2. Relative sourceIndex
+ sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
- function recordSourceMapSpan(pos: number) {
- var sourceLinePos = currentSourceFile.getLineAndCharacterFromPosition(pos);
- var emittedLine = writer.getLine();
- var emittedColumn = writer.getColumn();
+ // 3. Relative sourceLine 0 based
+ sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
- // If this location wasnt recorded or the location in source is going backwards, record the span
- if (!lastRecordedSourceMapSpan ||
- lastRecordedSourceMapSpan.emittedLine != emittedLine ||
- lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
- lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
- (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)) {
- // Encode the last recordedSpan before assigning new
- encodeLastRecordedSourceMapSpan();
+ // 4. Relative sourceColumn 0 based
+ sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
- // New span
- lastRecordedSourceMapSpan = {
- emittedLine: emittedLine,
- emittedColumn: emittedColumn,
- sourceLine: sourceLinePos.line,
- sourceColumn: sourceLinePos.character,
- nameIndex: getSourceMapNameIndex(),
- sourceIndex: sourceMapSourceIndex
- };
- }
- else {
- // Take the new pos instead since there is no change in emittedLine and column since last location
- lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
- lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
- }
- }
-
- function recordEmitNodeStartSpan(node: Node) {
- // Get the token pos after skipping to the token (ignoring the leading trivia)
- recordSourceMapSpan(ts.getTokenPosOfNode(node));
- }
-
- function recordEmitNodeEndSpan(node: Node) {
- recordSourceMapSpan(node.end);
- }
-
- function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
- var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
- recordSourceMapSpan(tokenStartPos);
- var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
- recordSourceMapSpan(tokenEndPos);
- return tokenEndPos;
- }
-
- function recordNewSourceFileStart(node: SourceFile) {
- // Add the the file to tsFilePaths
- // If sourceroot option: Use the relative path corresponding to the common directory path
- // otherwise source locations relative to map file location
- var sourcesDirectoryPath = compilerOptions.sourceRoot ? program.getCommonSourceDirectory() : sourceMapDir;
-
- sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
- node.filename,
- compilerHost.getCurrentDirectory(),
- /*isAbsolutePathAnUrl*/ true));
- sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
-
- // The one that can be used from program to get the actual source file
- sourceMapData.inputSourceFileNames.push(node.filename);
- }
-
- function recordScopeNameOfNode(node: Node, scopeName?: string) {
- function recordScopeNameIndex(scopeNameIndex: number) {
- sourceMapNameIndices.push(scopeNameIndex);
- }
-
- function recordScopeNameStart(scopeName: string) {
- var scopeNameIndex = -1;
- if (scopeName) {
- var parentIndex = getSourceMapNameIndex();
- if (parentIndex !== -1) {
- scopeName = sourceMapData.sourceMapNames[parentIndex] + "." + scopeName;
- }
-
- scopeNameIndex = getProperty(sourceMapNameIndexMap, scopeName);
- if (scopeNameIndex === undefined) {
- scopeNameIndex = sourceMapData.sourceMapNames.length;
- sourceMapData.sourceMapNames.push(scopeName);
- sourceMapNameIndexMap[scopeName] = scopeNameIndex;
- }
+ // 5. Relative namePosition 0 based
+ if (lastRecordedSourceMapSpan.nameIndex >= 0) {
+ sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
+ lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
}
- recordScopeNameIndex(scopeNameIndex);
- }
- if (scopeName) {
- // The scope was already given a name use it
- recordScopeNameStart(scopeName);
- }
- else if (node.kind === SyntaxKind.FunctionDeclaration ||
- node.kind === SyntaxKind.FunctionExpression ||
- node.kind === SyntaxKind.Method ||
- node.kind === SyntaxKind.GetAccessor ||
- node.kind === SyntaxKind.SetAccessor ||
- node.kind === SyntaxKind.ModuleDeclaration ||
- node.kind === SyntaxKind.ClassDeclaration ||
- node.kind === SyntaxKind.EnumDeclaration) {
- // Declaration and has associated name use it
- if ((node).name) {
- scopeName = (node).name.text;
+ lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
+ sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
+
+ function base64VLQFormatEncode(inValue: number) {
+ function base64FormatEncode(inValue: number) {
+ if (inValue < 64) {
+ return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
+ }
+ throw TypeError(inValue + ": not a 64 based value");
+ }
+
+ // Add a new least significant bit that has the sign of the value.
+ // if negative number the least significant bit that gets added to the number has value 1
+ // else least significant bit value that gets added is 0
+ // eg. -1 changes to binary : 01 [1] => 3
+ // +1 changes to binary : 01 [0] => 2
+ if (inValue < 0) {
+ inValue = ((-inValue) << 1) + 1;
+ }
+ else {
+ inValue = inValue << 1;
+ }
+
+ // Encode 5 bits at a time starting from least significant bits
+ var encodedStr = "";
+ do {
+ var currentDigit = inValue & 31; // 11111
+ inValue = inValue >> 5;
+ if (inValue > 0) {
+ // There are still more digits to decode, set the msb (6th bit)
+ currentDigit = currentDigit | 32;
+ }
+ encodedStr = encodedStr + base64FormatEncode(currentDigit);
+ } while (inValue > 0);
+
+ return encodedStr;
}
- recordScopeNameStart(scopeName);
- }
- else {
- // Block just use the name from upper level scope
- recordScopeNameIndex(getSourceMapNameIndex());
- }
- }
-
- function recordScopeNameEnd() {
- sourceMapNameIndices.pop();
- };
-
- function writeJavaScriptAndSourceMapFile(emitOutput: string) {
- // Write source map file
- encodeLastRecordedSourceMapSpan();
- writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({
- version: 3,
- file: sourceMapData.sourceMapFile,
- sourceRoot: sourceMapData.sourceMapSourceRoot,
- sources: sourceMapData.sourceMapSources,
- names: sourceMapData.sourceMapNames,
- mappings: sourceMapData.sourceMapMappings
- }));
- sourceMapDataList.push(sourceMapData);
-
- // Write sourcemap url to the js file and write the js file
- writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL);
- }
-
- // Initialize source map data
- var sourceMapJsFile = getBaseFilename(normalizeSlashes(jsFilePath));
- sourceMapData = {
- sourceMapFilePath: jsFilePath + ".map",
- jsSourceMappingURL: sourceMapJsFile + ".map",
- sourceMapFile: sourceMapJsFile,
- sourceMapSourceRoot: compilerOptions.sourceRoot || "",
- sourceMapSources: [],
- inputSourceFileNames: [],
- sourceMapNames: [],
- sourceMapMappings: "",
- sourceMapDecodedMappings: []
- };
-
- // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
- // relative paths of the sources list in the sourcemap
- sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
- if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
- sourceMapData.sourceMapSourceRoot += directorySeparator;
- }
-
- if (compilerOptions.mapRoot) {
- sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
- if (root) { // emitting single module file
- // For modules or multiple emit files the mapRoot will have directory structure like the sources
- // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
- sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceMapDir, root, program, compilerHost));
}
- if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
- // The relative paths are relative to the common directory
- sourceMapDir = combinePaths(program.getCommonSourceDirectory(), sourceMapDir);
- sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
- getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath
- combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
+ function recordSourceMapSpan(pos: number) {
+ var sourceLinePos = currentSourceFile.getLineAndCharacterFromPosition(pos);
+ var emittedLine = writer.getLine();
+ var emittedColumn = writer.getColumn();
+
+ // If this location wasnt recorded or the location in source is going backwards, record the span
+ if (!lastRecordedSourceMapSpan ||
+ lastRecordedSourceMapSpan.emittedLine != emittedLine ||
+ lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
+ lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
+ (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)) {
+ // Encode the last recordedSpan before assigning new
+ encodeLastRecordedSourceMapSpan();
+
+ // New span
+ lastRecordedSourceMapSpan = {
+ emittedLine: emittedLine,
+ emittedColumn: emittedColumn,
+ sourceLine: sourceLinePos.line,
+ sourceColumn: sourceLinePos.character,
+ nameIndex: getSourceMapNameIndex(),
+ sourceIndex: sourceMapSourceIndex
+ };
+ }
+ else {
+ // Take the new pos instead since there is no change in emittedLine and column since last location
+ lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
+ lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
+ }
+ }
+
+ function recordEmitNodeStartSpan(node: Node) {
+ // Get the token pos after skipping to the token (ignoring the leading trivia)
+ recordSourceMapSpan(ts.getTokenPosOfNode(node));
+ }
+
+ function recordEmitNodeEndSpan(node: Node) {
+ recordSourceMapSpan(node.end);
+ }
+
+ function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
+ var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
+ recordSourceMapSpan(tokenStartPos);
+ var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
+ recordSourceMapSpan(tokenEndPos);
+ return tokenEndPos;
+ }
+
+ function recordNewSourceFileStart(node: SourceFile) {
+ // Add the the file to tsFilePaths
+ // If sourceroot option: Use the relative path corresponding to the common directory path
+ // otherwise source locations relative to map file location
+ var sourcesDirectoryPath = compilerOptions.sourceRoot ? program.getCommonSourceDirectory() : sourceMapDir;
+
+ sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
+ node.filename,
compilerHost.getCurrentDirectory(),
- /*isAbsolutePathAnUrl*/ true);
- }
- else {
- sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
- }
- }
- else {
- sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
- }
+ /*isAbsolutePathAnUrl*/ true));
+ sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
- function emitNodeWithMap(node: Node) {
- if (node) {
- if (node.kind != SyntaxKind.SourceFile) {
- recordEmitNodeStartSpan(node);
- emitNode(node);
- recordEmitNodeEndSpan(node);
+ // The one that can be used from program to get the actual source file
+ sourceMapData.inputSourceFileNames.push(node.filename);
+ }
+
+ function recordScopeNameOfNode(node: Node, scopeName?: string) {
+ function recordScopeNameIndex(scopeNameIndex: number) {
+ sourceMapNameIndices.push(scopeNameIndex);
+ }
+
+ function recordScopeNameStart(scopeName: string) {
+ var scopeNameIndex = -1;
+ if (scopeName) {
+ var parentIndex = getSourceMapNameIndex();
+ if (parentIndex !== -1) {
+ scopeName = sourceMapData.sourceMapNames[parentIndex] + "." + scopeName;
+ }
+
+ scopeNameIndex = getProperty(sourceMapNameIndexMap, scopeName);
+ if (scopeNameIndex === undefined) {
+ scopeNameIndex = sourceMapData.sourceMapNames.length;
+ sourceMapData.sourceMapNames.push(scopeName);
+ sourceMapNameIndexMap[scopeName] = scopeNameIndex;
+ }
+ }
+ recordScopeNameIndex(scopeNameIndex);
+ }
+
+ if (scopeName) {
+ // The scope was already given a name use it
+ recordScopeNameStart(scopeName);
+ }
+ else if (node.kind === SyntaxKind.FunctionDeclaration ||
+ node.kind === SyntaxKind.FunctionExpression ||
+ node.kind === SyntaxKind.Method ||
+ node.kind === SyntaxKind.GetAccessor ||
+ node.kind === SyntaxKind.SetAccessor ||
+ node.kind === SyntaxKind.ModuleDeclaration ||
+ node.kind === SyntaxKind.ClassDeclaration ||
+ node.kind === SyntaxKind.EnumDeclaration) {
+ // Declaration and has associated name use it
+ if ((node).name) {
+ scopeName = (node).name.text;
+ }
+ recordScopeNameStart(scopeName);
}
else {
- recordNewSourceFileStart(node);
- emitNode(node);
+ // Block just use the name from upper level scope
+ recordScopeNameIndex(getSourceMapNameIndex());
+ }
+ }
+
+ function recordScopeNameEnd() {
+ sourceMapNameIndices.pop();
+ };
+
+ function writeJavaScriptAndSourceMapFile(emitOutput: string) {
+ // Write source map file
+ encodeLastRecordedSourceMapSpan();
+ writeFile(sourceMapData.sourceMapFilePath, JSON.stringify({
+ version: 3,
+ file: sourceMapData.sourceMapFile,
+ sourceRoot: sourceMapData.sourceMapSourceRoot,
+ sources: sourceMapData.sourceMapSources,
+ names: sourceMapData.sourceMapNames,
+ mappings: sourceMapData.sourceMapMappings
+ }));
+ sourceMapDataList.push(sourceMapData);
+
+ // Write sourcemap url to the js file and write the js file
+ writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL);
+ }
+
+ // Initialize source map data
+ var sourceMapJsFile = getBaseFilename(normalizeSlashes(jsFilePath));
+ sourceMapData = {
+ sourceMapFilePath: jsFilePath + ".map",
+ jsSourceMappingURL: sourceMapJsFile + ".map",
+ sourceMapFile: sourceMapJsFile,
+ sourceMapSourceRoot: compilerOptions.sourceRoot || "",
+ sourceMapSources: [],
+ inputSourceFileNames: [],
+ sourceMapNames: [],
+ sourceMapMappings: "",
+ sourceMapDecodedMappings: []
+ };
+
+ // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
+ // relative paths of the sources list in the sourcemap
+ sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
+ if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
+ sourceMapData.sourceMapSourceRoot += directorySeparator;
+ }
+
+ if (compilerOptions.mapRoot) {
+ sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
+ if (root) { // emitting single module file
+ // For modules or multiple emit files the mapRoot will have directory structure like the sources
+ // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
+ sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceMapDir, root));
+ }
+
+ if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
+ // The relative paths are relative to the common directory
+ sourceMapDir = combinePaths(program.getCommonSourceDirectory(), sourceMapDir);
+ sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
+ getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath
+ combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
+ compilerHost.getCurrentDirectory(),
+ /*isAbsolutePathAnUrl*/ true);
+ }
+ else {
+ sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
+ }
+ }
+ else {
+ sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
+ }
+
+ function emitNodeWithMap(node: Node) {
+ if (node) {
+ if (node.kind != SyntaxKind.SourceFile) {
+ recordEmitNodeStartSpan(node);
+ emitNode(node);
+ recordEmitNodeEndSpan(node);
+ }
+ else {
+ recordNewSourceFileStart(node);
+ emitNode(node);
+ }
+ }
+ }
+
+ writeEmittedFiles = writeJavaScriptAndSourceMapFile;
+ emit = emitNodeWithMap;
+ emitStart = recordEmitNodeStartSpan;
+ emitEnd = recordEmitNodeEndSpan;
+ emitToken = writeTextWithSpanRecord;
+ emitNewSourceFileStart = recordNewSourceFileStart;
+ scopeEmitStart = recordScopeNameOfNode;
+ scopeEmitEnd = recordScopeNameEnd;
+ }
+
+ function writeJavaScriptFile(emitOutput: string) {
+ writeFile(jsFilePath, emitOutput);
+ }
+
+ function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
+ var tokenString = tokenToString(tokenKind);
+ if (emitFn) {
+ emitFn();
+ }
+ else {
+ write(tokenString);
+ }
+ return startPos + tokenString.length;
+ }
+
+ function emitOptional(prefix: string, node: Node) {
+ if (node) {
+ write(prefix);
+ emit(node);
+ }
+ }
+
+ function emitCommaList(nodes: Node[], count?: number) {
+ if (!(count >= 0)) count = nodes.length;
+ if (nodes) {
+ for (var i = 0; i < count; i++) {
+ if (i) write(", ");
+ emit(nodes[i]);
}
}
}
- writeEmittedFiles = writeJavaScriptAndSourceMapFile;
- emit = emitNodeWithMap;
- emitStart = recordEmitNodeStartSpan;
- emitEnd = recordEmitNodeEndSpan;
- emitToken = writeTextWithSpanRecord;
- emitNewSourceFileStart = recordNewSourceFileStart;
- scopeEmitStart = recordScopeNameOfNode;
- scopeEmitEnd = recordScopeNameEnd;
- }
-
- function writeJavaScriptFile(emitOutput: string) {
- writeFile(jsFilePath, emitOutput);
- }
-
- function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
- var tokenString = tokenToString(tokenKind);
- if (emitFn) {
- emitFn();
- }
- else {
- write(tokenString);
- }
- return startPos + tokenString.length;
- }
-
- function emitOptional(prefix: string, node: Node) {
- if (node) {
- write(prefix);
- emit(node);
- }
- }
-
- function emitCommaList(nodes: Node[], count?: number) {
- if (!(count >= 0)) count = nodes.length;
- if (nodes) {
- for (var i = 0; i < count; i++) {
- if (i) write(", ");
- emit(nodes[i]);
+ function emitMultiLineList(nodes: Node[]) {
+ if (nodes) {
+ for (var i = 0; i < nodes.length; i++) {
+ if (i) write(",");
+ writeLine();
+ emit(nodes[i]);
+ }
}
}
- }
- function emitMultiLineList(nodes: Node[]) {
- if (nodes) {
+ function emitLines(nodes: Node[]) {
for (var i = 0; i < nodes.length; i++) {
- if (i) write(",");
writeLine();
emit(nodes[i]);
}
}
- }
- function emitLines(nodes: Node[]) {
- for (var i = 0; i < nodes.length; i++) {
- writeLine();
- emit(nodes[i]);
- }
- }
-
- function emitLiteral(node: LiteralExpression) {
- var text = getSourceTextOfLocalNode(node);
- if (node.kind === SyntaxKind.StringLiteral && compilerOptions.sourceMap) {
- writer.writeLiteral(text);
- }
- else {
- write(text);
- }
- }
-
- // This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
- // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
- function emitQuotedIdentifier(node: Identifier) {
- if (node.kind === SyntaxKind.StringLiteral) {
- emitLiteral(node);
- }
- else {
- write("\"");
-
- if (node.kind === SyntaxKind.NumericLiteral) {
- write(node.text);
+ function emitLiteral(node: LiteralExpression) {
+ var text = getSourceTextOfLocalNode(node);
+ if (node.kind === SyntaxKind.StringLiteral && compilerOptions.sourceMap) {
+ writer.writeLiteral(text);
}
else {
- write(getSourceTextOfLocalNode(node));
- }
-
- write("\"");
- }
- }
-
- function isNonExpressionIdentifier(node: Identifier) {
- var parent = node.parent;
- switch (parent.kind) {
- case SyntaxKind.Parameter:
- case SyntaxKind.VariableDeclaration:
- case SyntaxKind.Property:
- case SyntaxKind.PropertyAssignment:
- case SyntaxKind.EnumMember:
- case SyntaxKind.Method:
- case SyntaxKind.FunctionDeclaration:
- case SyntaxKind.GetAccessor:
- case SyntaxKind.SetAccessor:
- case SyntaxKind.FunctionExpression:
- case SyntaxKind.ClassDeclaration:
- case SyntaxKind.InterfaceDeclaration:
- case SyntaxKind.EnumDeclaration:
- case SyntaxKind.ModuleDeclaration:
- case SyntaxKind.ImportDeclaration:
- return (parent).name === node;
- case SyntaxKind.BreakStatement:
- case SyntaxKind.ContinueStatement:
- case SyntaxKind.ExportAssignment:
- return false;
- case SyntaxKind.LabelledStatement:
- return (node.parent).label === node;
- case SyntaxKind.CatchBlock:
- return (node.parent).variable === node;
- }
- }
-
- function emitIdentifier(node: Identifier) {
- if (!isNonExpressionIdentifier(node)) {
- var prefix = resolver.getExpressionNamePrefix(node);
- if (prefix) {
- write(prefix);
- write(".");
+ write(text);
}
}
- write(getSourceTextOfLocalNode(node));
- }
- function emitThis(node: Node) {
- if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalThis) {
- write("_this");
- }
- else {
- write("this");
- }
- }
-
- function emitSuper(node: Node) {
- var flags = resolver.getNodeCheckFlags(node);
- if (flags & NodeCheckFlags.SuperInstance) {
- write("_super.prototype");
- }
- else if (flags & NodeCheckFlags.SuperStatic) {
- write("_super");
- }
- else {
- write("super");
- }
- }
-
- function emitArrayLiteral(node: ArrayLiteral) {
- if (node.flags & NodeFlags.MultiLine) {
- write("[");
- increaseIndent();
- emitMultiLineList(node.elements);
- decreaseIndent();
- writeLine();
- write("]");
- }
- else {
- write("[");
- emitCommaList(node.elements);
- write("]");
- }
- }
-
- function emitObjectLiteral(node: ObjectLiteral) {
- if (!node.properties.length) {
- write("{}");
- }
- else if (node.flags & NodeFlags.MultiLine) {
- write("{");
- increaseIndent();
- emitMultiLineList(node.properties);
- decreaseIndent();
- writeLine();
- write("}");
- }
- else {
- write("{ ");
- emitCommaList(node.properties);
- write(" }");
- }
- }
-
- function emitPropertyAssignment(node: PropertyDeclaration) {
- emit(node.name);
- write(": ");
- emit(node.initializer);
- }
-
- function emitPropertyAccess(node: PropertyAccess) {
- var text = resolver.getPropertyAccessSubstitution(node);
- if (text) {
- write(text);
- return;
- }
- emit(node.left);
- write(".");
- emit(node.right);
- }
-
- function emitIndexedAccess(node: IndexedAccess) {
- emit(node.object);
- write("[");
- emit(node.index);
- write("]");
- }
-
- function emitCallExpression(node: CallExpression) {
- var superCall = false;
- if (node.func.kind === SyntaxKind.SuperKeyword) {
- write("_super");
- superCall = true;
- }
- else {
- emit(node.func);
- superCall = node.func.kind === SyntaxKind.PropertyAccess && (node.func).left.kind === SyntaxKind.SuperKeyword;
- }
- if (superCall) {
- write(".call(");
- emitThis(node.func);
- if (node.arguments.length) {
- write(", ");
- emitCommaList(node.arguments);
- }
- write(")");
- }
- else {
- write("(");
- emitCommaList(node.arguments);
- write(")");
- }
- }
-
- function emitNewExpression(node: NewExpression) {
- write("new ");
- emit(node.func);
- if (node.arguments) {
- write("(");
- emitCommaList(node.arguments);
- write(")");
- }
- }
-
- function emitParenExpression(node: ParenExpression) {
- if (node.expression.kind === SyntaxKind.TypeAssertion) {
- var operand = (node.expression).operand;
-
- // Make sure we consider all nested cast expressions, e.g.:
- // (-A).x;
- while (operand.kind == SyntaxKind.TypeAssertion) {
- operand = (operand).operand;
- }
-
- // We have an expression of the form: (SubExpr)
- // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
- // Omitting the parentheses, however, could cause change in the semantics of the generated
- // code if the casted expression has a lower precedence than the rest of the expression, e.g.:
- // (new A).foo should be emitted as (new A).foo and not new A.foo
- // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
- // new (A()) should be emitted as new (A()) and not new A()
- // (function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
- if (operand.kind !== SyntaxKind.PrefixOperator && operand.kind !== SyntaxKind.PostfixOperator && operand.kind !== SyntaxKind.NewExpression &&
- !(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
- !(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression)) {
- emit(operand);
- return;
- }
- }
- write("(");
- emit(node.expression);
- write(")");
- }
-
- function emitUnaryExpression(node: UnaryExpression) {
- if (node.kind === SyntaxKind.PrefixOperator) {
- write(tokenToString(node.operator));
- }
- // In some cases, we need to emit a space between the operator and the operand. One obvious case
- // is when the operator is an identifer, like delete or typeof. We also need to do this for plus
- // and minus expressions in certain cases. Specifically, consider the following two cases (parens
- // are just for clarity of exposition, and not part of the source code):
- //
- // (+(+1))
- // (+(++1))
- //
- // We need to emit a space in both cases. In the first case, the absence of a space will make
- // the resulting expression a prefix increment operation. And in the second, it will make the resulting
- // expression a prefix increment whose operand is a plus expression - (++(+x))
- // The same is true of minus of course.
- if (node.operator >= SyntaxKind.Identifier) {
- write(" ");
- }
- else if (node.kind === SyntaxKind.PrefixOperator && node.operand.kind === SyntaxKind.PrefixOperator) {
- var operand = node.operand;
- if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
- write(" ");
- }
- else if (node.operator === SyntaxKind.MinusToken && (operand.operator === SyntaxKind.MinusToken || operand.operator === SyntaxKind.MinusMinusToken)) {
- write(" ");
- }
- }
- emit(node.operand);
- if (node.kind === SyntaxKind.PostfixOperator) {
- write(tokenToString(node.operator));
- }
- }
-
- function emitBinaryExpression(node: BinaryExpression) {
- emit(node.left);
- if (node.operator !== SyntaxKind.CommaToken) write(" ");
- write(tokenToString(node.operator));
- write(" ");
- emit(node.right);
- }
-
- function emitConditionalExpression(node: ConditionalExpression) {
- emit(node.condition);
- write(" ? ");
- emit(node.whenTrue);
- write(" : ");
- emit(node.whenFalse);
- }
-
- function emitBlock(node: Block) {
- emitToken(SyntaxKind.OpenBraceToken, node.pos);
- increaseIndent();
- scopeEmitStart(node.parent);
- if (node.kind === SyntaxKind.ModuleBlock) {
- Debug.assert(node.parent.kind === SyntaxKind.ModuleDeclaration);
- emitCaptureThisForNodeIfNecessary(node.parent);
- }
- emitLines(node.statements);
- decreaseIndent();
- writeLine();
- emitToken(SyntaxKind.CloseBraceToken, node.statements.end);
- scopeEmitEnd();
- }
-
- function emitEmbeddedStatement(node: Node) {
- if (node.kind === SyntaxKind.Block) {
- write(" ");
- emit(node);
- }
- else {
- increaseIndent();
- writeLine();
- emit(node);
- decreaseIndent();
- }
- }
-
- function emitExpressionStatement(node: ExpressionStatement) {
- var isArrowExpression = node.expression.kind === SyntaxKind.ArrowFunction;
- if (isArrowExpression) write("(");
- emit(node.expression);
- if (isArrowExpression) write(")");
- write(";");
- }
-
- function emitIfStatement(node: IfStatement) {
- var endPos = emitToken(SyntaxKind.IfKeyword, node.pos);
- write(" ");
- endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
- emit(node.expression);
- emitToken(SyntaxKind.CloseParenToken, node.expression.end);
- emitEmbeddedStatement(node.thenStatement);
- if (node.elseStatement) {
- writeLine();
- emitToken(SyntaxKind.ElseKeyword, node.thenStatement.end);
- if (node.elseStatement.kind === SyntaxKind.IfStatement) {
- write(" ");
- emit(node.elseStatement);
+ // This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
+ // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
+ function emitQuotedIdentifier(node: Identifier) {
+ if (node.kind === SyntaxKind.StringLiteral) {
+ emitLiteral(node);
}
else {
- emitEmbeddedStatement(node.elseStatement);
+ write("\"");
+
+ if (node.kind === SyntaxKind.NumericLiteral) {
+ write(node.text);
+ }
+ else {
+ write(getSourceTextOfLocalNode(node));
+ }
+
+ write("\"");
}
}
- }
- function emitDoStatement(node: DoStatement) {
- write("do");
- emitEmbeddedStatement(node.statement);
- if (node.statement.kind === SyntaxKind.Block) {
- write(" ");
+ function isNonExpressionIdentifier(node: Identifier) {
+ var parent = node.parent;
+ switch (parent.kind) {
+ case SyntaxKind.Parameter:
+ case SyntaxKind.VariableDeclaration:
+ case SyntaxKind.Property:
+ case SyntaxKind.PropertyAssignment:
+ case SyntaxKind.EnumMember:
+ case SyntaxKind.Method:
+ case SyntaxKind.FunctionDeclaration:
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ case SyntaxKind.FunctionExpression:
+ case SyntaxKind.ClassDeclaration:
+ case SyntaxKind.InterfaceDeclaration:
+ case SyntaxKind.EnumDeclaration:
+ case SyntaxKind.ModuleDeclaration:
+ case SyntaxKind.ImportDeclaration:
+ return (parent).name === node;
+ case SyntaxKind.BreakStatement:
+ case SyntaxKind.ContinueStatement:
+ case SyntaxKind.ExportAssignment:
+ return false;
+ case SyntaxKind.LabelledStatement:
+ return (node.parent).label === node;
+ case SyntaxKind.CatchBlock:
+ return (node.parent).variable === node;
+ }
}
- else {
- writeLine();
- }
- write("while (");
- emit(node.expression);
- write(");");
- }
- function emitWhileStatement(node: WhileStatement) {
- write("while (");
- emit(node.expression);
- write(")");
- emitEmbeddedStatement(node.statement);
- }
-
- function emitForStatement(node: ForStatement) {
- var endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
- write(" ");
- endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
- if (node.declarations) {
- emitToken(SyntaxKind.VarKeyword, endPos);
- write(" ");
- emitCommaList(node.declarations);
+ function emitIdentifier(node: Identifier) {
+ if (!isNonExpressionIdentifier(node)) {
+ var prefix = resolver.getExpressionNamePrefix(node);
+ if (prefix) {
+ write(prefix);
+ write(".");
+ }
+ }
+ write(getSourceTextOfLocalNode(node));
}
- if (node.initializer) {
+
+ function emitThis(node: Node) {
+ if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalThis) {
+ write("_this");
+ }
+ else {
+ write("this");
+ }
+ }
+
+ function emitSuper(node: Node) {
+ var flags = resolver.getNodeCheckFlags(node);
+ if (flags & NodeCheckFlags.SuperInstance) {
+ write("_super.prototype");
+ }
+ else if (flags & NodeCheckFlags.SuperStatic) {
+ write("_super");
+ }
+ else {
+ write("super");
+ }
+ }
+
+ function emitArrayLiteral(node: ArrayLiteral) {
+ if (node.flags & NodeFlags.MultiLine) {
+ write("[");
+ increaseIndent();
+ emitMultiLineList(node.elements);
+ decreaseIndent();
+ writeLine();
+ write("]");
+ }
+ else {
+ write("[");
+ emitCommaList(node.elements);
+ write("]");
+ }
+ }
+
+ function emitObjectLiteral(node: ObjectLiteral) {
+ if (!node.properties.length) {
+ write("{}");
+ }
+ else if (node.flags & NodeFlags.MultiLine) {
+ write("{");
+ increaseIndent();
+ emitMultiLineList(node.properties);
+ decreaseIndent();
+ writeLine();
+ write("}");
+ }
+ else {
+ write("{ ");
+ emitCommaList(node.properties);
+ write(" }");
+ }
+ }
+
+ function emitPropertyAssignment(node: PropertyDeclaration) {
+ emit(node.name);
+ write(": ");
emit(node.initializer);
}
- write(";");
- emitOptional(" ", node.condition);
- write(";");
- emitOptional(" ", node.iterator);
- write(")");
- emitEmbeddedStatement(node.statement);
- }
- function emitForInStatement(node: ForInStatement) {
- var endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
- write(" ");
- endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
- if (node.declaration) {
- emitToken(SyntaxKind.VarKeyword, endPos);
- write(" ");
- emit(node.declaration);
- }
- else {
- emit(node.variable);
- }
- write(" in ");
- emit(node.expression);
- emitToken(SyntaxKind.CloseParenToken, node.expression.end);
- emitEmbeddedStatement(node.statement);
- }
-
- function emitBreakOrContinueStatement(node: BreakOrContinueStatement) {
- emitToken(node.kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword, node.pos);
- emitOptional(" ", node.label);
- write(";");
- }
-
- function emitReturnStatement(node: ReturnStatement) {
- emitToken(SyntaxKind.ReturnKeyword, node.pos);
- emitOptional(" ", node.expression);
- write(";");
- }
-
- function emitWithStatement(node: WhileStatement) {
- write("with (");
- emit(node.expression);
- write(")");
- emitEmbeddedStatement(node.statement);
- }
-
- function emitSwitchStatement(node: SwitchStatement) {
- var endPos = emitToken(SyntaxKind.SwitchKeyword, node.pos);
- write(" ");
- emitToken(SyntaxKind.OpenParenToken, endPos);
- emit(node.expression);
- endPos = emitToken(SyntaxKind.CloseParenToken, node.expression.end);
- write(" ");
- emitToken(SyntaxKind.OpenBraceToken, endPos);
- increaseIndent();
- emitLines(node.clauses);
- decreaseIndent();
- writeLine();
- emitToken(SyntaxKind.CloseBraceToken, node.clauses.end);
- }
-
- function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
- if (node.kind === SyntaxKind.CaseClause) {
- write("case ");
- emit(node.expression);
- write(":");
- }
- else {
- write("default:");
- }
- increaseIndent();
- emitLines(node.statements);
- decreaseIndent();
- }
-
- function emitThrowStatement(node: ThrowStatement) {
- write("throw ");
- emit(node.expression);
- write(";");
- }
-
- function emitTryStatement(node: TryStatement) {
- write("try ");
- emit(node.tryBlock);
- emit(node.catchBlock);
- if (node.finallyBlock) {
- writeLine();
- write("finally ");
- emit(node.finallyBlock);
- }
- }
-
- function emitCatchBlock(node: CatchBlock) {
- writeLine();
- var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
- write(" ");
- emitToken(SyntaxKind.OpenParenToken, endPos);
- emit(node.variable);
- emitToken(SyntaxKind.CloseParenToken, node.variable.end);
- write(" ");
- emitBlock(node);
- }
-
- function emitDebuggerStatement(node: Node) {
- emitToken(SyntaxKind.DebuggerKeyword, node.pos);
- write(";");
- }
-
- function emitLabelledStatement(node: LabelledStatement) {
- emit(node.label);
- write(": ");
- emit(node.statement);
- }
-
- function getContainingModule(node: Node): ModuleDeclaration {
- do {
- node = node.parent;
- } while (node && node.kind !== SyntaxKind.ModuleDeclaration);
- return node;
- }
-
- function emitModuleMemberName(node: Declaration) {
- emitStart(node.name);
- if (node.flags & NodeFlags.Export) {
- var container = getContainingModule(node);
- write(container ? resolver.getModuleObjectName(container) : "exports");
- write(".");
- }
- emitNode(node.name);
- emitEnd(node.name);
- }
-
- function emitVariableDeclaration(node: VariableDeclaration) {
- emitModuleMemberName(node);
- emitOptional(" = ", node.initializer);
- }
-
- function emitVariableStatement(node: VariableStatement) {
- if (!(node.flags & NodeFlags.Export)) write("var ");
- emitCommaList(node.declarations);
- write(";");
- }
-
- function emitParameter(node: ParameterDeclaration) {
- emit(node.name);
- }
-
- function emitDefaultValueAssignments(node: FunctionDeclaration) {
- forEach(node.parameters, param => {
- if (param.initializer) {
- writeLine();
- emitStart(param);
- write("if (");
- emitNode(param.name);
- write(" === void 0)");
- emitEnd(param);
- write(" { ");
- emitStart(param);
- emitNode(param.name);
- write(" = ");
- emitNode(param.initializer);
- emitEnd(param);
- write("; }");
+ function emitPropertyAccess(node: PropertyAccess) {
+ var text = resolver.getPropertyAccessSubstitution(node);
+ if (text) {
+ write(text);
+ return;
}
- });
- }
+ emit(node.left);
+ write(".");
+ emit(node.right);
+ }
- function emitRestParameter(node: FunctionDeclaration) {
- if (hasRestParameters(node)) {
- var restIndex = node.parameters.length - 1;
- var restParam = node.parameters[restIndex];
- writeLine();
- emitStart(restParam);
- write("var ");
- emitNode(restParam.name);
- write(" = [];");
- emitEnd(restParam);
- writeLine();
- write("for (");
- emitStart(restParam);
- write("var _i = " + restIndex + ";");
- emitEnd(restParam);
+ function emitIndexedAccess(node: IndexedAccess) {
+ emit(node.object);
+ write("[");
+ emit(node.index);
+ write("]");
+ }
+
+ function emitCallExpression(node: CallExpression) {
+ var superCall = false;
+ if (node.func.kind === SyntaxKind.SuperKeyword) {
+ write("_super");
+ superCall = true;
+ }
+ else {
+ emit(node.func);
+ superCall = node.func.kind === SyntaxKind.PropertyAccess && (node.func).left.kind === SyntaxKind.SuperKeyword;
+ }
+ if (superCall) {
+ write(".call(");
+ emitThis(node.func);
+ if (node.arguments.length) {
+ write(", ");
+ emitCommaList(node.arguments);
+ }
+ write(")");
+ }
+ else {
+ write("(");
+ emitCommaList(node.arguments);
+ write(")");
+ }
+ }
+
+ function emitNewExpression(node: NewExpression) {
+ write("new ");
+ emit(node.func);
+ if (node.arguments) {
+ write("(");
+ emitCommaList(node.arguments);
+ write(")");
+ }
+ }
+
+ function emitParenExpression(node: ParenExpression) {
+ if (node.expression.kind === SyntaxKind.TypeAssertion) {
+ var operand = (node.expression).operand;
+
+ // Make sure we consider all nested cast expressions, e.g.:
+ // (-A).x;
+ while (operand.kind == SyntaxKind.TypeAssertion) {
+ operand = (operand).operand;
+ }
+
+ // We have an expression of the form: (SubExpr)
+ // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
+ // Omitting the parentheses, however, could cause change in the semantics of the generated
+ // code if the casted expression has a lower precedence than the rest of the expression, e.g.:
+ // (new A).foo should be emitted as (new A).foo and not new A.foo
+ // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
+ // new (A()) should be emitted as new (A()) and not new A()
+ // (function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
+ if (operand.kind !== SyntaxKind.PrefixOperator && operand.kind !== SyntaxKind.PostfixOperator && operand.kind !== SyntaxKind.NewExpression &&
+ !(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
+ !(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression)) {
+ emit(operand);
+ return;
+ }
+ }
+ write("(");
+ emit(node.expression);
+ write(")");
+ }
+
+ function emitUnaryExpression(node: UnaryExpression) {
+ if (node.kind === SyntaxKind.PrefixOperator) {
+ write(tokenToString(node.operator));
+ }
+ // In some cases, we need to emit a space between the operator and the operand. One obvious case
+ // is when the operator is an identifer, like delete or typeof. We also need to do this for plus
+ // and minus expressions in certain cases. Specifically, consider the following two cases (parens
+ // are just for clarity of exposition, and not part of the source code):
+ //
+ // (+(+1))
+ // (+(++1))
+ //
+ // We need to emit a space in both cases. In the first case, the absence of a space will make
+ // the resulting expression a prefix increment operation. And in the second, it will make the resulting
+ // expression a prefix increment whose operand is a plus expression - (++(+x))
+ // The same is true of minus of course.
+ if (node.operator >= SyntaxKind.Identifier) {
+ write(" ");
+ }
+ else if (node.kind === SyntaxKind.PrefixOperator && node.operand.kind === SyntaxKind.PrefixOperator) {
+ var operand = node.operand;
+ if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
+ write(" ");
+ }
+ else if (node.operator === SyntaxKind.MinusToken && (operand.operator === SyntaxKind.MinusToken || operand.operator === SyntaxKind.MinusMinusToken)) {
+ write(" ");
+ }
+ }
+ emit(node.operand);
+ if (node.kind === SyntaxKind.PostfixOperator) {
+ write(tokenToString(node.operator));
+ }
+ }
+
+ function emitBinaryExpression(node: BinaryExpression) {
+ emit(node.left);
+ if (node.operator !== SyntaxKind.CommaToken) write(" ");
+ write(tokenToString(node.operator));
write(" ");
- emitStart(restParam);
- write("_i < arguments.length;");
- emitEnd(restParam);
- write(" ");
- emitStart(restParam);
- write("_i++");
- emitEnd(restParam);
- write(") {");
+ emit(node.right);
+ }
+
+ function emitConditionalExpression(node: ConditionalExpression) {
+ emit(node.condition);
+ write(" ? ");
+ emit(node.whenTrue);
+ write(" : ");
+ emit(node.whenFalse);
+ }
+
+ function emitBlock(node: Block) {
+ emitToken(SyntaxKind.OpenBraceToken, node.pos);
increaseIndent();
- writeLine();
- emitStart(restParam);
- emitNode(restParam.name);
- write("[_i - " + restIndex + "] = arguments[_i];");
- emitEnd(restParam);
+ scopeEmitStart(node.parent);
+ if (node.kind === SyntaxKind.ModuleBlock) {
+ Debug.assert(node.parent.kind === SyntaxKind.ModuleDeclaration);
+ emitCaptureThisForNodeIfNecessary(node.parent);
+ }
+ emitLines(node.statements);
decreaseIndent();
writeLine();
- write("}");
+ emitToken(SyntaxKind.CloseBraceToken, node.statements.end);
+ scopeEmitEnd();
}
- }
- function emitAccessor(node: AccessorDeclaration) {
- write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
- emit(node.name);
- emitSignatureAndBody(node);
- }
+ function emitEmbeddedStatement(node: Node) {
+ if (node.kind === SyntaxKind.Block) {
+ write(" ");
+ emit(node);
+ }
+ else {
+ increaseIndent();
+ writeLine();
+ emit(node);
+ decreaseIndent();
+ }
+ }
- function emitFunctionDeclaration(node: FunctionDeclaration) {
- if (!node.body) return;
- write("function ");
- if (node.kind === SyntaxKind.FunctionDeclaration || (node.kind === SyntaxKind.FunctionExpression && node.name)) {
+ function emitExpressionStatement(node: ExpressionStatement) {
+ var isArrowExpression = node.expression.kind === SyntaxKind.ArrowFunction;
+ if (isArrowExpression) write("(");
+ emit(node.expression);
+ if (isArrowExpression) write(")");
+ write(";");
+ }
+
+ function emitIfStatement(node: IfStatement) {
+ var endPos = emitToken(SyntaxKind.IfKeyword, node.pos);
+ write(" ");
+ endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+ emit(node.expression);
+ emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+ emitEmbeddedStatement(node.thenStatement);
+ if (node.elseStatement) {
+ writeLine();
+ emitToken(SyntaxKind.ElseKeyword, node.thenStatement.end);
+ if (node.elseStatement.kind === SyntaxKind.IfStatement) {
+ write(" ");
+ emit(node.elseStatement);
+ }
+ else {
+ emitEmbeddedStatement(node.elseStatement);
+ }
+ }
+ }
+
+ function emitDoStatement(node: DoStatement) {
+ write("do");
+ emitEmbeddedStatement(node.statement);
+ if (node.statement.kind === SyntaxKind.Block) {
+ write(" ");
+ }
+ else {
+ writeLine();
+ }
+ write("while (");
+ emit(node.expression);
+ write(");");
+ }
+
+ function emitWhileStatement(node: WhileStatement) {
+ write("while (");
+ emit(node.expression);
+ write(")");
+ emitEmbeddedStatement(node.statement);
+ }
+
+ function emitForStatement(node: ForStatement) {
+ var endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
+ write(" ");
+ endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+ if (node.declarations) {
+ emitToken(SyntaxKind.VarKeyword, endPos);
+ write(" ");
+ emitCommaList(node.declarations);
+ }
+ if (node.initializer) {
+ emit(node.initializer);
+ }
+ write(";");
+ emitOptional(" ", node.condition);
+ write(";");
+ emitOptional(" ", node.iterator);
+ write(")");
+ emitEmbeddedStatement(node.statement);
+ }
+
+ function emitForInStatement(node: ForInStatement) {
+ var endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
+ write(" ");
+ endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+ if (node.declaration) {
+ emitToken(SyntaxKind.VarKeyword, endPos);
+ write(" ");
+ emit(node.declaration);
+ }
+ else {
+ emit(node.variable);
+ }
+ write(" in ");
+ emit(node.expression);
+ emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+ emitEmbeddedStatement(node.statement);
+ }
+
+ function emitBreakOrContinueStatement(node: BreakOrContinueStatement) {
+ emitToken(node.kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword, node.pos);
+ emitOptional(" ", node.label);
+ write(";");
+ }
+
+ function emitReturnStatement(node: ReturnStatement) {
+ emitToken(SyntaxKind.ReturnKeyword, node.pos);
+ emitOptional(" ", node.expression);
+ write(";");
+ }
+
+ function emitWithStatement(node: WhileStatement) {
+ write("with (");
+ emit(node.expression);
+ write(")");
+ emitEmbeddedStatement(node.statement);
+ }
+
+ function emitSwitchStatement(node: SwitchStatement) {
+ var endPos = emitToken(SyntaxKind.SwitchKeyword, node.pos);
+ write(" ");
+ emitToken(SyntaxKind.OpenParenToken, endPos);
+ emit(node.expression);
+ endPos = emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+ write(" ");
+ emitToken(SyntaxKind.OpenBraceToken, endPos);
+ increaseIndent();
+ emitLines(node.clauses);
+ decreaseIndent();
+ writeLine();
+ emitToken(SyntaxKind.CloseBraceToken, node.clauses.end);
+ }
+
+ function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
+ if (node.kind === SyntaxKind.CaseClause) {
+ write("case ");
+ emit(node.expression);
+ write(":");
+ }
+ else {
+ write("default:");
+ }
+ increaseIndent();
+ emitLines(node.statements);
+ decreaseIndent();
+ }
+
+ function emitThrowStatement(node: ThrowStatement) {
+ write("throw ");
+ emit(node.expression);
+ write(";");
+ }
+
+ function emitTryStatement(node: TryStatement) {
+ write("try ");
+ emit(node.tryBlock);
+ emit(node.catchBlock);
+ if (node.finallyBlock) {
+ writeLine();
+ write("finally ");
+ emit(node.finallyBlock);
+ }
+ }
+
+ function emitCatchBlock(node: CatchBlock) {
+ writeLine();
+ var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
+ write(" ");
+ emitToken(SyntaxKind.OpenParenToken, endPos);
+ emit(node.variable);
+ emitToken(SyntaxKind.CloseParenToken, node.variable.end);
+ write(" ");
+ emitBlock(node);
+ }
+
+ function emitDebuggerStatement(node: Node) {
+ emitToken(SyntaxKind.DebuggerKeyword, node.pos);
+ write(";");
+ }
+
+ function emitLabelledStatement(node: LabelledStatement) {
+ emit(node.label);
+ write(": ");
+ emit(node.statement);
+ }
+
+ function getContainingModule(node: Node): ModuleDeclaration {
+ do {
+ node = node.parent;
+ } while (node && node.kind !== SyntaxKind.ModuleDeclaration);
+ return node;
+ }
+
+ function emitModuleMemberName(node: Declaration) {
+ emitStart(node.name);
+ if (node.flags & NodeFlags.Export) {
+ var container = getContainingModule(node);
+ write(container ? resolver.getModuleObjectName(container) : "exports");
+ write(".");
+ }
+ emitNode(node.name);
+ emitEnd(node.name);
+ }
+
+ function emitVariableDeclaration(node: VariableDeclaration) {
+ emitModuleMemberName(node);
+ emitOptional(" = ", node.initializer);
+ }
+
+ function emitVariableStatement(node: VariableStatement) {
+ if (!(node.flags & NodeFlags.Export)) write("var ");
+ emitCommaList(node.declarations);
+ write(";");
+ }
+
+ function emitParameter(node: ParameterDeclaration) {
emit(node.name);
}
- emitSignatureAndBody(node);
- }
- function emitCaptureThisForNodeIfNecessary(node: Node): void {
- if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureThis) {
- writeLine();
- emitStart(node);
- write("var _this = this;");
- emitEnd(node);
+ function emitDefaultValueAssignments(node: FunctionDeclaration) {
+ forEach(node.parameters, param => {
+ if (param.initializer) {
+ writeLine();
+ emitStart(param);
+ write("if (");
+ emitNode(param.name);
+ write(" === void 0)");
+ emitEnd(param);
+ write(" { ");
+ emitStart(param);
+ emitNode(param.name);
+ write(" = ");
+ emitNode(param.initializer);
+ emitEnd(param);
+ write("; }");
+ }
+ });
}
- }
- function emitSignatureAndBody(node: FunctionDeclaration) {
- write("(");
- emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
- write(") {");
- scopeEmitStart(node);
- increaseIndent();
- var outPos = writer.getTextPos();
- emitCaptureThisForNodeIfNecessary(node);
- emitDefaultValueAssignments(node);
- emitRestParameter(node);
- if (node.body.kind !== SyntaxKind.FunctionBlock && outPos === writer.getTextPos()) {
- decreaseIndent();
- write(" ");
- emitStart(node.body);
- write("return ");
- emitNode(node.body);
- emitEnd(node.body);
- write("; ");
- emitStart(node.body);
- write("}");
- emitEnd(node.body);
- }
- else {
- if (node.body.kind === SyntaxKind.FunctionBlock) {
- emitLines((node.body).statements);
- }
- else {
+ function emitRestParameter(node: FunctionDeclaration) {
+ if (hasRestParameters(node)) {
+ var restIndex = node.parameters.length - 1;
+ var restParam = node.parameters[restIndex];
writeLine();
+ emitStart(restParam);
+ write("var ");
+ emitNode(restParam.name);
+ write(" = [];");
+ emitEnd(restParam);
+ writeLine();
+ write("for (");
+ emitStart(restParam);
+ write("var _i = " + restIndex + ";");
+ emitEnd(restParam);
+ write(" ");
+ emitStart(restParam);
+ write("_i < arguments.length;");
+ emitEnd(restParam);
+ write(" ");
+ emitStart(restParam);
+ write("_i++");
+ emitEnd(restParam);
+ write(") {");
+ increaseIndent();
+ writeLine();
+ emitStart(restParam);
+ emitNode(restParam.name);
+ write("[_i - " + restIndex + "] = arguments[_i];");
+ emitEnd(restParam);
+ decreaseIndent();
+ writeLine();
+ write("}");
+ }
+ }
+
+ function emitAccessor(node: AccessorDeclaration) {
+ write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
+ emit(node.name);
+ emitSignatureAndBody(node);
+ }
+
+ function emitFunctionDeclaration(node: FunctionDeclaration) {
+ if (!node.body) return;
+ write("function ");
+ if (node.kind === SyntaxKind.FunctionDeclaration || (node.kind === SyntaxKind.FunctionExpression && node.name)) {
+ emit(node.name);
+ }
+ emitSignatureAndBody(node);
+ }
+
+ function emitCaptureThisForNodeIfNecessary(node: Node): void {
+ if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureThis) {
+ writeLine();
+ emitStart(node);
+ write("var _this = this;");
+ emitEnd(node);
+ }
+ }
+
+ function emitSignatureAndBody(node: FunctionDeclaration) {
+ write("(");
+ emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
+ write(") {");
+ scopeEmitStart(node);
+ increaseIndent();
+ var outPos = writer.getTextPos();
+ emitCaptureThisForNodeIfNecessary(node);
+ emitDefaultValueAssignments(node);
+ emitRestParameter(node);
+ if (node.body.kind !== SyntaxKind.FunctionBlock && outPos === writer.getTextPos()) {
+ decreaseIndent();
+ write(" ");
+ emitStart(node.body);
write("return ");
- emit(node.body);
- write(";");
- }
- decreaseIndent();
- writeLine();
- if (node.body.kind === SyntaxKind.FunctionBlock) {
- emitToken(SyntaxKind.CloseBraceToken, (node.body).statements.end);
- }
- else {
+ emitNode(node.body);
+ emitEnd(node.body);
+ write("; ");
emitStart(node.body);
write("}");
emitEnd(node.body);
}
+ else {
+ if (node.body.kind === SyntaxKind.FunctionBlock) {
+ emitLines((node.body).statements);
+ }
+ else {
+ writeLine();
+ write("return ");
+ emit(node.body);
+ write(";");
+ }
+ decreaseIndent();
+ writeLine();
+ if (node.body.kind === SyntaxKind.FunctionBlock) {
+ emitToken(SyntaxKind.CloseBraceToken, (node.body).statements.end);
+ }
+ else {
+ emitStart(node.body);
+ write("}");
+ emitEnd(node.body);
+ }
+ }
+ scopeEmitEnd();
+ if (node.flags & NodeFlags.Export) {
+ writeLine();
+ emitStart(node);
+ emitModuleMemberName(node);
+ write(" = ");
+ emit(node.name);
+ emitEnd(node);
+ write(";");
+ }
}
- scopeEmitEnd();
- if (node.flags & NodeFlags.Export) {
- writeLine();
- emitStart(node);
- emitModuleMemberName(node);
- write(" = ");
- emit(node.name);
- emitEnd(node);
- write(";");
- }
- }
- function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
- if (ctor.body) {
- var statement = (ctor.body).statements[0];
- if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
- var expr = (statement).expression;
- if (expr && expr.kind === SyntaxKind.CallExpression) {
- var func = (expr).func;
- if (func && func.kind === SyntaxKind.SuperKeyword) {
- return statement;
+ function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
+ if (ctor.body) {
+ var statement = (ctor.body).statements[0];
+ if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
+ var expr = (statement).expression;
+ if (expr && expr.kind === SyntaxKind.CallExpression) {
+ var func = (expr).func;
+ if (func && func.kind === SyntaxKind.SuperKeyword) {
+ return statement;
+ }
}
}
}
}
- }
- function emitParameterPropertyAssignments(node: ConstructorDeclaration) {
- forEach(node.parameters, param => {
- if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
- writeLine();
- emitStart(param);
- emitStart(param.name);
- write("this.");
- emitNode(param.name);
- emitEnd(param.name);
- write(" = ");
- emit(param.name);
- write(";");
- emitEnd(param);
- }
- });
- }
-
- function emitMemberAccess(memberName: Identifier) {
- if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) {
- write("[");
- emitNode(memberName);
- write("]");
+ function emitParameterPropertyAssignments(node: ConstructorDeclaration) {
+ forEach(node.parameters, param => {
+ if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
+ writeLine();
+ emitStart(param);
+ emitStart(param.name);
+ write("this.");
+ emitNode(param.name);
+ emitEnd(param.name);
+ write(" = ");
+ emit(param.name);
+ write(";");
+ emitEnd(param);
+ }
+ });
}
- else {
- write(".");
- emitNode(memberName);
+
+ function emitMemberAccess(memberName: Identifier) {
+ if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) {
+ write("[");
+ emitNode(memberName);
+ write("]");
+ }
+ else {
+ write(".");
+ emitNode(memberName);
+ }
}
- }
- function emitMemberAssignments(node: ClassDeclaration, staticFlag: NodeFlags) {
- forEach(node.members, member => {
- if (member.kind === SyntaxKind.Property && (member.flags & NodeFlags.Static) === staticFlag && (member).initializer) {
- writeLine();
- emitStart(member);
- emitStart((member).name);
- if (staticFlag) {
- emitNode(node.name);
- }
- else {
- write("this");
- }
- emitMemberAccess((member).name);
- emitEnd((member).name);
- write(" = ");
- emit((member).initializer);
- write(";");
- emitEnd(member);
- }
- });
- }
-
- function emitMemberFunctions(node: ClassDeclaration) {
- forEach(node.members, member => {
- if (member.kind === SyntaxKind.Method) {
- if (!(member).body) return;
- writeLine();
- emitStart(member);
- emitStart((member).name);
- emitNode(node.name);
- if (!(member.flags & NodeFlags.Static)) {
- write(".prototype");
- }
- emitMemberAccess((member).name);
- emitEnd((member).name);
- write(" = ");
- emitStart(member);
- emitFunctionDeclaration(member);
- emitEnd(member);
- emitEnd(member);
- write(";");
- }
- else if (member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) {
- var accessors = getAllAccessorDeclarations(node, member);
- if (member === accessors.firstAccessor) {
+ function emitMemberAssignments(node: ClassDeclaration, staticFlag: NodeFlags) {
+ forEach(node.members, member => {
+ if (member.kind === SyntaxKind.Property && (member.flags & NodeFlags.Static) === staticFlag && (member).initializer) {
writeLine();
emitStart(member);
- write("Object.defineProperty(");
- emitStart((member).name);
+ emitStart((member).name);
+ if (staticFlag) {
+ emitNode(node.name);
+ }
+ else {
+ write("this");
+ }
+ emitMemberAccess((member).name);
+ emitEnd((member).name);
+ write(" = ");
+ emit((member).initializer);
+ write(";");
+ emitEnd(member);
+ }
+ });
+ }
+
+ function emitMemberFunctions(node: ClassDeclaration) {
+ forEach(node.members, member => {
+ if (member.kind === SyntaxKind.Method) {
+ if (!(member).body) return;
+ writeLine();
+ emitStart(member);
+ emitStart((member).name);
emitNode(node.name);
if (!(member.flags & NodeFlags.Static)) {
write(".prototype");
}
- write(", ");
- emitQuotedIdentifier((member).name);
- emitEnd((member).name);
- write(", {");
- increaseIndent();
- if (accessors.getAccessor) {
- writeLine();
- write("get: ");
- emitStart(accessors.getAccessor);
- write("function ");
- emitSignatureAndBody(accessors.getAccessor);
- emitEnd(accessors.getAccessor);
- write(",");
- }
- if (accessors.setAccessor) {
- writeLine();
- write("set: ");
- emitStart(accessors.setAccessor);
- write("function ");
- emitSignatureAndBody(accessors.setAccessor);
- emitEnd(accessors.setAccessor);
- write(",");
- }
- writeLine();
- write("enumerable: true,");
- writeLine();
- write("configurable: true");
- decreaseIndent();
- writeLine();
- write("});");
+ emitMemberAccess((member).name);
+ emitEnd((member).name);
+ write(" = ");
+ emitStart(member);
+ emitFunctionDeclaration(member);
emitEnd(member);
+ emitEnd(member);
+ write(";");
}
- }
- });
- }
+ else if (member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) {
+ var accessors = getAllAccessorDeclarations(node, member);
+ if (member === accessors.firstAccessor) {
+ writeLine();
+ emitStart(member);
+ write("Object.defineProperty(");
+ emitStart((member).name);
+ emitNode(node.name);
+ if (!(member.flags & NodeFlags.Static)) {
+ write(".prototype");
+ }
+ write(", ");
+ emitQuotedIdentifier((member).name);
+ emitEnd((member).name);
+ write(", {");
+ increaseIndent();
+ if (accessors.getAccessor) {
+ writeLine();
+ write("get: ");
+ emitStart(accessors.getAccessor);
+ write("function ");
+ emitSignatureAndBody(accessors.getAccessor);
+ emitEnd(accessors.getAccessor);
+ write(",");
+ }
+ if (accessors.setAccessor) {
+ writeLine();
+ write("set: ");
+ emitStart(accessors.setAccessor);
+ write("function ");
+ emitSignatureAndBody(accessors.setAccessor);
+ emitEnd(accessors.setAccessor);
+ write(",");
+ }
+ writeLine();
+ write("enumerable: true,");
+ writeLine();
+ write("configurable: true");
+ decreaseIndent();
+ writeLine();
+ write("});");
+ emitEnd(member);
+ }
+ }
+ });
+ }
- function emitClassDeclaration(node: ClassDeclaration) {
- var ctor = getFirstConstructorWithBody(node);
- write("var ");
- emit(node.name);
- write(" = (function (");
- if (node.baseType) write("_super");
- write(") {");
- increaseIndent();
- scopeEmitStart(node);
- if (node.baseType) {
- writeLine();
- emitStart(node.baseType);
- write("__extends(");
+ function emitClassDeclaration(node: ClassDeclaration) {
+ var ctor = getFirstConstructorWithBody(node);
+ write("var ");
emit(node.name);
- write(", _super);");
- emitEnd(node.baseType);
- }
- writeLine();
- emitStart(ctor || node);
- write("function ");
- emit(node.name);
- write("(");
- if (ctor) {
- emitCommaList(ctor.parameters);
- }
- write(") {");
- scopeEmitStart(node, "constructor");
- increaseIndent();
- if (ctor) {
- emitDefaultValueAssignments(ctor);
- emitRestParameter(ctor);
- if (node.baseType) {
- var superCall = findInitialSuperCall(ctor);
- if (superCall) {
- writeLine();
- emit(superCall);
- }
- }
- emitParameterPropertyAssignments(ctor);
- }
- else {
+ write(" = (function (");
+ if (node.baseType) write("_super");
+ write(") {");
+ increaseIndent();
+ scopeEmitStart(node);
if (node.baseType) {
writeLine();
emitStart(node.baseType);
- write("_super.apply(this, arguments);");
+ write("__extends(");
+ emit(node.name);
+ write(", _super);");
emitEnd(node.baseType);
}
- }
- emitCaptureThisForNodeIfNecessary(node);
- emitMemberAssignments(node, /*nonstatic*/0);
- if (ctor) {
- var statements: Node[] = (ctor.body).statements;
- if (superCall) statements = statements.slice(1);
- emitLines(statements);
- }
- decreaseIndent();
- writeLine();
- emitToken(SyntaxKind.CloseBraceToken, ctor ? (ctor.body).statements.end : node.members.end);
- scopeEmitEnd();
- emitEnd(ctor || node);
- emitMemberFunctions(node);
- emitMemberAssignments(node, NodeFlags.Static);
- writeLine();
- function emitClassReturnStatement() {
- write("return ");
- emitNode(node.name);
- }
- emitToken(SyntaxKind.CloseBraceToken, node.members.end, emitClassReturnStatement);
- write(";");
- decreaseIndent();
- writeLine();
- emitToken(SyntaxKind.CloseBraceToken, node.members.end);
- scopeEmitEnd();
- emitStart(node);
- write(")(");
- if (node.baseType) {
- emit(node.baseType.typeName);
- }
- write(");");
- emitEnd(node);
- if (node.flags & NodeFlags.Export) {
writeLine();
- emitStart(node);
- emitModuleMemberName(node);
- write(" = ");
+ emitStart(ctor || node);
+ write("function ");
emit(node.name);
- emitEnd(node);
- write(";");
- }
- }
-
- function emitEnumDeclaration(node: EnumDeclaration) {
- if (!(node.flags & NodeFlags.Export)) {
- emitStart(node);
- write("var ");
- emit(node.name);
- emitEnd(node);
- write(";");
- }
- writeLine();
- emitStart(node);
- write("(function (");
- emit(node.name);
- write(") {");
- increaseIndent();
- scopeEmitStart(node);
- forEach(node.members, member => {
- writeLine();
- emitStart(member);
- emitNode(node.name);
- write("[");
- emitNode(node.name);
- write("[");
- emitQuotedIdentifier(member.name);
- write("] = ");
- if (member.initializer) {
- emit(member.initializer);
+ write("(");
+ if (ctor) {
+ emitCommaList(ctor.parameters);
+ }
+ write(") {");
+ scopeEmitStart(node, "constructor");
+ increaseIndent();
+ if (ctor) {
+ emitDefaultValueAssignments(ctor);
+ emitRestParameter(ctor);
+ if (node.baseType) {
+ var superCall = findInitialSuperCall(ctor);
+ if (superCall) {
+ writeLine();
+ emit(superCall);
+ }
+ }
+ emitParameterPropertyAssignments(ctor);
}
else {
- write(resolver.getEnumMemberValue(member).toString());
+ if (node.baseType) {
+ writeLine();
+ emitStart(node.baseType);
+ write("_super.apply(this, arguments);");
+ emitEnd(node.baseType);
+ }
}
- write("] = ");
- emitQuotedIdentifier(member.name);
- emitEnd(member);
- write(";");
- });
- decreaseIndent();
- writeLine();
- emitToken(SyntaxKind.CloseBraceToken, node.members.end);
- scopeEmitEnd();
- write(")(");
- emitModuleMemberName(node);
- write(" || (");
- emitModuleMemberName(node);
- write(" = {}));");
- emitEnd(node);
- if (node.flags & NodeFlags.Export) {
- writeLine();
- emitStart(node);
- write("var ");
- emit(node.name);
- write(" = ");
- emitModuleMemberName(node);
- emitEnd(node);
- write(";");
- }
- }
-
- function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration {
- if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
- var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body);
- return recursiveInnerModule || moduleDeclaration.body;
- }
- }
-
- function emitModuleDeclaration(node: ModuleDeclaration) {
- if (!isInstantiated(node)) return;
- if (!(node.flags & NodeFlags.Export)) {
- emitStart(node);
- write("var ");
- emit(node.name);
- write(";");
- emitEnd(node);
- writeLine();
- }
- emitStart(node);
- write("(function (");
- emit(node.name);
- write(") ");
- if (node.body.kind === SyntaxKind.ModuleBlock) {
- emit(node.body);
- }
- else {
- write("{");
- increaseIndent();
- scopeEmitStart(node);
emitCaptureThisForNodeIfNecessary(node);
- writeLine();
- emit(node.body);
+ emitMemberAssignments(node, /*nonstatic*/0);
+ if (ctor) {
+ var statements: Node[] = (ctor.body).statements;
+ if (superCall) statements = statements.slice(1);
+ emitLines(statements);
+ }
decreaseIndent();
writeLine();
- var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body;
- emitToken(SyntaxKind.CloseBraceToken, moduleBlock.statements.end);
+ emitToken(SyntaxKind.CloseBraceToken, ctor ? (ctor.body).statements.end : node.members.end);
scopeEmitEnd();
+ emitEnd(ctor || node);
+ emitMemberFunctions(node);
+ emitMemberAssignments(node, NodeFlags.Static);
+ writeLine();
+ function emitClassReturnStatement() {
+ write("return ");
+ emitNode(node.name);
+ }
+ emitToken(SyntaxKind.CloseBraceToken, node.members.end, emitClassReturnStatement);
+ write(";");
+ decreaseIndent();
+ writeLine();
+ emitToken(SyntaxKind.CloseBraceToken, node.members.end);
+ scopeEmitEnd();
+ emitStart(node);
+ write(")(");
+ if (node.baseType) {
+ emit(node.baseType.typeName);
+ }
+ write(");");
+ emitEnd(node);
+ if (node.flags & NodeFlags.Export) {
+ writeLine();
+ emitStart(node);
+ emitModuleMemberName(node);
+ write(" = ");
+ emit(node.name);
+ emitEnd(node);
+ write(";");
+ }
}
- write(")(");
- emitModuleMemberName(node);
- write(" || (");
- emitModuleMemberName(node);
- write(" = {}));");
- emitEnd(node);
- if (node.flags & NodeFlags.Export) {
+
+ function emitEnumDeclaration(node: EnumDeclaration) {
+ if (!(node.flags & NodeFlags.Export)) {
+ emitStart(node);
+ write("var ");
+ emit(node.name);
+ emitEnd(node);
+ write(";");
+ }
writeLine();
emitStart(node);
- write("var ");
+ write("(function (");
emit(node.name);
- write(" = ");
+ write(") {");
+ increaseIndent();
+ scopeEmitStart(node);
+ forEach(node.members, member => {
+ writeLine();
+ emitStart(member);
+ emitNode(node.name);
+ write("[");
+ emitNode(node.name);
+ write("[");
+ emitQuotedIdentifier(member.name);
+ write("] = ");
+ if (member.initializer) {
+ emit(member.initializer);
+ }
+ else {
+ write(resolver.getEnumMemberValue(member).toString());
+ }
+ write("] = ");
+ emitQuotedIdentifier(member.name);
+ emitEnd(member);
+ write(";");
+ });
+ decreaseIndent();
+ writeLine();
+ emitToken(SyntaxKind.CloseBraceToken, node.members.end);
+ scopeEmitEnd();
+ write(")(");
emitModuleMemberName(node);
+ write(" || (");
+ emitModuleMemberName(node);
+ write(" = {}));");
emitEnd(node);
- write(";");
- }
- }
-
- function emitImportDeclaration(node: ImportDeclaration) {
- var emitImportDeclaration = resolver.isReferencedImportDeclaration(node);
-
- if (!emitImportDeclaration) {
- // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
- // - current file is not external module
- // - import declaration is top level and target is value imported by entity name
- emitImportDeclaration = !(currentSourceFile.flags & NodeFlags.ExternalModule) && resolver.isTopLevelValueImportedViaEntityName(node);
+ if (node.flags & NodeFlags.Export) {
+ writeLine();
+ emitStart(node);
+ write("var ");
+ emit(node.name);
+ write(" = ");
+ emitModuleMemberName(node);
+ emitEnd(node);
+ write(";");
+ }
}
- if (emitImportDeclaration) {
- if (node.externalModuleName && node.parent.kind === SyntaxKind.SourceFile && compilerOptions.module === ModuleKind.AMD) {
- if (node.flags & NodeFlags.Export) {
+ function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration {
+ if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
+ var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body);
+ return recursiveInnerModule || moduleDeclaration.body;
+ }
+ }
+
+ function emitModuleDeclaration(node: ModuleDeclaration) {
+ if (!isInstantiated(node)) return;
+ if (!(node.flags & NodeFlags.Export)) {
+ emitStart(node);
+ write("var ");
+ emit(node.name);
+ write(";");
+ emitEnd(node);
+ writeLine();
+ }
+ emitStart(node);
+ write("(function (");
+ emit(node.name);
+ write(") ");
+ if (node.body.kind === SyntaxKind.ModuleBlock) {
+ emit(node.body);
+ }
+ else {
+ write("{");
+ increaseIndent();
+ scopeEmitStart(node);
+ emitCaptureThisForNodeIfNecessary(node);
+ writeLine();
+ emit(node.body);
+ decreaseIndent();
+ writeLine();
+ var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body;
+ emitToken(SyntaxKind.CloseBraceToken, moduleBlock.statements.end);
+ scopeEmitEnd();
+ }
+ write(")(");
+ emitModuleMemberName(node);
+ write(" || (");
+ emitModuleMemberName(node);
+ write(" = {}));");
+ emitEnd(node);
+ if (node.flags & NodeFlags.Export) {
+ writeLine();
+ emitStart(node);
+ write("var ");
+ emit(node.name);
+ write(" = ");
+ emitModuleMemberName(node);
+ emitEnd(node);
+ write(";");
+ }
+ }
+
+ function emitImportDeclaration(node: ImportDeclaration) {
+ var emitImportDeclaration = resolver.isReferencedImportDeclaration(node);
+
+ if (!emitImportDeclaration) {
+ // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
+ // - current file is not external module
+ // - import declaration is top level and target is value imported by entity name
+ emitImportDeclaration = !(currentSourceFile.flags & NodeFlags.ExternalModule) && resolver.isTopLevelValueImportedViaEntityName(node);
+ }
+
+ if (emitImportDeclaration) {
+ if (node.externalModuleName && node.parent.kind === SyntaxKind.SourceFile && compilerOptions.module === ModuleKind.AMD) {
+ if (node.flags & NodeFlags.Export) {
+ writeLine();
+ emitStart(node);
+ emitModuleMemberName(node);
+ write(" = ");
+ emit(node.name);
+ write(";");
+ emitEnd(node);
+ }
+ }
+ else {
writeLine();
emitStart(node);
+ if (!(node.flags & NodeFlags.Export)) write("var ");
emitModuleMemberName(node);
write(" = ");
- emit(node.name);
+ if (node.entityName) {
+ emit(node.entityName);
+ }
+ else {
+ write("require(");
+ emitStart(node.externalModuleName);
+ emitLiteral(node.externalModuleName);
+ emitEnd(node.externalModuleName);
+ emitToken(SyntaxKind.CloseParenToken, node.externalModuleName.end);
+ }
write(";");
emitEnd(node);
}
}
- else {
- writeLine();
- emitStart(node);
- if (!(node.flags & NodeFlags.Export)) write("var ");
- emitModuleMemberName(node);
- write(" = ");
- if (node.entityName) {
- emit(node.entityName);
+ }
+
+ function getExternalImportDeclarations(node: SourceFile): ImportDeclaration[] {
+ var result: ImportDeclaration[] = [];
+ forEach(node.statements, stat => {
+ if (stat.kind === SyntaxKind.ImportDeclaration && (stat).externalModuleName && resolver.isReferencedImportDeclaration(stat)) {
+ result.push(stat);
}
- else {
- write("require(");
- emitStart(node.externalModuleName);
- emitLiteral(node.externalModuleName);
- emitEnd(node.externalModuleName);
- emitToken(SyntaxKind.CloseParenToken, node.externalModuleName.end);
+ });
+ return result;
+ }
+
+ function getFirstExportAssignment(sourceFile: SourceFile) {
+ return forEach(sourceFile.statements, node => {
+ if (node.kind === SyntaxKind.ExportAssignment) {
+ return node;
}
- write(";");
- emitEnd(node);
- }
+ });
}
- }
- function getExternalImportDeclarations(node: SourceFile): ImportDeclaration[]{
- var result: ImportDeclaration[] = [];
- forEach(node.statements, stat => {
- if (stat.kind === SyntaxKind.ImportDeclaration && (stat).externalModuleName && resolver.isReferencedImportDeclaration(stat)) {
- result.push(stat);
- }
- });
- return result;
- }
-
- function getFirstExportAssignment(sourceFile: SourceFile) {
- return forEach(sourceFile.statements, node => {
- if (node.kind === SyntaxKind.ExportAssignment) {
- return node;
- }
- });
- }
-
- function emitAMDModule(node: SourceFile) {
- var imports = getExternalImportDeclarations(node);
- writeLine();
- write("define([\"require\", \"exports\"");
- forEach(imports, imp => {
- write(", ");
- emitLiteral(imp.externalModuleName);
- });
- forEach(node.amdDependencies, amdDependency => {
- var text = "\"" + amdDependency + "\"";
- write(", ");
- write(text);
- });
- write("], function (require, exports");
- forEach(imports, imp => {
- write(", ");
- emit(imp.name);
- });
- write(") {");
- increaseIndent();
- emitCaptureThisForNodeIfNecessary(node);
- emitLines(node.statements);
- var exportName = resolver.getExportAssignmentName(node);
- if (exportName) {
+ function emitAMDModule(node: SourceFile) {
+ var imports = getExternalImportDeclarations(node);
writeLine();
- var exportAssignement = getFirstExportAssignment(node);
- emitStart(exportAssignement);
- write("return ");
- emitStart(exportAssignement.exportName);
- write(exportName);
- emitEnd(exportAssignement.exportName);
- write(";");
- emitEnd(exportAssignement);
- }
- decreaseIndent();
- writeLine();
- write("});");
- }
-
- function emitCommonJSModule(node: SourceFile) {
- emitCaptureThisForNodeIfNecessary(node);
- emitLines(node.statements);
- var exportName = resolver.getExportAssignmentName(node);
- if (exportName) {
- writeLine();
- var exportAssignement = getFirstExportAssignment(node);
- emitStart(exportAssignement);
- write("module.exports = ");
- emitStart(exportAssignement.exportName);
- write(exportName);
- emitEnd(exportAssignement.exportName);
- write(";");
- emitEnd(exportAssignement);
- }
- }
-
- function emitSourceFile(node: SourceFile) {
- currentSourceFile = node;
- if (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends) {
- writeLine();
- write("var __extends = this.__extends || function (d, b) {");
+ write("define([\"require\", \"exports\"");
+ forEach(imports, imp => {
+ write(", ");
+ emitLiteral(imp.externalModuleName);
+ });
+ forEach(node.amdDependencies, amdDependency => {
+ var text = "\"" + amdDependency + "\"";
+ write(", ");
+ write(text);
+ });
+ write("], function (require, exports");
+ forEach(imports, imp => {
+ write(", ");
+ emit(imp.name);
+ });
+ write(") {");
increaseIndent();
- writeLine();
- write("for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
- writeLine();
- write("function __() { this.constructor = d; }");
- writeLine();
- write("__.prototype = b.prototype;");
- writeLine();
- write("d.prototype = new __();");
- decreaseIndent();
- writeLine();
- write("};");
- extendsEmitted = true;
- }
- if (node.flags & NodeFlags.ExternalModule) {
- if (compilerOptions.module === ModuleKind.AMD) {
- emitAMDModule(node);
- }
- else {
- emitCommonJSModule(node);
- }
- }
- else {
emitCaptureThisForNodeIfNecessary(node);
emitLines(node.statements);
- }
- }
-
- function emitNode(node: Node) {
- if (!node || node.flags & NodeFlags.Ambient) return;
- switch (node.kind) {
- case SyntaxKind.Identifier:
- return emitIdentifier(node);
- case SyntaxKind.Parameter:
- return emitParameter(node);
- case SyntaxKind.GetAccessor:
- case SyntaxKind.SetAccessor:
- return emitAccessor(node);
- case SyntaxKind.ThisKeyword:
- return emitThis(node);
- case SyntaxKind.SuperKeyword:
- return emitSuper(node);
- case SyntaxKind.NullKeyword:
- return write("null");
- case SyntaxKind.TrueKeyword:
- return write("true");
- case SyntaxKind.FalseKeyword:
- return write("false");
- case SyntaxKind.NumericLiteral:
- case SyntaxKind.StringLiteral:
- case SyntaxKind.RegularExpressionLiteral:
- return emitLiteral(node);
- case SyntaxKind.QualifiedName:
- return emitPropertyAccess(node);
- case SyntaxKind.ArrayLiteral:
- return emitArrayLiteral(node);
- case SyntaxKind.ObjectLiteral:
- return emitObjectLiteral(node);
- case SyntaxKind.PropertyAssignment:
- return emitPropertyAssignment(node);
- case SyntaxKind.PropertyAccess:
- return emitPropertyAccess(node);
- case SyntaxKind.IndexedAccess:
- return emitIndexedAccess(node);
- case SyntaxKind.CallExpression:
- return emitCallExpression(node);
- case SyntaxKind.NewExpression:
- return emitNewExpression(node);
- case SyntaxKind.TypeAssertion:
- return emit((node).operand);
- case SyntaxKind.ParenExpression:
- return emitParenExpression(node);
- case SyntaxKind.FunctionDeclaration:
- case SyntaxKind.FunctionExpression:
- case SyntaxKind.ArrowFunction:
- return emitFunctionDeclaration(node);
- case SyntaxKind.PrefixOperator:
- case SyntaxKind.PostfixOperator:
- return emitUnaryExpression(node);
- case SyntaxKind.BinaryExpression:
- return emitBinaryExpression(node);
- case SyntaxKind.ConditionalExpression:
- return emitConditionalExpression(node);
- case SyntaxKind.OmittedExpression:
- return;
- case SyntaxKind.Block:
- case SyntaxKind.TryBlock:
- case SyntaxKind.FinallyBlock:
- case SyntaxKind.FunctionBlock:
- case SyntaxKind.ModuleBlock:
- return emitBlock(node);
- case SyntaxKind.VariableStatement:
- return emitVariableStatement(node);
- case SyntaxKind.EmptyStatement:
- return write(";");
- case SyntaxKind.ExpressionStatement:
- return emitExpressionStatement(node);
- case SyntaxKind.IfStatement:
- return emitIfStatement(node);
- case SyntaxKind.DoStatement:
- return emitDoStatement(node);
- case SyntaxKind.WhileStatement:
- return emitWhileStatement(node);
- case SyntaxKind.ForStatement:
- return emitForStatement(node);
- case SyntaxKind.ForInStatement:
- return emitForInStatement(node);
- case SyntaxKind.ContinueStatement:
- case SyntaxKind.BreakStatement:
- return emitBreakOrContinueStatement(node);
- case SyntaxKind.ReturnStatement:
- return emitReturnStatement(node);
- case SyntaxKind.WithStatement:
- return emitWithStatement(node);
- case SyntaxKind.SwitchStatement:
- return emitSwitchStatement(node);
- case SyntaxKind.CaseClause:
- case SyntaxKind.DefaultClause:
- return emitCaseOrDefaultClause(node);
- case SyntaxKind.LabelledStatement:
- return emitLabelledStatement(node);
- case SyntaxKind.ThrowStatement:
- return emitThrowStatement(node);
- case SyntaxKind.TryStatement:
- return emitTryStatement(node);
- case SyntaxKind.CatchBlock:
- return emitCatchBlock(node);
- case SyntaxKind.DebuggerStatement:
- return emitDebuggerStatement(node);
- case SyntaxKind.VariableDeclaration:
- return emitVariableDeclaration(node);
- case SyntaxKind.ClassDeclaration:
- return emitClassDeclaration(node);
- case SyntaxKind.EnumDeclaration:
- return emitEnumDeclaration(node);
- case SyntaxKind.ModuleDeclaration:
- return emitModuleDeclaration(node);
- case SyntaxKind.ImportDeclaration:
- return emitImportDeclaration(node);
- case SyntaxKind.SourceFile:
- return emitSourceFile(node);
- }
- }
-
- if (compilerOptions.sourceMap) {
- initializeEmitterWithSourceMaps();
- }
-
- if (root) {
- emit(root);
- }
- else {
- forEach(program.getSourceFiles(), sourceFile => {
- if (!isExternalModuleOrDeclarationFile(sourceFile)) {
- emit(sourceFile);
+ var exportName = resolver.getExportAssignmentName(node);
+ if (exportName) {
+ writeLine();
+ var exportAssignement = getFirstExportAssignment(node);
+ emitStart(exportAssignement);
+ write("return ");
+ emitStart(exportAssignement.exportName);
+ write(exportName);
+ emitEnd(exportAssignement.exportName);
+ write(";");
+ emitEnd(exportAssignement);
}
- });
- }
-
- writeLine();
- writeEmittedFiles(writer.getText());
- }
-
- function emitDeclarations(resolver: EmitResolver, jsFilePath: string, diagnostics: Diagnostic[], root?: SourceFile) {
- var program = resolver.getProgram();
- var compilerOptions = program.getCompilerOptions();
- var compilerHost = program.getCompilerHost();
-
- var writer = createTextWriter();
- var write = writer.write;
- var writeLine = writer.writeLine;
- var increaseIndent = writer.increaseIndent;
- var decreaseIndent = writer.decreaseIndent;
-
- var enclosingDeclaration: Node;
-
- function writeFile(filename: string, data: string) {
- compilerHost.writeFile(filename, data, hostErrorMessage => {
- diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage));
- });
- }
-
- function emitLines(nodes: Node[]) {
- for (var i = 0, n = nodes.length; i < n; i++) {
- emitNode(nodes[i]);
+ decreaseIndent();
+ writeLine();
+ write("});");
}
- }
- function emitCommaList(nodes: Node[], eachNodeEmitFn: (node: Node) => void) {
- var currentWriterPos = writer.getTextPos();
- for (var i = 0, n = nodes.length; i < n; i++) {
- if (currentWriterPos !== writer.getTextPos()) {
- write(", ");
+ function emitCommonJSModule(node: SourceFile) {
+ emitCaptureThisForNodeIfNecessary(node);
+ emitLines(node.statements);
+ var exportName = resolver.getExportAssignmentName(node);
+ if (exportName) {
+ writeLine();
+ var exportAssignement = getFirstExportAssignment(node);
+ emitStart(exportAssignement);
+ write("module.exports = ");
+ emitStart(exportAssignement.exportName);
+ write(exportName);
+ emitEnd(exportAssignement.exportName);
+ write(";");
+ emitEnd(exportAssignement);
}
- currentWriterPos = writer.getTextPos();
- eachNodeEmitFn(nodes[i]);
}
- }
- function emitSourceTextOfNode(node: Node) {
- write(getSourceTextOfLocalNode(node));
- }
-
- function emitSourceFile(node: SourceFile) {
- currentSourceFile = node;
- enclosingDeclaration = node;
- emitLines(node.statements);
- }
-
- function emitExportAssignment(node: ExportAssignment) {
- write("export = ");
- emitSourceTextOfNode(node.exportName);
- write(";");
- writeLine();
- }
-
- function emitDeclarationFlags(node: Declaration) {
- if (node.flags & NodeFlags.Static) {
- if (node.flags & NodeFlags.Private) {
- write("private ");
+ function emitSourceFile(node: SourceFile) {
+ currentSourceFile = node;
+ if (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends) {
+ writeLine();
+ write("var __extends = this.__extends || function (d, b) {");
+ increaseIndent();
+ writeLine();
+ write("for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
+ writeLine();
+ write("function __() { this.constructor = d; }");
+ writeLine();
+ write("__.prototype = b.prototype;");
+ writeLine();
+ write("d.prototype = new __();");
+ decreaseIndent();
+ writeLine();
+ write("};");
+ extendsEmitted = true;
}
- write("static ");
+ if (node.flags & NodeFlags.ExternalModule) {
+ if (compilerOptions.module === ModuleKind.AMD) {
+ emitAMDModule(node);
+ }
+ else {
+ emitCommonJSModule(node);
+ }
+ }
+ else {
+ emitCaptureThisForNodeIfNecessary(node);
+ emitLines(node.statements);
+ }
+ }
+
+ function emitNode(node: Node) {
+ if (!node || node.flags & NodeFlags.Ambient) return;
+ switch (node.kind) {
+ case SyntaxKind.Identifier:
+ return emitIdentifier(node);
+ case SyntaxKind.Parameter:
+ return emitParameter(node);
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ return emitAccessor(node);
+ case SyntaxKind.ThisKeyword:
+ return emitThis(node);
+ case SyntaxKind.SuperKeyword:
+ return emitSuper(node);
+ case SyntaxKind.NullKeyword:
+ return write("null");
+ case SyntaxKind.TrueKeyword:
+ return write("true");
+ case SyntaxKind.FalseKeyword:
+ return write("false");
+ case SyntaxKind.NumericLiteral:
+ case SyntaxKind.StringLiteral:
+ case SyntaxKind.RegularExpressionLiteral:
+ return emitLiteral(node);
+ case SyntaxKind.QualifiedName:
+ return emitPropertyAccess(node);
+ case SyntaxKind.ArrayLiteral:
+ return emitArrayLiteral(node);
+ case SyntaxKind.ObjectLiteral:
+ return emitObjectLiteral(node);
+ case SyntaxKind.PropertyAssignment:
+ return emitPropertyAssignment(node);
+ case SyntaxKind.PropertyAccess:
+ return emitPropertyAccess(node);
+ case SyntaxKind.IndexedAccess:
+ return emitIndexedAccess(node);
+ case SyntaxKind.CallExpression:
+ return emitCallExpression(node);
+ case SyntaxKind.NewExpression:
+ return emitNewExpression(node);
+ case SyntaxKind.TypeAssertion:
+ return emit((node).operand);
+ case SyntaxKind.ParenExpression:
+ return emitParenExpression(node);
+ case SyntaxKind.FunctionDeclaration:
+ case SyntaxKind.FunctionExpression:
+ case SyntaxKind.ArrowFunction:
+ return emitFunctionDeclaration(node);
+ case SyntaxKind.PrefixOperator:
+ case SyntaxKind.PostfixOperator:
+ return emitUnaryExpression(node);
+ case SyntaxKind.BinaryExpression:
+ return emitBinaryExpression(node);
+ case SyntaxKind.ConditionalExpression:
+ return emitConditionalExpression(node);
+ case SyntaxKind.OmittedExpression:
+ return;
+ case SyntaxKind.Block:
+ case SyntaxKind.TryBlock:
+ case SyntaxKind.FinallyBlock:
+ case SyntaxKind.FunctionBlock:
+ case SyntaxKind.ModuleBlock:
+ return emitBlock(node);
+ case SyntaxKind.VariableStatement:
+ return emitVariableStatement(node);
+ case SyntaxKind.EmptyStatement:
+ return write(";");
+ case SyntaxKind.ExpressionStatement:
+ return emitExpressionStatement(node);
+ case SyntaxKind.IfStatement:
+ return emitIfStatement(node);
+ case SyntaxKind.DoStatement:
+ return emitDoStatement(node);
+ case SyntaxKind.WhileStatement:
+ return emitWhileStatement(node);
+ case SyntaxKind.ForStatement:
+ return emitForStatement(node);
+ case SyntaxKind.ForInStatement:
+ return emitForInStatement(node);
+ case SyntaxKind.ContinueStatement:
+ case SyntaxKind.BreakStatement:
+ return emitBreakOrContinueStatement(node);
+ case SyntaxKind.ReturnStatement:
+ return emitReturnStatement(node);
+ case SyntaxKind.WithStatement:
+ return emitWithStatement(node);
+ case SyntaxKind.SwitchStatement:
+ return emitSwitchStatement(node);
+ case SyntaxKind.CaseClause:
+ case SyntaxKind.DefaultClause:
+ return emitCaseOrDefaultClause(node);
+ case SyntaxKind.LabelledStatement:
+ return emitLabelledStatement(node);
+ case SyntaxKind.ThrowStatement:
+ return emitThrowStatement(node);
+ case SyntaxKind.TryStatement:
+ return emitTryStatement(node);
+ case SyntaxKind.CatchBlock:
+ return emitCatchBlock(node);
+ case SyntaxKind.DebuggerStatement:
+ return emitDebuggerStatement(node);
+ case SyntaxKind.VariableDeclaration:
+ return emitVariableDeclaration(node);
+ case SyntaxKind.ClassDeclaration:
+ return emitClassDeclaration(node);
+ case SyntaxKind.EnumDeclaration:
+ return emitEnumDeclaration(node);
+ case SyntaxKind.ModuleDeclaration:
+ return emitModuleDeclaration(node);
+ case SyntaxKind.ImportDeclaration:
+ return emitImportDeclaration(node);
+ case SyntaxKind.SourceFile:
+ return emitSourceFile(node);
+ }
+ }
+
+ if (compilerOptions.sourceMap) {
+ initializeEmitterWithSourceMaps();
+ }
+
+ if (root) {
+ emit(root);
}
else {
- if (node.flags & NodeFlags.Private) {
- write("private ");
+ forEach(program.getSourceFiles(), sourceFile => {
+ if (!isExternalModuleOrDeclarationFile(sourceFile)) {
+ emit(sourceFile);
+ }
+ });
+ }
+
+ writeLine();
+ writeEmittedFiles(writer.getText());
+ }
+
+ function emitDeclarations(jsFilePath: string, root?: SourceFile) {
+ var writer = createTextWriter();
+ var write = writer.write;
+ var writeLine = writer.writeLine;
+ var increaseIndent = writer.increaseIndent;
+ var decreaseIndent = writer.decreaseIndent;
+
+ var enclosingDeclaration: Node;
+
+ function emitLines(nodes: Node[]) {
+ for (var i = 0, n = nodes.length; i < n; i++) {
+ emitNode(nodes[i]);
}
- // If the node is parented in the current source file we need to emit export declare or just export
- else if (node.parent === currentSourceFile) {
- // If the node is exported
+ }
+
+ function emitCommaList(nodes: Node[], eachNodeEmitFn: (node: Node) => void) {
+ var currentWriterPos = writer.getTextPos();
+ for (var i = 0, n = nodes.length; i < n; i++) {
+ if (currentWriterPos !== writer.getTextPos()) {
+ write(", ");
+ }
+ currentWriterPos = writer.getTextPos();
+ eachNodeEmitFn(nodes[i]);
+ }
+ }
+
+ function emitSourceTextOfNode(node: Node) {
+ write(getSourceTextOfLocalNode(node));
+ }
+
+ function emitSourceFile(node: SourceFile) {
+ currentSourceFile = node;
+ enclosingDeclaration = node;
+ emitLines(node.statements);
+ }
+
+ function emitExportAssignment(node: ExportAssignment) {
+ write("export = ");
+ emitSourceTextOfNode(node.exportName);
+ write(";");
+ writeLine();
+ }
+
+ function emitDeclarationFlags(node: Declaration) {
+ if (node.flags & NodeFlags.Static) {
+ if (node.flags & NodeFlags.Private) {
+ write("private ");
+ }
+ write("static ");
+ }
+ else {
+ if (node.flags & NodeFlags.Private) {
+ write("private ");
+ }
+ // If the node is parented in the current source file we need to emit export declare or just export
+ else if (node.parent === currentSourceFile) {
+ // If the node is exported
+ if (node.flags & NodeFlags.Export) {
+ write("export ");
+ }
+
+ if (node.kind !== SyntaxKind.InterfaceDeclaration) {
+ write("declare ");
+ }
+ }
+ }
+ }
+
+ function emitImportDeclaration(node: ImportDeclaration) {
+ if (resolver.isDeclarationVisible(node)) {
if (node.flags & NodeFlags.Export) {
write("export ");
}
+ write("import ");
+ emitSourceTextOfNode(node.name);
+ write(" = ");
+ if (node.entityName) {
+ emitSourceTextOfNode(node.entityName);
+ write(";");
+ }
+ else {
+ write("require(");
+ emitSourceTextOfNode(node.externalModuleName);
+ write(");");
+ }
+ writeLine();
+ }
+ }
- if (node.kind !== SyntaxKind.InterfaceDeclaration) {
- write("declare ");
+ function emitModuleDeclaration(node: ModuleDeclaration) {
+ if (resolver.isDeclarationVisible(node)) {
+ emitDeclarationFlags(node);
+ write("module ");
+ emitSourceTextOfNode(node.name);
+ while (node.body.kind !== SyntaxKind.ModuleBlock) {
+ node = node.body;
+ write(".");
+ emitSourceTextOfNode(node.name);
+ }
+ var prevEnclosingDeclaration = enclosingDeclaration;
+ enclosingDeclaration = node;
+ write(" {");
+ writeLine();
+ increaseIndent();
+ emitLines((node.body).statements);
+ decreaseIndent();
+ write("}");
+ writeLine();
+ enclosingDeclaration = prevEnclosingDeclaration;
+ }
+ }
+
+ function emitEnumDeclaration(node: EnumDeclaration) {
+ if (resolver.isDeclarationVisible(node)) {
+ emitDeclarationFlags(node);
+ write("enum ");
+ emitSourceTextOfNode(node.name);
+ write(" {");
+ writeLine();
+ increaseIndent();
+ emitLines(node.members);
+ decreaseIndent();
+ write("}");
+ writeLine();
+ }
+ }
+
+ function emitEnumMemberDeclaration(node: EnumMember) {
+ emitSourceTextOfNode(node.name);
+ var enumMemberValue = resolver.getEnumMemberValue(node);
+ if (enumMemberValue !== undefined) {
+ write(" = ");
+ write(enumMemberValue.toString());
+ }
+ write(",");
+ writeLine();
+ }
+
+ function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
+ function emitTypeParameter(node: TypeParameterDeclaration) {
+ emitSourceTextOfNode(node.name);
+ if (node.constraint) {
+ write(" extends ");
+ resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.None, writer);
}
}
- }
- }
- function emitImportDeclaration(node: ImportDeclaration) {
- if (resolver.isDeclarationVisible(node)) {
- if (node.flags & NodeFlags.Export) {
- write("export ");
+ if (typeParameters) {
+ write("<");
+ emitCommaList(typeParameters, emitTypeParameter);
+ write(">");
}
- write("import ");
- emitSourceTextOfNode(node.name);
- write(" = ");
- if (node.entityName) {
- emitSourceTextOfNode(node.entityName);
- write(";");
- }
- else {
- write("require(");
- emitSourceTextOfNode(node.externalModuleName);
- write(");");
- }
- writeLine();
}
- }
-
- function emitModuleDeclaration(node: ModuleDeclaration) {
- if (resolver.isDeclarationVisible(node)) {
- emitDeclarationFlags(node);
- write("module ");
- emitSourceTextOfNode(node.name);
- while (node.body.kind !== SyntaxKind.ModuleBlock) {
- node = node.body;
- write(".");
+
+ function emitHeritageClause(typeReferences: TypeReferenceNode[], isImplementsList: boolean) {
+ function emitTypeOfTypeReference(node: Node) {
+ resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType, writer);
+ }
+
+ if (typeReferences) {
+ write(isImplementsList ? " implments " : " extends ");
+ emitCommaList(typeReferences, emitTypeOfTypeReference);
+ }
+ }
+
+ function emitClassDeclaration(node: ClassDeclaration) {
+ function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
+ if (constructorDeclaration) {
+ forEach(constructorDeclaration.parameters, param => {
+ if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
+ emitPropertyDeclaration(param);
+ }
+ });
+ }
+ }
+
+ if (resolver.isDeclarationVisible(node)) {
+ emitDeclarationFlags(node);
+ write("class ");
emitSourceTextOfNode(node.name);
+ var prevEnclosingDeclaration = enclosingDeclaration;
+ enclosingDeclaration = node;
+ emitTypeParameters(node.typeParameters);
+ if (node.baseType) {
+ emitHeritageClause([node.baseType], /*isImplementsList*/ false);
+ }
+ emitHeritageClause(node.implementedTypes, /*isImplementsList*/ true);
+ write(" {");
+ writeLine();
+ increaseIndent();
+ emitParameterProperties(getFirstConstructorWithBody(node));
+ emitLines(node.members);
+ decreaseIndent();
+ write("}");
+ writeLine();
+ enclosingDeclaration = prevEnclosingDeclaration;
}
- var prevEnclosingDeclaration = enclosingDeclaration;
- enclosingDeclaration = node;
- write(" {");
- writeLine();
- increaseIndent();
- emitLines((node.body).statements);
- decreaseIndent();
- write("}");
- writeLine();
- enclosingDeclaration = prevEnclosingDeclaration;
}
- }
- function emitEnumDeclaration(node: EnumDeclaration) {
- if (resolver.isDeclarationVisible(node)) {
+ function emitInterfaceDeclaration(node: InterfaceDeclaration) {
+ if (resolver.isDeclarationVisible(node)) {
+ emitDeclarationFlags(node);
+ write("interface ");
+ emitSourceTextOfNode(node.name);
+ var prevEnclosingDeclaration = enclosingDeclaration;
+ enclosingDeclaration = node;
+ emitTypeParameters(node.typeParameters);
+ emitHeritageClause(node.baseTypes, /*isImplementsList*/ false);
+ write(" {");
+ writeLine();
+ increaseIndent();
+ emitLines(node.members);
+ decreaseIndent();
+ write("}");
+ writeLine();
+ enclosingDeclaration = prevEnclosingDeclaration;
+ }
+ }
+
+ function emitPropertyDeclaration(node: PropertyDeclaration) {
emitDeclarationFlags(node);
- write("enum ");
- emitSourceTextOfNode(node.name);
- write(" {");
- writeLine();
- increaseIndent();
- emitLines(node.members);
- decreaseIndent();
- write("}");
- writeLine();
- }
- }
-
- function emitEnumMemberDeclaration(node: EnumMember) {
- emitSourceTextOfNode(node.name);
- var enumMemberValue = resolver.getEnumMemberValue(node);
- if (enumMemberValue !== undefined) {
- write(" = ");
- write(enumMemberValue.toString());
- }
- write(",");
- writeLine();
- }
-
- function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
- function emitTypeParameter(node: TypeParameterDeclaration) {
- emitSourceTextOfNode(node.name);
- if (node.constraint) {
- write(" extends ");
- resolver.writeTypeAtLocation(node.constraint, enclosingDeclaration, TypeFormatFlags.None, writer);
- }
- }
-
- if (typeParameters) {
- write("<");
- emitCommaList(typeParameters, emitTypeParameter);
- write(">");
- }
- }
-
- function emitHeritageClause(typeReferences: TypeReferenceNode[], isImplementsList: boolean) {
- function emitTypeOfTypeReference(node: Node) {
- resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.WriteArrayAsGenericType, writer);
- }
-
- if (typeReferences) {
- write(isImplementsList ? " implments " : " extends ");
- emitCommaList(typeReferences, emitTypeOfTypeReference);
- }
- }
-
- function emitClassDeclaration(node: ClassDeclaration) {
- function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
- if (constructorDeclaration) {
- forEach(constructorDeclaration.parameters, param => {
- if (param.flags & (NodeFlags.Public | NodeFlags.Private)) {
- emitPropertyDeclaration(param);
- }
- });
- }
- }
-
- if (resolver.isDeclarationVisible(node)) {
- emitDeclarationFlags(node);
- write("class ");
- emitSourceTextOfNode(node.name);
- var prevEnclosingDeclaration = enclosingDeclaration;
- enclosingDeclaration = node;
- emitTypeParameters(node.typeParameters);
- if (node.baseType) {
- emitHeritageClause([node.baseType], /*isImplementsList*/ false);
- }
- emitHeritageClause(node.implementedTypes, /*isImplementsList*/ true);
- write(" {");
- writeLine();
- increaseIndent();
- emitParameterProperties(getFirstConstructorWithBody(node));
- emitLines(node.members);
- decreaseIndent();
- write("}");
- writeLine();
- enclosingDeclaration = prevEnclosingDeclaration;
- }
- }
-
- function emitInterfaceDeclaration(node: InterfaceDeclaration) {
- if (resolver.isDeclarationVisible(node)) {
- emitDeclarationFlags(node);
- write("interface ");
- emitSourceTextOfNode(node.name);
- var prevEnclosingDeclaration = enclosingDeclaration;
- enclosingDeclaration = node;
- emitTypeParameters(node.typeParameters);
- emitHeritageClause(node.baseTypes, /*isImplementsList*/ false);
- write(" {");
- writeLine();
- increaseIndent();
- emitLines(node.members);
- decreaseIndent();
- write("}");
- writeLine();
- enclosingDeclaration = prevEnclosingDeclaration;
- }
- }
-
- function emitPropertyDeclaration(node: PropertyDeclaration) {
- emitDeclarationFlags(node);
- emitVariableDeclaration(node);
- write(";");
- writeLine();
- }
-
- function emitVariableDeclaration(node: VariableDeclaration) {
- // If we are emitting property it isnt moduleElement and hence we already know it needs to be emitted
- // so there is no check needed to see if declaration is visible
- if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
- emitSourceTextOfNode(node.name);
- // If optional property emit ?
- if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) {
- write("?");
- }
- if (!(node.flags & NodeFlags.Private)) {
- write(": ");
- resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
- }
- }
- }
-
- function emitVariableStatement(node: VariableStatement) {
- var hasDeclarationWithEmit = forEach(node.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
- if (hasDeclarationWithEmit) {
- emitDeclarationFlags(node);
- write("var ");
- emitCommaList(node.declarations, emitVariableDeclaration);
+ emitVariableDeclaration(node);
write(";");
writeLine();
}
- }
- function emitAccessorDeclaration(node: AccessorDeclaration) {
- var accessors = getAllAccessorDeclarations(node.parent, node);
- if (node === accessors.firstAccessor) {
- emitDeclarationFlags(node);
- emitSourceTextOfNode(node.name);
- if (!(node.flags & NodeFlags.Private)) {
- write(": ");
- resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
- }
- write(";");
- writeLine();
- }
- }
-
- function emitFunctionDeclaration(node: FunctionDeclaration) {
- // If we are emitting Method/Constructor it isnt moduleElement and hence already determined to be emitting
- // so no need to verify if the declaration is visible
- if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
- !resolver.isImplementationOfOverload(node)) {
- emitDeclarationFlags(node);
- if (node.kind === SyntaxKind.FunctionDeclaration) {
- write("function ");
+ function emitVariableDeclaration(node: VariableDeclaration) {
+ // If we are emitting property it isnt moduleElement and hence we already know it needs to be emitted
+ // so there is no check needed to see if declaration is visible
+ if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
emitSourceTextOfNode(node.name);
- }
- else if (node.kind === SyntaxKind.Constructor) {
- write("constructor");
- }
- else {
- emitSourceTextOfNode(node.name);
- if (node.flags & NodeFlags.QuestionMark) {
+ // If optional property emit ?
+ if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) {
write("?");
}
- }
- emitSignatureDeclaration(node);
- }
- }
-
- function emitConstructSignatureDeclaration(node: SignatureDeclaration) {
- write("new ");
- emitSignatureDeclaration(node);
- }
-
- function emitSignatureDeclaration(node: SignatureDeclaration) {
- emitTypeParameters(node.typeParameters);
- if (node.kind === SyntaxKind.IndexSignature) {
- write("[");
- }
- else {
- write("(");
- }
-
- // Parameters
- emitCommaList(node.parameters, emitParameterDeclaration);
-
- if (node.kind === SyntaxKind.IndexSignature) {
- write("]");
- }
- else {
- write(")");
- }
-
- // If this is not a constructor and is not private, emit the return type
- if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
- write(": ");
- resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.None, writer);
- }
- write(";");
- writeLine();
- }
-
- function emitParameterDeclaration(node: ParameterDeclaration) {
- if (node.flags & NodeFlags.Rest) {
- write("...");
- }
- emitSourceTextOfNode(node.name);
- if (node.initializer || (node.flags & NodeFlags.QuestionMark)) {
- write("?");
- }
-
- if (!(node.parent.flags & NodeFlags.Private)) {
- write(": ");
- resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
- }
- }
-
- function emitNode(node: Node) {
- switch (node.kind) {
- case SyntaxKind.Constructor:
- case SyntaxKind.FunctionDeclaration:
- case SyntaxKind.Method:
- return emitFunctionDeclaration(node);
- case SyntaxKind.ConstructSignature:
- return emitConstructSignatureDeclaration(node);
- case SyntaxKind.CallSignature:
- case SyntaxKind.IndexSignature:
- return emitSignatureDeclaration(node);
- case SyntaxKind.GetAccessor:
- case SyntaxKind.SetAccessor:
- return emitAccessorDeclaration(node);
- case SyntaxKind.VariableStatement:
- return emitVariableStatement(node);
- case SyntaxKind.Property:
- return emitPropertyDeclaration(node);
- case SyntaxKind.InterfaceDeclaration:
- return emitInterfaceDeclaration(node);
- case SyntaxKind.ClassDeclaration:
- return emitClassDeclaration(node);
- case SyntaxKind.EnumMember:
- return emitEnumMemberDeclaration(node);
- case SyntaxKind.EnumDeclaration:
- return emitEnumDeclaration(node);
- case SyntaxKind.ModuleDeclaration:
- return emitModuleDeclaration(node);
- case SyntaxKind.ImportDeclaration:
- return emitImportDeclaration(node);
- case SyntaxKind.ExportAssignment:
- return emitExportAssignment(node);
- case SyntaxKind.SourceFile:
- return emitSourceFile(node);
- }
- }
-
- function resolveScriptReference(sourceFile: SourceFile, reference: FileReference) {
- var referenceFileName = compilerOptions.noResolve
- ? reference.filename
- : normalizePath(combinePaths(getDirectoryPath(sourceFile.filename), reference.filename));
- return program.getSourceFile(referenceFileName);
- }
-
- // Contains the reference paths that needs to go in the declaration file.
- // Collecting this separately because reference paths need to be first thing in the declaration file
- // and we could be collecting these paths from multiple files into single one with --out option
- var referencePathsOutput = "";
- function writeReferencePath(referencedFile: SourceFile) {
- var declFileName = referencedFile.flags & NodeFlags.DeclarationFile
- ? referencedFile.filename // Declaration file, use declaration file name
- : emitToOwnOutputFile(referencedFile, compilerOptions)
- ? getOwnEmitOutputFilePath(referencedFile, program, ".d.ts") // Own output file so get the .d.ts file
- : getModuleNameFromFilename(compilerOptions.out) + ".d.ts";// Global out file
-
- declFileName = getRelativePathToDirectoryOrUrl(
- getDirectoryPath(normalizeSlashes(jsFilePath)),
- declFileName,
- compilerHost.getCurrentDirectory(),
- /*isAbsolutePathAnUrl*/ false);
-
- referencePathsOutput += "/// " + sys.newLine;
- }
-
- if (root) {
- // Emiting single file so emit references in this file only
- var addedGlobalFileReference = false;
- forEach(root.referencedFiles, fileReference => {
- var referencedFile = resolveScriptReference(root, fileReference);
-
- // All the references that are not going to be part of same file
- if ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
- emitToOwnOutputFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
- !addedGlobalFileReference) { // Or the global out file corresponding to this reference was not added
-
- writeReferencePath(referencedFile);
- if (!isExternalModuleOrDeclarationFile(referencedFile)) {
- addedGlobalFileReference = true;
+ if (!(node.flags & NodeFlags.Private)) {
+ write(": ");
+ resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
}
}
- });
+ }
- emitNode(root);
- }
- else {
- // Emit references corresponding to this file
- var emittedReferencedFiles: SourceFile[] = [];
- forEach(program.getSourceFiles(), sourceFile => {
- if (!isExternalModuleOrDeclarationFile(sourceFile)) {
- // Check what references need to be added
- forEach(sourceFile.referencedFiles, fileReference => {
- var referencedFile = resolveScriptReference(sourceFile, fileReference);
-
- // If the reference file is declaration file or external module emit that reference
- if (isExternalModuleOrDeclarationFile(referencedFile) &&
- !contains(emittedReferencedFiles, referencedFile)) { // If the file refernece was not already emitted
-
- writeReferencePath(referencedFile);
- emittedReferencedFiles.push(referencedFile);
- }
- });
-
- emitNode(sourceFile);
+ function emitVariableStatement(node: VariableStatement) {
+ var hasDeclarationWithEmit = forEach(node.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
+ if (hasDeclarationWithEmit) {
+ emitDeclarationFlags(node);
+ write("var ");
+ emitCommaList(node.declarations, emitVariableDeclaration);
+ write(";");
+ writeLine();
}
- });
+ }
+
+ function emitAccessorDeclaration(node: AccessorDeclaration) {
+ var accessors = getAllAccessorDeclarations(node.parent, node);
+ if (node === accessors.firstAccessor) {
+ emitDeclarationFlags(node);
+ emitSourceTextOfNode(node.name);
+ if (!(node.flags & NodeFlags.Private)) {
+ write(": ");
+ resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
+ }
+ write(";");
+ writeLine();
+ }
+ }
+
+ function emitFunctionDeclaration(node: FunctionDeclaration) {
+ // If we are emitting Method/Constructor it isnt moduleElement and hence already determined to be emitting
+ // so no need to verify if the declaration is visible
+ if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
+ !resolver.isImplementationOfOverload(node)) {
+ emitDeclarationFlags(node);
+ if (node.kind === SyntaxKind.FunctionDeclaration) {
+ write("function ");
+ emitSourceTextOfNode(node.name);
+ }
+ else if (node.kind === SyntaxKind.Constructor) {
+ write("constructor");
+ }
+ else {
+ emitSourceTextOfNode(node.name);
+ if (node.flags & NodeFlags.QuestionMark) {
+ write("?");
+ }
+ }
+ emitSignatureDeclaration(node);
+ }
+ }
+
+ function emitConstructSignatureDeclaration(node: SignatureDeclaration) {
+ write("new ");
+ emitSignatureDeclaration(node);
+ }
+
+ function emitSignatureDeclaration(node: SignatureDeclaration) {
+ emitTypeParameters(node.typeParameters);
+ if (node.kind === SyntaxKind.IndexSignature) {
+ write("[");
+ }
+ else {
+ write("(");
+ }
+
+ // Parameters
+ emitCommaList(node.parameters, emitParameterDeclaration);
+
+ if (node.kind === SyntaxKind.IndexSignature) {
+ write("]");
+ }
+ else {
+ write(")");
+ }
+
+ // If this is not a constructor and is not private, emit the return type
+ if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
+ write(": ");
+ resolver.writeReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, TypeFormatFlags.None, writer);
+ }
+ write(";");
+ writeLine();
+ }
+
+ function emitParameterDeclaration(node: ParameterDeclaration) {
+ if (node.flags & NodeFlags.Rest) {
+ write("...");
+ }
+ emitSourceTextOfNode(node.name);
+ if (node.initializer || (node.flags & NodeFlags.QuestionMark)) {
+ write("?");
+ }
+
+ if (!(node.parent.flags & NodeFlags.Private)) {
+ write(": ");
+ resolver.writeTypeAtLocation(node, enclosingDeclaration, TypeFormatFlags.None, writer);
+ }
+ }
+
+ function emitNode(node: Node) {
+ switch (node.kind) {
+ case SyntaxKind.Constructor:
+ case SyntaxKind.FunctionDeclaration:
+ case SyntaxKind.Method:
+ return emitFunctionDeclaration(node);
+ case SyntaxKind.ConstructSignature:
+ return emitConstructSignatureDeclaration(node);
+ case SyntaxKind.CallSignature:
+ case SyntaxKind.IndexSignature:
+ return emitSignatureDeclaration(node);
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ return emitAccessorDeclaration(node);
+ case SyntaxKind.VariableStatement:
+ return emitVariableStatement(node);
+ case SyntaxKind.Property:
+ return emitPropertyDeclaration(node);
+ case SyntaxKind.InterfaceDeclaration:
+ return emitInterfaceDeclaration(node);
+ case SyntaxKind.ClassDeclaration:
+ return emitClassDeclaration(node);
+ case SyntaxKind.EnumMember:
+ return emitEnumMemberDeclaration(node);
+ case SyntaxKind.EnumDeclaration:
+ return emitEnumDeclaration(node);
+ case SyntaxKind.ModuleDeclaration:
+ return emitModuleDeclaration(node);
+ case SyntaxKind.ImportDeclaration:
+ return emitImportDeclaration(node);
+ case SyntaxKind.ExportAssignment:
+ return emitExportAssignment(node);
+ case SyntaxKind.SourceFile:
+ return emitSourceFile(node);
+ }
+ }
+
+ function resolveScriptReference(sourceFile: SourceFile, reference: FileReference) {
+ var referenceFileName = compilerOptions.noResolve
+ ? reference.filename
+ : normalizePath(combinePaths(getDirectoryPath(sourceFile.filename), reference.filename));
+ return program.getSourceFile(referenceFileName);
+ }
+
+ // Contains the reference paths that needs to go in the declaration file.
+ // Collecting this separately because reference paths need to be first thing in the declaration file
+ // and we could be collecting these paths from multiple files into single one with --out option
+ var referencePathsOutput = "";
+ function writeReferencePath(referencedFile: SourceFile) {
+ var declFileName = referencedFile.flags & NodeFlags.DeclarationFile
+ ? referencedFile.filename // Declaration file, use declaration file name
+ : emitToOwnOutputFile(referencedFile)
+ ? getOwnEmitOutputFilePath(referencedFile, ".d.ts") // Own output file so get the .d.ts file
+ : getModuleNameFromFilename(compilerOptions.out) + ".d.ts";// Global out file
+
+ declFileName = getRelativePathToDirectoryOrUrl(
+ getDirectoryPath(normalizeSlashes(jsFilePath)),
+ declFileName,
+ compilerHost.getCurrentDirectory(),
+ /*isAbsolutePathAnUrl*/ false);
+
+ referencePathsOutput += "/// " + sys.newLine;
+ }
+
+ if (root) {
+ // Emiting single file so emit references in this file only
+ var addedGlobalFileReference = false;
+ forEach(root.referencedFiles, fileReference => {
+ var referencedFile = resolveScriptReference(root, fileReference);
+
+ // All the references that are not going to be part of same file
+ if ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
+ emitToOwnOutputFile(referencedFile) || // This is referenced file is emitting its own js file
+ !addedGlobalFileReference) { // Or the global out file corresponding to this reference was not added
+
+ writeReferencePath(referencedFile);
+ if (!isExternalModuleOrDeclarationFile(referencedFile)) {
+ addedGlobalFileReference = true;
+ }
+ }
+ });
+
+ emitNode(root);
+ }
+ else {
+ // Emit references corresponding to this file
+ var emittedReferencedFiles: SourceFile[] = [];
+ forEach(program.getSourceFiles(), sourceFile => {
+ if (!isExternalModuleOrDeclarationFile(sourceFile)) {
+ // Check what references need to be added
+ forEach(sourceFile.referencedFiles, fileReference => {
+ var referencedFile = resolveScriptReference(sourceFile, fileReference);
+
+ // If the reference file is declaration file or external module emit that reference
+ if (isExternalModuleOrDeclarationFile(referencedFile) &&
+ !contains(emittedReferencedFiles, referencedFile)) { // If the file refernece was not already emitted
+
+ writeReferencePath(referencedFile);
+ emittedReferencedFiles.push(referencedFile);
+ }
+ });
+
+ emitNode(sourceFile);
+ }
+ });
+ }
+
+ writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText());
}
- writeFile(getModuleNameFromFilename(jsFilePath) + ".d.ts", referencePathsOutput + writer.getText());
+ var shouldEmitDeclarations = resolver.shouldEmitDeclarations();
+ function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
+ emitJavaScript(jsFilePath, sourceFile);
+ if (shouldEmitDeclarations) {
+ emitDeclarations(jsFilePath, sourceFile);
+ }
+ }
+
+ forEach(program.getSourceFiles(), sourceFile => {
+ if (emitToOwnOutputFile(sourceFile)) {
+ var jsFilePath = getOwnEmitOutputFilePath(sourceFile, ".js");
+ emitFile(jsFilePath, sourceFile);
+ }
+ });
+ if (compilerOptions.out) {
+ emitFile(compilerOptions.out);
+ }
+ return {
+ errors: diagnostics,
+ sourceMaps: sourceMapDataList
+ };
}
}