mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix emit for undefined SourceFile (#48774)
Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>
This commit is contained in:
parent
94cb657b1c
commit
07660c8307
@ -1172,7 +1172,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getCurrentLineMap() {
|
||||
return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile!));
|
||||
return currentLineMap || (currentLineMap = getLineStarts(Debug.checkDefined(currentSourceFile)));
|
||||
}
|
||||
|
||||
function emit(node: Node, parenthesizerRule?: (node: Node) => Node): void;
|
||||
@ -1817,7 +1817,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);
|
||||
@ -2467,7 +2467,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) {
|
||||
@ -2882,7 +2882,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();
|
||||
}
|
||||
}
|
||||
@ -3209,7 +3209,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile!)) {
|
||||
if (!nodeIsSynthesized(body) && currentSourceFile && !rangeIsOnSingleLine(body, currentSourceFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3240,12 +3240,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);
|
||||
@ -3703,9 +3698,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;
|
||||
@ -3960,16 +3956,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);
|
||||
}
|
||||
@ -4371,7 +4365,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)) {
|
||||
@ -4675,7 +4669,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
|
||||
@ -4699,7 +4693,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))
|
||||
@ -4712,7 +4706,7 @@ namespace ts {
|
||||
currentSourceFile!,
|
||||
includeComments));
|
||||
}
|
||||
return rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile!) ? 0 : 1;
|
||||
return rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile) ? 0 : 1;
|
||||
}
|
||||
if (synthesizedNodeStartsOnNewLine(firstChild, format)) {
|
||||
return 1;
|
||||
@ -4730,7 +4724,7 @@ 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(
|
||||
@ -4745,7 +4739,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.
|
||||
@ -4769,9 +4763,9 @@ 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(
|
||||
@ -4781,7 +4775,7 @@ namespace ts {
|
||||
currentSourceFile!,
|
||||
includeComments));
|
||||
}
|
||||
return rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile!) ? 0 : 1;
|
||||
return rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile) ? 0 : 1;
|
||||
}
|
||||
if (synthesizedNodeStartsOnNewLine(lastChild, format)) {
|
||||
return 1;
|
||||
@ -4859,7 +4853,7 @@ 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(
|
||||
@ -4868,7 +4862,7 @@ namespace ts {
|
||||
currentSourceFile!,
|
||||
includeComments));
|
||||
}
|
||||
return rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile!) ? 0 : 1;
|
||||
return rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile) ? 0 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -4876,7 +4870,7 @@ namespace ts {
|
||||
|
||||
function isEmptyBlock(block: BlockLike) {
|
||||
return block.statements.length === 0
|
||||
&& rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile!);
|
||||
&& (!currentSourceFile || rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile));
|
||||
}
|
||||
|
||||
function skipSynthesizedParentheses(node: Node) {
|
||||
@ -4887,21 +4881,27 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function getTextOfNode(node: Node, includeTrivia?: boolean): string {
|
||||
function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression, includeTrivia?: boolean): string {
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return generateName(node);
|
||||
}
|
||||
else if ((isIdentifier(node) || isPrivateIdentifier(node)) && (nodeIsSynthesized(node) || !node.parent || !currentSourceFile || (node.parent && currentSourceFile && getSourceFileOfNode(node) !== getOriginalNode(currentSourceFile)))) {
|
||||
return idText(node);
|
||||
if (isStringLiteral(node) && node.textSourceNode) {
|
||||
return getTextOfNode(node.textSourceNode, includeTrivia);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) {
|
||||
return getTextOfNode((node as StringLiteral).textSourceNode!, includeTrivia);
|
||||
const sourceFile = currentSourceFile; // const needed for control flow
|
||||
const canUseSourceFile = !!sourceFile && !!node.parent && !nodeIsSynthesized(node);
|
||||
if (isMemberName(node)) {
|
||||
if (!canUseSourceFile || getSourceFileOfNode(node) !== getOriginalNode(sourceFile)) {
|
||||
return idText(node);
|
||||
}
|
||||
}
|
||||
else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) {
|
||||
return node.text;
|
||||
else {
|
||||
Debug.assertNode(node, isLiteralExpression); // not strictly necessary
|
||||
if (!canUseSourceFile) {
|
||||
return node.text;
|
||||
}
|
||||
}
|
||||
|
||||
return getSourceTextOfNodeFromSourceFile(currentSourceFile!, node, includeTrivia);
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia);
|
||||
}
|
||||
|
||||
function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
|
||||
@ -4923,7 +4923,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5246,7 +5246,7 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return makeUniqueName(
|
||||
getTextOfNode(node),
|
||||
getTextOfNode(node as Identifier),
|
||||
isUniqueName,
|
||||
!!(flags! & GeneratedIdentifierFlags.Optimistic),
|
||||
!!(flags! & GeneratedIdentifierFlags.ReservedInNestedScopes)
|
||||
@ -5548,7 +5548,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
|
||||
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
|
||||
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return;
|
||||
if (!hasWrittenComment) {
|
||||
emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos);
|
||||
hasWrittenComment = true;
|
||||
@ -5556,7 +5556,7 @@ namespace ts {
|
||||
|
||||
// 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) {
|
||||
@ -5580,14 +5580,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
|
||||
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
|
||||
if (!currentSourceFile || !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) {
|
||||
@ -5605,10 +5605,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTrailingCommentOfPositionNoNewline(commentPos: number, commentEnd: number, kind: SyntaxKind) {
|
||||
if (!currentSourceFile) return;
|
||||
// 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) {
|
||||
@ -5617,10 +5618,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
|
||||
if(!currentSourceFile) return;
|
||||
// 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) {
|
||||
@ -5655,6 +5657,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) {
|
||||
if (!currentSourceFile) return;
|
||||
// get the leading comments from detachedPos
|
||||
const pos = last(detachedCommentsInfo!).detachedCommentEndPos;
|
||||
if (detachedCommentsInfo!.length - 1) {
|
||||
@ -5664,11 +5667,11 @@ namespace ts {
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
forEachLeadingCommentRange(currentSourceFile!.text, pos, cb, /*state*/ pos);
|
||||
forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos);
|
||||
}
|
||||
|
||||
function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) {
|
||||
const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile!.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled);
|
||||
const currentDetachedCommentInfo = currentSourceFile && emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled);
|
||||
if (currentDetachedCommentInfo) {
|
||||
if (detachedCommentsInfo) {
|
||||
detachedCommentsInfo.push(currentDetachedCommentInfo);
|
||||
@ -5680,7 +5683,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
|
||||
if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return;
|
||||
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return;
|
||||
emitPos(commentPos);
|
||||
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
|
||||
emitPos(commentEnd);
|
||||
@ -5692,7 +5695,7 @@ 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);
|
||||
return !!currentSourceFile && isRecognizedTripleSlashComment(currentSourceFile.text, commentPos, commentEnd);
|
||||
}
|
||||
|
||||
// Source Maps
|
||||
|
||||
@ -656,10 +656,10 @@ namespace ts {
|
||||
AllowNumericSeparator = 1 << 3
|
||||
}
|
||||
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, flags: GetLiteralTextFlags) {
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | undefined, flags: GetLiteralTextFlags) {
|
||||
// If we don't need to downlevel and we can reach the original source text using
|
||||
// the node's parent reference, then simply get the text as it was originally written.
|
||||
if (canUseOriginalText(node, flags)) {
|
||||
if (sourceFile && canUseOriginalText(node, flags)) {
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user