Skip to content

Commit

Permalink
Fix emit for undefined SourceFile
Browse files Browse the repository at this point in the history
  • Loading branch information
jakebailey committed Apr 20, 2022
1 parent d81a976 commit 816cdf0
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 52 deletions.
104 changes: 54 additions & 50 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,8 @@ namespace ts {
}

function getCurrentLineMap() {
return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile!));
Debug.assertIsDefined(currentSourceFile);
return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile));
}

function emit(node: Node, parenthesizerRule?: (node: Node) => Node): void;
Expand Down Expand Up @@ -1815,7 +1816,7 @@ namespace ts {
const numNodes = bundle ? bundle.sourceFiles.length + numPrepends : 1;
for (let i = 0; i < numNodes; i++) {
const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node;
const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile!;
const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile;
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile));
const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit;
const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode);
Expand Down Expand Up @@ -2465,7 +2466,7 @@ namespace ts {
}

const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
const allowTrailingComma = currentSourceFile!.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile!) ? ListFormat.AllowTrailingComma : ListFormat.None;
const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None;
emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine);

if (indentedFlag) {
Expand Down Expand Up @@ -2880,7 +2881,7 @@ namespace ts {
emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfExpressionStatement);
// Emit semicolon in non json files
// or if json file that created synthesized expression(eg.define expression statement when --out and amd code generation)
if (!isJsonSourceFile(currentSourceFile!) || nodeIsSynthesized(node.expression)) {
if (currentSourceFile && !isJsonSourceFile(currentSourceFile) || nodeIsSynthesized(node.expression)) {
writeTrailingSemicolon();
}
}
Expand Down Expand Up @@ -3207,7 +3208,7 @@ namespace ts {
return false;
}

if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile!)) {
if (!nodeIsSynthesized(body) && currentSourceFile && !rangeIsOnSingleLine(body, currentSourceFile)) {
return false;
}

Expand Down Expand Up @@ -3238,12 +3239,7 @@ namespace ts {
? emitBlockFunctionBodyOnSingleLine
: emitBlockFunctionBodyWorker;

if (emitBodyWithDetachedComments) {
emitBodyWithDetachedComments(body, body.statements, emitBlockFunctionBody);
}
else {
emitBlockFunctionBody(body);
}
emitBodyWithDetachedComments(body, body.statements, emitBlockFunctionBody);

decreaseIndent();
writeToken(SyntaxKind.CloseBraceToken, body.statements.end, writePunctuation, body);
Expand Down Expand Up @@ -3701,9 +3697,10 @@ namespace ts {
statements.length === 1 &&
(
// treat synthesized nodes as located on the same line for emit purposes
!currentSourceFile ||
nodeIsSynthesized(parentNode) ||
nodeIsSynthesized(statements[0]) ||
rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile!)
rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)
);

let format = ListFormat.CaseOrDefaultClauseStatements;
Expand Down Expand Up @@ -3958,16 +3955,14 @@ namespace ts {
function emitSourceFile(node: SourceFile) {
writeLine();
const statements = node.statements;
if (emitBodyWithDetachedComments) {
// Emit detached comment if there are no prologue directives or if the first node is synthesized.
// The synthesized node will have no leading comment so some comments may be missed.
const shouldEmitDetachedComment = statements.length === 0 ||
!isPrologueDirective(statements[0]) ||
nodeIsSynthesized(statements[0]);
if (shouldEmitDetachedComment) {
emitBodyWithDetachedComments(node, statements, emitSourceFileWorker);
return;
}
// Emit detached comment if there are no prologue directives or if the first node is synthesized.
// The synthesized node will have no leading comment so some comments may be missed.
const shouldEmitDetachedComment = statements.length === 0 ||
!isPrologueDirective(statements[0]) ||
nodeIsSynthesized(statements[0]);
if (shouldEmitDetachedComment) {
emitBodyWithDetachedComments(node, statements, emitSourceFileWorker);
return;
}
emitSourceFileWorker(node);
}
Expand Down Expand Up @@ -4369,7 +4364,7 @@ namespace ts {

if (isEmpty) {
// Write a line terminator if the parent node was multi-line
if (format & ListFormat.MultiLine && !(preserveSourceNewlines && (!parentNode || rangeIsOnSingleLine(parentNode, currentSourceFile!)))) {
if (format & ListFormat.MultiLine && !(preserveSourceNewlines && (!parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile)))) {
writeLine();
}
else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) {
Expand Down Expand Up @@ -4673,7 +4668,7 @@ namespace ts {

const firstChild = children[0];
if (firstChild === undefined) {
return !parentNode || rangeIsOnSingleLine(parentNode, currentSourceFile!) ? 0 : 1;
return !parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1;
}
if (firstChild.pos === nextListElementPos) {
// If this child starts at the beginning of a list item in a parent list, its leading
Expand All @@ -4697,7 +4692,7 @@ namespace ts {
// JsxText will be written with its leading whitespace, so don't add more manually.
return 0;
}
if (parentNode &&
if (currentSourceFile && parentNode &&
!positionIsSynthesized(parentNode.pos) &&
!nodeIsSynthesized(firstChild) &&
(!firstChild.parent || getOriginalNode(firstChild.parent) === getOriginalNode(parentNode))
Expand All @@ -4707,10 +4702,10 @@ namespace ts {
includeComments => getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter(
firstChild.pos,
parentNode.pos,
currentSourceFile!,
Debug.checkDefined(currentSourceFile),
includeComments));
}
return rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile!) ? 0 : 1;
return rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile) ? 0 : 1;
}
if (synthesizedNodeStartsOnNewLine(firstChild, format)) {
return 1;
Expand All @@ -4728,13 +4723,13 @@ namespace ts {
// JsxText will be written with its leading whitespace, so don't add more manually.
return 0;
}
else if (!nodeIsSynthesized(previousNode) && !nodeIsSynthesized(nextNode)) {
else if (currentSourceFile && !nodeIsSynthesized(previousNode) && !nodeIsSynthesized(nextNode)) {
if (preserveSourceNewlines && siblingNodePositionsAreComparable(previousNode, nextNode)) {
return getEffectiveLines(
includeComments => getLinesBetweenRangeEndAndRangeStart(
previousNode,
nextNode,
currentSourceFile!,
Debug.checkDefined(currentSourceFile),
includeComments));
}
// If `preserveSourceNewlines` is `false` we do not intend to preserve the effective lines between the
Expand All @@ -4743,7 +4738,7 @@ namespace ts {
// expensive than checking with `preserveSourceNewlines` as above, but the goal is not to preserve the
// effective source lines between two sibling nodes.
else if (!preserveSourceNewlines && originalNodesHaveSameParent(previousNode, nextNode)) {
return rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile!) ? 0 : 1;
return rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile) ? 0 : 1;
}
// If the two nodes are not comparable, add a line terminator based on the format that can indicate
// whether new lines are preferred or not.
Expand All @@ -4767,19 +4762,19 @@ namespace ts {

const lastChild = lastOrUndefined(children);
if (lastChild === undefined) {
return !parentNode || rangeIsOnSingleLine(parentNode, currentSourceFile!) ? 0 : 1;
return !parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1;
}
if (parentNode && !positionIsSynthesized(parentNode.pos) && !nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode)) {
if (currentSourceFile && parentNode && !positionIsSynthesized(parentNode.pos) && !nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode)) {
if (preserveSourceNewlines) {
const end = isNodeArray(children) && !positionIsSynthesized(children.end) ? children.end : lastChild.end;
return getEffectiveLines(
includeComments => getLinesBetweenPositionAndNextNonWhitespaceCharacter(
end,
parentNode.end,
currentSourceFile!,
Debug.checkDefined(currentSourceFile),
includeComments));
}
return rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile!) ? 0 : 1;
return rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile) ? 0 : 1;
}
if (synthesizedNodeStartsOnNewLine(lastChild, format)) {
return 1;
Expand Down Expand Up @@ -4857,24 +4852,24 @@ namespace ts {
return 1;
}

if (!nodeIsSynthesized(parent) && !nodeIsSynthesized(node1) && !nodeIsSynthesized(node2)) {
if (currentSourceFile && !nodeIsSynthesized(parent) && !nodeIsSynthesized(node1) && !nodeIsSynthesized(node2)) {
if (preserveSourceNewlines) {
return getEffectiveLines(
includeComments => getLinesBetweenRangeEndAndRangeStart(
node1,
node2,
currentSourceFile!,
Debug.checkDefined(currentSourceFile),
includeComments));
}
return rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile!) ? 0 : 1;
return rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile) ? 0 : 1;
}

return 0;
}

function isEmptyBlock(block: BlockLike) {
return block.statements.length === 0
&& rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile!);
&& (!currentSourceFile || rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile));
}

function skipSynthesizedParentheses(node: Node) {
Expand All @@ -4899,7 +4894,8 @@ namespace ts {
return node.text;
}

return getSourceTextOfNodeFromSourceFile(currentSourceFile!, node, includeTrivia);
Debug.assertIsDefined(currentSourceFile);
return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia);
}

function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
Expand All @@ -4921,7 +4917,7 @@ namespace ts {
| (printerOptions.terminateUnterminatedLiterals ? GetLiteralTextFlags.TerminateUnterminatedLiterals : 0)
| (printerOptions.target && printerOptions.target === ScriptTarget.ESNext ? GetLiteralTextFlags.AllowNumericSeparator : 0);

return getLiteralText(node, currentSourceFile!, flags);
return getLiteralText(node, currentSourceFile, flags);
}

/**
Expand Down Expand Up @@ -5546,15 +5542,16 @@ namespace ts {
}

function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
Debug.assertIsDefined(currentSourceFile);
if (!shouldWriteComment(currentSourceFile.text, commentPos)) return;
if (!hasWrittenComment) {
emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos);
hasWrittenComment = true;
}

// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitPos(commentPos);
writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);

if (hasTrailingNewLine) {
Expand All @@ -5578,14 +5575,15 @@ namespace ts {
}

function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
Debug.assertIsDefined(currentSourceFile);
if (!shouldWriteComment(currentSourceFile.text, commentPos)) return;
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/
if (!writer.isAtStartOfLine()) {
writer.writeSpace(" ");
}

emitPos(commentPos);
writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);

if (hasTrailingNewLine) {
Expand All @@ -5603,10 +5601,11 @@ namespace ts {
}

function emitTrailingCommentOfPositionNoNewline(commentPos: number, commentEnd: number, kind: SyntaxKind) {
Debug.assertIsDefined(currentSourceFile);
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space

emitPos(commentPos);
writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);

if (kind === SyntaxKind.SingleLineCommentTrivia) {
Expand All @@ -5615,10 +5614,11 @@ namespace ts {
}

function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
Debug.assertIsDefined(currentSourceFile);
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space

emitPos(commentPos);
writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);

if (hasTrailingNewLine) {
Expand Down Expand Up @@ -5662,11 +5662,13 @@ namespace ts {
detachedCommentsInfo = undefined;
}

forEachLeadingCommentRange(currentSourceFile!.text, pos, cb, /*state*/ pos);
Debug.assertIsDefined(currentSourceFile);
forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos);
}

function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) {
const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile!.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled);
Debug.assertIsDefined(currentSourceFile);
const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled);
if (currentDetachedCommentInfo) {
if (detachedCommentsInfo) {
detachedCommentsInfo.push(currentDetachedCommentInfo);
Expand All @@ -5678,7 +5680,8 @@ namespace ts {
}

function emitComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
Debug.assertIsDefined(currentSourceFile);
if (!shouldWriteComment(currentSourceFile.text, commentPos)) return;
emitPos(commentPos);
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
Expand All @@ -5690,7 +5693,8 @@ namespace ts {
* @return true if the comment is a triple-slash comment else false
*/
function isTripleSlashComment(commentPos: number, commentEnd: number) {
return isRecognizedTripleSlashComment(currentSourceFile!.text, commentPos, commentEnd);
Debug.assertIsDefined(currentSourceFile);
return isRecognizedTripleSlashComment(currentSourceFile.text, commentPos, commentEnd);
}

// Source Maps
Expand Down
Loading

0 comments on commit 816cdf0

Please sign in to comment.