diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 2c59cd9fa47..a4ad046f7dd 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -2165,13 +2165,25 @@ function __export(m) { } } - function writeToken(token: SyntaxKind) { - write(tokenToString(token)); + function writeToken(token: SyntaxKind, pos?: number) { + let tokenStartPos = skipTrivia(currentSourceFile.text, pos); + emitPos(tokenStartPos); + let tokenEndPos = writeTokenText(token, pos); + emitPos(tokenEndPos); + return tokenEndPos; + } + + function writeTokenText(token: SyntaxKind, pos?: number) { + let tokenString = tokenToString(token); + write(tokenString); + return positionIsSynthesized(pos) ? -1 : pos + tokenString.length; } function writeTokenNode(node: Node) { if (node) { - writeToken(node.kind); + emitStart(node); + writeTokenText(node.kind); + emitEnd(node); } } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2053b224e03..b8f7f9cf35b 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -425,10 +425,10 @@ namespace ts { /* @internal */ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number { - if (pos < 0) { + if (positionIsSynthesized(pos)) { return pos; } - + // Keep in sync with couldStartTrivia while (true) { let ch = text.charCodeAt(pos); @@ -571,12 +571,12 @@ namespace ts { } /** - * Extract comments from text prefixing the token closest following `pos`. + * Extract comments from text prefixing the token closest following `pos`. * The return value is an array containing a TextRange for each comment. * Single-line comment ranges include the beginning '//' characters but not the ending line break. * Multi - line comment ranges include the beginning '/* and ending '/' characters. * The return value is undefined if no comments were found. - * @param trailing + * @param trailing * If false, whitespace is skipped until the first line break and comments between that location * and the next token are returned. * If true, comments occurring between the given position and the next line break are returned. diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 26aaa0ab653..70c0c9786e1 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -7,7 +7,7 @@ namespace ts { export interface SourceMapWriter { sourceMapData?: SourceMapData; setSourceFile(sourceFile: SourceFile): void; - emitPos(pos: number, skipTrivia?: boolean): void; + emitPos(pos: number): void; emitStart(range: TextRange): void; emitEnd(range: TextRange): void; pushScope(scopeDeclaration: Node, scopeName?: string): void; @@ -167,15 +167,11 @@ namespace ts { sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); } - function recordSourceMapSpan(pos: number, skipTrivia?: boolean) { + function recordSourceMapSpan(pos: number) { if (pos === -1) { return; } - if (skipTrivia) { - pos = ts.skipTrivia(currentSourceFile.text, pos); - } - let sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos); // Convert the location to be one-based. @@ -215,11 +211,11 @@ namespace ts { } function recordEmitNodeStartSpan(range: TextRange) { - recordSourceMapSpan(range.pos, /*skipTrivia*/ true); + recordSourceMapSpan(range.pos !== -1 ? skipTrivia(currentSourceFile.text, range.pos) : -1); } function recordEmitNodeEndSpan(range: TextRange) { - recordSourceMapSpan(range.end, /*skipTrivia*/ false); + recordSourceMapSpan(range.end); } function recordNewSourceFileStart(sourceFile: SourceFile) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9f30968b16e..c42389aee65 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1827,11 +1827,13 @@ namespace ts { } export function nodeIsSynthesized(node: Node): boolean { - return node && node.pos === -1; + return node && positionIsSynthesized(node.pos); } export function positionIsSynthesized(pos: number): boolean { - return pos === -1; + // Using ! with a greater than test is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos <= 0; + return !(pos > 0); } export function childNodeStartPositionIsOnSameLine(sourceFile: SourceFile, parent: Node, child: Node) {