Skip to content

Fix JSX comment duplication in preserve mode #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions tests/baselines/reference/jsxCommentDuplication(jsx=preserve).js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//// [tests/cases/compiler/jsxCommentDuplication.tsx] ////

//// [jsxCommentDuplication.tsx]
// Simple test case to reproduce JSX comment duplication
const x = 42;
const jsx = <div>/*pre*/{x}/*post*/</div>;

//// [jsxCommentDuplication.jsx]
// Simple test case to reproduce JSX comment duplication
var x = 42;
var jsx = <div>/*pre*/{x}/*post*/</div>;
Original file line number Diff line number Diff line change
@@ -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 = <div>/*pre*/{x}/*post*/</div>;
>jsx : Symbol(jsx, Decl(jsxCommentDuplication.tsx, 2, 5))
>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5))

Original file line number Diff line number Diff line change
@@ -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 = <div>/*pre*/{x}/*post*/</div>;
>jsx : error
><div>/*pre*/{x}/*post*/</div> : error
>div : any
> : ^^^
>x : 42
> : ^^
>div : any
> : ^^^

Original file line number Diff line number Diff line change
@@ -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 = <div>/*pre*/{x}/*post*/</div>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! 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.
14 changes: 14 additions & 0 deletions tests/baselines/reference/jsxCommentDuplication(jsx=react-jsx).js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/jsxCommentDuplication.tsx] ////

//// [jsxCommentDuplication.tsx]
// Simple test case to reproduce JSX comment duplication
const x = 42;
const jsx = <div>/*pre*/{x}/*post*/</div>;

//// [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*/"] });
Original file line number Diff line number Diff line change
@@ -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 = <div>/*pre*/{x}/*post*/</div>;
>jsx : Symbol(jsx, Decl(jsxCommentDuplication.tsx, 2, 5))
>x : Symbol(x, Decl(jsxCommentDuplication.tsx, 1, 5))

Original file line number Diff line number Diff line change
@@ -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 = <div>/*pre*/{x}/*post*/</div>;
>jsx : any
> : ^^^
><div>/*pre*/{x}/*post*/</div> : any
> : ^^^
>div : any
> : ^^^
>x : 42
> : ^^
>div : any
> : ^^^

4 changes: 4 additions & 0 deletions tests/cases/compiler/jsxCommentDuplication.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @jsx: preserve,react-jsx
// Simple test case to reproduce JSX comment duplication
const x = 42;
const jsx = <div>/*pre*/{x}/*post*/</div>;