From 81d5d2b6b6a2eff88938410ce1f485da862a1b3e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 May 2016 13:18:24 -0700 Subject: [PATCH] Added 'extendedDiagnostics' option for comments/sourcemap measurements. --- src/compiler/commandLineParser.ts | 5 ++ src/compiler/comments.ts | 85 +++++++++++++++++++++++-------- src/compiler/emitter.ts | 2 +- src/compiler/printer.ts | 11 ++-- src/compiler/sourcemap.ts | 75 +++++++++++++++++++++++++-- src/compiler/types.ts | 1 + 6 files changed, 150 insertions(+), 29 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index fef057b9107..2cabb930a68 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -27,6 +27,11 @@ namespace ts { name: "diagnostics", type: "boolean", }, + { + name: "extendedDiagnostics", + type: "boolean", + experimental: true, + }, { name: "emitBOM", type: "boolean" diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 2b7ab987e4e..7ad380f06af 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -35,10 +35,14 @@ namespace ts { let leadingCommentRangePositions: Map; let trailingCommentRangePositions: Map; - return compilerOptions.removeComments + const commentWriter = compilerOptions.removeComments ? createCommentRemovingWriter() : createCommentPreservingWriter(); + return compilerOptions.extendedDiagnostics + ? createCommentWriterWithExtendedDiagnostics(commentWriter) + : commentWriter; + function createCommentRemovingWriter(): CommentWriter { return { reset, @@ -78,8 +82,6 @@ namespace ts { function getLeadingComments(range: TextRange): CommentRange[]; function getLeadingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[]; function getLeadingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange) { - performance.mark("commentStart"); - let comments: CommentRange[] = []; let ignored = false; if (contextNode) { @@ -108,7 +110,6 @@ namespace ts { comments = getLeadingCommentsOfPosition(range.pos); } - performance.measure("commentTime", "commentStart"); return comments; } @@ -131,8 +132,6 @@ namespace ts { function getTrailingComments(range: TextRange): CommentRange[]; function getTrailingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[]; function getTrailingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange) { - performance.mark("commentStart"); - let ignored = false; if (contextNode) { if (ignoreNodeCallback(contextNode)) { @@ -145,10 +144,8 @@ namespace ts { let comments: CommentRange[]; if (!ignored) { - comments = getTrailingCommentsOfPositionWorker(range.end); + comments = getTrailingCommentsOfPosition(range.end); } - - performance.measure("commentTime", "commentStart"); return comments; } @@ -165,13 +162,6 @@ namespace ts { } function getTrailingCommentsOfPosition(pos: number) { - performance.mark("commentStart"); - const comments = getTrailingCommentsOfPositionWorker(pos); - performance.measure("commentTime", "commentStart"); - return comments; - } - - function getTrailingCommentsOfPositionWorker(pos: number) { if (positionIsSynthesized(pos) || trailingCommentRangePositions[pos]) { return undefined; } @@ -184,7 +174,6 @@ namespace ts { function emitLeadingComments(range: TextRange, comments: CommentRange[]): void; function emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode: Node, getTextRangeCallback: (contextNode: Node) => TextRange): void; function emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode?: Node, getTextRangeCallback?: (contextNode: Node) => TextRange) { - performance.mark("commentStart"); if (comments && comments.length > 0) { if (contextNode) { range = getTextRangeCallback(contextNode) || range; @@ -195,14 +184,11 @@ namespace ts { // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); } - performance.measure("commentTime", "commentStart"); } function emitTrailingComments(range: TextRange, comments: CommentRange[]) { // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - performance.mark("commentStart"); emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment); - performance.measure("commentTime", "commentStart"); } function emitLeadingDetachedComments(range: TextRange): void; @@ -212,9 +198,7 @@ namespace ts { return; } - performance.mark("commentStart"); emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false); - performance.measure("commentTime", "commentStart"); } function emitTrailingDetachedComments(range: TextRange): void; @@ -276,6 +260,63 @@ namespace ts { } } + function createCommentWriterWithExtendedDiagnostics(writer: CommentWriter): CommentWriter { + const { + reset, + setSourceFile, + getLeadingComments, + getTrailingComments, + getTrailingCommentsOfPosition, + emitLeadingComments, + emitTrailingComments, + emitLeadingDetachedComments, + emitTrailingDetachedComments + } = writer; + + return { + reset, + setSourceFile, + getLeadingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] { + performance.mark("commentStart"); + const comments = getLeadingComments(range, contextNode, ignoreNodeCallback, getTextRangeCallback); + performance.measure("commentTime", "commentStart"); + return comments; + }, + getTrailingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] { + performance.mark("commentStart"); + const comments = getTrailingComments(range, contextNode, ignoreNodeCallback, getTextRangeCallback); + performance.measure("commentTime", "commentStart"); + return comments; + }, + getTrailingCommentsOfPosition(pos: number): CommentRange[] { + performance.mark("commentStart"); + const comments = getTrailingCommentsOfPosition(pos); + performance.measure("commentTime", "commentStart"); + return comments; + }, + emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode?: Node, getTextRangeCallback?: (contextNode: Node) => TextRange): void { + performance.mark("commentStart"); + emitLeadingComments(range, comments, contextNode, getTextRangeCallback); + performance.measure("commentTime", "commentStart"); + }, + emitTrailingComments(range: TextRange, comments: CommentRange[]): void { + performance.mark("commentStart"); + emitLeadingComments(range, comments); + performance.measure("commentTime", "commentStart"); + }, + emitLeadingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void { + performance.mark("commentStart"); + emitLeadingDetachedComments(range, contextNode, ignoreNodeCallback); + performance.measure("commentTime", "commentStart"); + }, + emitTrailingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void { + performance.mark("commentStart"); + emitTrailingDetachedComments(range, contextNode, ignoreNodeCallback); + performance.measure("commentTime", "commentStart"); + } + }; + } + function reset() { currentSourceFile = undefined; currentText = undefined; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8bcdd4c8201..c2d602204dd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -524,7 +524,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge const writer = createTextWriter(newLine); const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer; - let sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter(); + let sourceMap = createSourceMapWriter(host, writer); let { setSourceFile, emitStart, emitEnd, emitPos } = sourceMap; let currentSourceFile: SourceFile; diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 1b4531102c9..f1f3e213d69 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -151,7 +151,7 @@ const _super = (function (geti, seti) { decreaseIndent } = writer; - const sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter(); + const sourceMap = createSourceMapWriter(host, writer); const { emitStart, emitEnd, @@ -267,7 +267,7 @@ const _super = (function (geti, seti) { isEmitNotificationEnabled = context.isEmitNotificationEnabled; onSubstituteNode = context.onSubstituteNode; onEmitNode = context.onEmitNode; - return printSourceFile; + return compilerOptions.extendedDiagnostics ? printSourceFileWithExtendedDiagnostics : printSourceFile; } function printSourceFile(node: SourceFile) { @@ -276,8 +276,13 @@ const _super = (function (geti, seti) { currentFileIdentifiers = node.identifiers; sourceMap.setSourceFile(node); comments.setSourceFile(node); - performance.mark("printStart"); emitNodeWithNotificationOption(node, emitWorker); + return node; + } + + function printSourceFileWithExtendedDiagnostics(node: SourceFile) { + performance.mark("printStart"); + printSourceFile(node); performance.measure("printTime", "printStart"); return node; } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 58df47c770c..8e7cc3b1d44 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -170,6 +170,20 @@ namespace ts { getSourceMappingURL(): string; } + export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { + const compilerOptions = host.getCompilerOptions(); + if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { + if (compilerOptions.extendedDiagnostics) { + return createSourceMapWriterWithExtendedDiagnostics(host, writer); + } + + return createSourceMapWriterWorker(host, writer); + } + else { + return getNullSourceMapWriter(); + } + } + let nullSourceMapWriter: SourceMapWriter; export function getNullSourceMapWriter(): SourceMapWriter { @@ -182,8 +196,8 @@ namespace ts { emitPos(pos: number): void { }, emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { }, emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { }, - emitTokenStart(token: SyntaxKind, pos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind, pos: number) => TextRange): number { return -1; }, - emitTokenEnd(token: SyntaxKind, end: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind, pos: number) => TextRange): number { return -1; }, + emitTokenStart(token: SyntaxKind, pos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { return -1; }, + emitTokenEnd(token: SyntaxKind, end: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { return -1; }, changeEmitSourcePos(): void { }, stopOverridingSpan(): void { }, getText(): string { return undefined; }, @@ -203,7 +217,7 @@ namespace ts { sourceIndex: 0 }; - export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { + function createSourceMapWriterWorker(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { const compilerOptions = host.getCompilerOptions(); let currentSourceFile: SourceFile; let currentSourceText: string; @@ -746,6 +760,61 @@ namespace ts { } } + function createSourceMapWriterWithExtendedDiagnostics(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { + const { + initialize, + reset, + getSourceMapData, + setSourceFile, + emitPos, + emitStart, + emitEnd, + emitTokenStart, + emitTokenEnd, + changeEmitSourcePos, + stopOverridingSpan, + getText, + getSourceMappingURL, + } = createSourceMapWriterWorker(host, writer); + return { + initialize, + reset, + getSourceMapData, + setSourceFile, + emitPos(pos: number): void { + performance.mark("sourcemapStart"); + emitPos(pos); + performance.measure("sourcemapTime", "sourcemapStart"); + }, + emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { + performance.mark("sourcemapStart"); + emitStart(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback); + performance.measure("sourcemapTime", "sourcemapStart"); + }, + emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { + performance.mark("sourcemapStart"); + emitEnd(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback); + performance.measure("sourcemapTime", "sourcemapStart"); + }, + emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { + performance.mark("sourcemapStart"); + tokenStartPos = emitTokenStart(token, tokenStartPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback); + performance.measure("sourcemapTime", "sourcemapStart"); + return tokenStartPos; + }, + emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { + performance.mark("sourcemapStart"); + tokenEndPos = emitTokenEnd(token, tokenEndPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback); + performance.measure("sourcemapTime", "sourcemapStart"); + return tokenEndPos; + }, + changeEmitSourcePos, + stopOverridingSpan, + getText, + getSourceMappingURL, + }; + } + const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; function base64FormatEncode(inValue: number) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42beb0e6335..110ca5f512d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2476,6 +2476,7 @@ namespace ts { declaration?: boolean; declarationDir?: string; diagnostics?: boolean; + /*@internal*/ extendedDiagnostics?: boolean; emitBOM?: boolean; help?: boolean; init?: boolean;