From f85634ca3e81da39ac591e72cb429854fd8ba2c6 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Fri, 5 May 2023 06:17:46 +0200 Subject: [PATCH] Keep leading comments on consecutive lines (#4975) --- src/ast/nodes/Program.ts | 16 +++++++++++++++- src/utils/renderHelpers.ts | 2 +- test/form/samples/leading-comments/_config.js | 6 ++++++ test/form/samples/leading-comments/_expected.js | 13 +++++++++++++ test/form/samples/leading-comments/dep.js | 7 +++++++ test/form/samples/leading-comments/main.js | 6 ++++++ .../pure-comment-scenarios-complex/_expected.js | 1 + .../remove-treeshaken-banners/_expected.js | 1 + .../render-removed-statements/_expected.js | 1 + 9 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 test/form/samples/leading-comments/_config.js create mode 100644 test/form/samples/leading-comments/_expected.js create mode 100644 test/form/samples/leading-comments/dep.js create mode 100644 test/form/samples/leading-comments/main.js diff --git a/src/ast/nodes/Program.ts b/src/ast/nodes/Program.ts index e82cc2bf2b6..f5f260e06aa 100644 --- a/src/ast/nodes/Program.ts +++ b/src/ast/nodes/Program.ts @@ -3,7 +3,11 @@ import type MagicString from 'magic-string'; import getCodeFrame from '../../utils/getCodeFrame'; import { getOriginalLocation } from '../../utils/getOriginalLocation'; import relativeId from '../../utils/relativeId'; -import { type RenderOptions, renderStatementList } from '../../utils/renderHelpers'; +import { + findFirstLineBreakOutsideComment, + type RenderOptions, + renderStatementList +} from '../../utils/renderHelpers'; import type { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import { createHasEffectsContext } from '../ExecutionContext'; import type * as NodeType from './NodeType'; @@ -79,6 +83,16 @@ export default class Program extends NodeBase { code.remove(0, start); } if (this.body.length > 0) { + // Keep all consecutive lines that start with a comment + while (code.original[start] === '/' && /[*/]/.test(code.original[start + 1])) { + const firstLineBreak = findFirstLineBreakOutsideComment( + code.original.slice(start, this.body[0].start) + ); + if (firstLineBreak[0] === -1) { + break; + } + start += firstLineBreak[1]; + } renderStatementList(this.body, code, start, this.end, options); } else { super.render(code, options); diff --git a/src/utils/renderHelpers.ts b/src/utils/renderHelpers.ts index c3e3b080841..89b486ee777 100644 --- a/src/utils/renderHelpers.ts +++ b/src/utils/renderHelpers.ts @@ -70,7 +70,7 @@ export function findNonWhiteSpace(code: string, index: number): number { // This assumes "code" only contains white-space and comments // Returns position of line-comment if applicable -function findFirstLineBreakOutsideComment(code: string): [number, number] { +export function findFirstLineBreakOutsideComment(code: string): [number, number] { let lineBreakPos, charCodeAfterSlash, start = 0; diff --git a/test/form/samples/leading-comments/_config.js b/test/form/samples/leading-comments/_config.js new file mode 100644 index 00000000000..0df87ffe825 --- /dev/null +++ b/test/form/samples/leading-comments/_config.js @@ -0,0 +1,6 @@ +module.exports = defineTest({ + description: 'keeps leading comments on consecutive lines', + options: { + external: ['external'] + } +}); diff --git a/test/form/samples/leading-comments/_expected.js b/test/form/samples/leading-comments/_expected.js new file mode 100644 index 00000000000..9975cfbc807 --- /dev/null +++ b/test/form/samples/leading-comments/_expected.js @@ -0,0 +1,13 @@ +import 'external'; + +// comment dep 1/3 +/* comment +*/ // comment dep 2/3 +// comment dep 3/3 + +console.log('dep'); + +// comment main 1/2 +// comment main 2/2 + +console.log('main'); diff --git a/test/form/samples/leading-comments/dep.js b/test/form/samples/leading-comments/dep.js new file mode 100644 index 00000000000..dffa1075a82 --- /dev/null +++ b/test/form/samples/leading-comments/dep.js @@ -0,0 +1,7 @@ +// comment dep 1/3 +/* comment +*/ // comment dep 2/3 +// comment dep 3/3 +/* import comment */ import 'external'; + +console.log('dep'); diff --git a/test/form/samples/leading-comments/main.js b/test/form/samples/leading-comments/main.js new file mode 100644 index 00000000000..f17e3915705 --- /dev/null +++ b/test/form/samples/leading-comments/main.js @@ -0,0 +1,6 @@ +#! /usr/bin/env node +// comment main 1/2 +// comment main 2/2 +import './dep.js'; + +console.log('main'); diff --git a/test/form/samples/pure-comment-scenarios-complex/_expected.js b/test/form/samples/pure-comment-scenarios-complex/_expected.js index 11dd422687e..bc4b8984dce 100644 --- a/test/form/samples/pure-comment-scenarios-complex/_expected.js +++ b/test/form/samples/pure-comment-scenarios-complex/_expected.js @@ -1,5 +1,6 @@ // pure top-level IIFE will be dropped + // pure top-level IIFE assigned to unreferenced var will not be dropped global.iife1 = /*@__PURE__*/(function() { console.log("iife1"); diff --git a/test/form/samples/remove-treeshaken-banners/_expected.js b/test/form/samples/remove-treeshaken-banners/_expected.js index 054d5981ded..41986884c32 100644 --- a/test/form/samples/remove-treeshaken-banners/_expected.js +++ b/test/form/samples/remove-treeshaken-banners/_expected.js @@ -1,4 +1,5 @@ // dep included banner: included + console.log('dep included'); // dep included footer: included diff --git a/test/form/samples/render-removed-statements/_expected.js b/test/form/samples/render-removed-statements/_expected.js index 6f8e622701a..707551fa6aa 100644 --- a/test/form/samples/render-removed-statements/_expected.js +++ b/test/form/samples/render-removed-statements/_expected.js @@ -1,4 +1,5 @@ /* header retained */ + /* lead retained */ console.log(2); // trail retained console.log(2); // trail retained