diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c60fd92787275..c907b2453090d 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6104,10 +6104,39 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) { // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments if (currentSourceFile && (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd))) { - forEachTrailingCommentRange(currentSourceFile.text, end, cb); + // Create a wrapper callback that filters out comments that are part of JSX text content + const filteredCb = (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => { + // Check if this comment is actually JSX text content + if (isCommentWithinJsxText(commentPos, commentEnd)) { + return; // Skip this comment emission + } + cb(commentPos, commentEnd, kind, hasTrailingNewLine); + }; + + forEachTrailingCommentRange(currentSourceFile.text, end, filteredCb); } } + function isCommentWithinJsxText(commentPos: number, commentEnd: number): boolean { + if (!currentSourceFile) return false; + + // Find JSX text nodes that might contain this comment + function checkNode(node: Node): boolean { + if (node.kind === SyntaxKind.JsxText) { + const jsxText = node as JsxText; + // Check if the comment range is within the JSX text node range + if (commentPos >= jsxText.pos && commentEnd <= jsxText.end) { + return true; + } + } + + // Recursively check children + return !!forEachChild(node, checkNode); + } + + return checkNode(currentSourceFile); + } + function hasDetachedComments(pos: number) { return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos; } diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).js b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).js new file mode 100644 index 0000000000000..e6e31288aa05d --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).js @@ -0,0 +1,11 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +//// [jsxCommentDuplication.tsx] +// Simple test case to reproduce JSX comment duplication +const x = 42; +const jsx =
/*pre*/{x}/*post*/
; + +//// [jsxCommentDuplication.jsx] +// Simple test case to reproduce JSX comment duplication +var x = 42; +var jsx =
/*pre*/{x}/*post*/
; diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).symbols b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).symbols new file mode 100644 index 0000000000000..bb4f837dbfc9e --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).symbols @@ -0,0 +1,11 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +=== jsxCommentDuplication.tsx === +// Simple test case to reproduce JSX comment duplication +const x = 42; +>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5)) + +const jsx =
/*pre*/{x}/*post*/
; +>jsx : Symbol(jsx, Decl(jsxCommentDuplication.tsx, 2, 5)) +>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5)) + diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).types b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).types new file mode 100644 index 0000000000000..2c9cdbd68a0f4 --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=preserve).types @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +=== jsxCommentDuplication.tsx === +// Simple test case to reproduce JSX comment duplication +const x = 42; +>x : 42 +> : ^^ +>42 : 42 +> : ^^ + +const jsx =
/*pre*/{x}/*post*/
; +>jsx : error +>
/*pre*/{x}/*post*/
: error +>div : any +> : ^^^ +>x : 42 +> : ^^ +>div : any +> : ^^^ + diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).errors.txt b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).errors.txt new file mode 100644 index 0000000000000..aefdad9e893ce --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).errors.txt @@ -0,0 +1,9 @@ +jsxCommentDuplication.tsx(3,13): error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. + + +==== jsxCommentDuplication.tsx (1 errors) ==== + // Simple test case to reproduce JSX comment duplication + const x = 42; + const jsx =
/*pre*/{x}/*post*/
; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed. \ No newline at end of file diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).js b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).js new file mode 100644 index 0000000000000..c663c49b539ec --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).js @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +//// [jsxCommentDuplication.tsx] +// Simple test case to reproduce JSX comment duplication +const x = 42; +const jsx =
/*pre*/{x}/*post*/
; + +//// [jsxCommentDuplication.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var jsx_runtime_1 = require("react/jsx-runtime"); +// Simple test case to reproduce JSX comment duplication +var x = 42; +var jsx = (0, jsx_runtime_1.jsxs)("div", { children: ["/*pre*/", x, "/*post*/"] }); diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).symbols b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).symbols new file mode 100644 index 0000000000000..bb4f837dbfc9e --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).symbols @@ -0,0 +1,11 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +=== jsxCommentDuplication.tsx === +// Simple test case to reproduce JSX comment duplication +const x = 42; +>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5)) + +const jsx =
/*pre*/{x}/*post*/
; +>jsx : Symbol(jsx, Decl(jsxCommentDuplication.tsx, 2, 5)) +>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5)) + diff --git a/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).types b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).types new file mode 100644 index 0000000000000..0ee7b9eb8dcfa --- /dev/null +++ b/tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).types @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/jsxCommentDuplication.tsx] //// + +=== jsxCommentDuplication.tsx === +// Simple test case to reproduce JSX comment duplication +const x = 42; +>x : 42 +> : ^^ +>42 : 42 +> : ^^ + +const jsx =
/*pre*/{x}/*post*/
; +>jsx : any +> : ^^^ +>
/*pre*/{x}/*post*/
: any +> : ^^^ +>div : any +> : ^^^ +>x : 42 +> : ^^ +>div : any +> : ^^^ + diff --git a/tests/cases/compiler/jsxCommentDuplication.tsx b/tests/cases/compiler/jsxCommentDuplication.tsx new file mode 100644 index 0000000000000..4ff65ddd631d6 --- /dev/null +++ b/tests/cases/compiler/jsxCommentDuplication.tsx @@ -0,0 +1,4 @@ +// @jsx: preserve,react-jsx +// Simple test case to reproduce JSX comment duplication +const x = 42; +const jsx =
/*pre*/{x}/*post*/
; \ No newline at end of file