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