Skip to content
Merged
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
2 changes: 1 addition & 1 deletion crates/oxc_codegen/examples/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn parse<'a>(

fn codegen(ret: &ParserReturn<'_>, minify: bool) -> String {
Codegen::new()
.with_options(CodegenOptions { minify, ..CodegenOptions::default() })
.with_options(if minify { CodegenOptions::minify() } else { CodegenOptions::default() })
.build(&ret.program)
.code
}
24 changes: 19 additions & 5 deletions crates/oxc_codegen/src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@ pub type CommentsMap = FxHashMap</* attached_to */ u32, Vec<Comment>>;
impl Codegen<'_> {
pub(crate) fn build_comments(&mut self, comments: &[Comment]) {
self.comments.reserve(comments.len());
let move_legal_comments = {
let legal_comments = &self.options.legal_comments;
matches!(
legal_comments,
LegalComment::Eof | LegalComment::Linked(_) | LegalComment::External
)
};
for comment in comments {
// Omit pure comments because they are handled separately.
if comment.is_pure() || comment.is_no_side_effects() {
continue;
}
if comment.is_legal() && move_legal_comments {
self.legal_comments.push(*comment);
}
self.comments.entry(comment.attached_to).or_default().push(*comment);
}
}
Expand All @@ -30,10 +40,10 @@ impl Codegen<'_> {
arguments: &[Argument<'_>],
) -> (bool, bool) {
let has_comment_before_right_paren =
self.print_comments && span.end > 0 && self.has_comment(span.end - 1);
self.print_annotation_comment && span.end > 0 && self.has_comment(span.end - 1);

let has_comment = has_comment_before_right_paren
|| self.print_comments
|| self.print_annotation_comment
&& arguments.iter().any(|item| self.has_comment(item.span().start));

(has_comment, has_comment_before_right_paren)
Expand All @@ -45,7 +55,7 @@ impl Codegen<'_> {
}

pub(crate) fn print_leading_comments(&mut self, start: u32) {
if !self.print_comments {
if !self.print_any_comment {
return;
}
let Some(comments) = self.comments.remove(&start) else {
Expand Down Expand Up @@ -73,7 +83,7 @@ impl Codegen<'_> {
continue;
}
LegalComment::Eof | LegalComment::Linked(_) | LegalComment::External => {
self.legal_comments.push(comment);
/* noop, handled by `build_comments`. */
continue;
}
LegalComment::None => {}
Expand All @@ -90,7 +100,7 @@ impl Codegen<'_> {
/// A statement comment also includes legal comments
#[inline]
pub(crate) fn print_statement_comments(&mut self, start: u32) {
if self.print_comments {
if self.print_any_comment {
if let Some(comments) = self.get_statement_comments(start) {
self.print_comments(&comments);
}
Expand Down Expand Up @@ -178,12 +188,16 @@ impl Codegen<'_> {
match self.options.legal_comments.clone() {
LegalComment::Eof => {
let comments = self.legal_comments.drain(..).collect::<Vec<_>>();
if !comments.is_empty() {
self.print_hard_newline();
}
for c in comments {
self.print_comment(&c);
self.print_hard_newline();
}
}
LegalComment::Linked(path) => {
self.print_hard_newline();
self.print_str("/*! For license information please see ");
self.print_str(&path);
self.print_str(" */");
Expand Down
21 changes: 10 additions & 11 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ impl Gen for Statement<'_> {
Self::ExportDefaultDeclaration(decl) => {
p.print_statement_comments(decl.span.start);
if let ExportDefaultDeclarationKind::FunctionDeclaration(func) = &decl.declaration {
if func.pure && p.options.print_annotation_comments() {
if func.pure && p.print_annotation_comment {
p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
}
}
Expand All @@ -198,7 +198,7 @@ impl Gen for Statement<'_> {
Self::ExportNamedDeclaration(decl) => {
p.print_statement_comments(decl.span.start);
if let Some(Declaration::FunctionDeclaration(func)) = &decl.declaration {
if func.pure && p.options.print_annotation_comments() {
if func.pure && p.print_annotation_comment {
p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
}
}
Expand All @@ -220,7 +220,7 @@ impl Gen for Statement<'_> {
}
Self::FunctionDeclaration(decl) => {
p.print_statement_comments(decl.span.start);
if decl.pure && p.options.print_annotation_comments() {
if decl.pure && p.print_annotation_comment {
p.print_indent();
p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
}
Expand Down Expand Up @@ -803,7 +803,7 @@ impl Gen for Function<'_> {
impl Gen for FunctionBody<'_> {
fn r#gen(&self, p: &mut Codegen, ctx: Context) {
let span_end = self.span.end;
let comments_at_end = if p.print_comments && span_end > 0 {
let comments_at_end = if p.print_any_comment && span_end > 0 {
p.get_statement_comments(span_end - 1)
} else {
None
Expand Down Expand Up @@ -1194,13 +1194,13 @@ impl GenExpr for Expression<'_> {
Self::ArrayExpression(expr) => expr.print(p, ctx),
Self::ObjectExpression(expr) => expr.print_expr(p, precedence, ctx),
Self::FunctionExpression(func) => {
if func.pure && p.options.print_annotation_comments() {
if func.pure && p.print_annotation_comment {
p.print_str(NO_SIDE_EFFECTS_COMMENT);
}
func.print(p, ctx);
}
Self::ArrowFunctionExpression(func) => {
if func.pure && p.options.print_annotation_comments() {
if func.pure && p.print_annotation_comment {
p.print_str(NO_SIDE_EFFECTS_COMMENT);
}
func.print_expr(p, precedence, ctx);
Expand Down Expand Up @@ -1438,7 +1438,7 @@ impl GenExpr for CallExpression<'_> {
let is_statement = p.start_of_stmt == p.code_len();
let is_export_default = p.start_of_default_export == p.code_len();
let mut wrap = precedence >= Precedence::New || ctx.intersects(Context::FORBID_CALL);
let pure = self.pure && p.options.print_annotation_comments();
let pure = self.pure && p.print_annotation_comment;
if precedence >= Precedence::Postfix && pure {
wrap = true;
}
Expand Down Expand Up @@ -2091,10 +2091,9 @@ impl GenExpr for ImportExpression<'_> {
fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
let wrap = precedence >= Precedence::New || ctx.intersects(Context::FORBID_CALL);

let print_comments = p.options.print_comments();
let has_comment_before_right_paren =
print_comments && self.span.end > 0 && p.has_comment(self.span.end - 1);
let has_comment = print_comments
p.options.comments && self.span.end > 0 && p.has_comment(self.span.end - 1);
let has_comment = p.options.comments
&& (has_comment_before_right_paren
|| p.has_comment(self.source.span().start)
|| self
Expand Down Expand Up @@ -2208,7 +2207,7 @@ impl GenExpr for ChainExpression<'_> {
impl GenExpr for NewExpression<'_> {
fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
let mut wrap = precedence >= self.precedence();
let pure = self.pure && p.options.print_annotation_comments();
let pure = self.pure && p.print_annotation_comment;
if precedence >= Precedence::Postfix && pure {
wrap = true;
}
Expand Down
21 changes: 15 additions & 6 deletions crates/oxc_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,11 @@ pub struct Codegen<'a> {

/// Fast path for [CodegenOptions::single_quote]
quote: Quote,

/// Fast path for if print comments
print_comments: bool,
print_any_comment: bool,
print_legal_comment: bool,
print_annotation_comment: bool,

// Builders
comments: CommentsMap,
Expand Down Expand Up @@ -143,7 +146,9 @@ impl<'a> Codegen<'a> {
#[must_use]
pub fn new() -> Self {
let options = CodegenOptions::default();
let print_comments = options.print_comments();
let print_any_comment = options.print_any_comment();
let print_legal_comment = options.print_legal_comment();
let print_annotation_comment = options.print_annotation_comment();
Self {
options,
source_text: "",
Expand All @@ -162,7 +167,9 @@ impl<'a> Codegen<'a> {
is_jsx: false,
indent: 0,
quote: Quote::Double,
print_comments,
print_any_comment,
print_legal_comment,
print_annotation_comment,
comments: CommentsMap::default(),
legal_comments: vec![],
sourcemap_builder: None,
Expand All @@ -173,7 +180,9 @@ impl<'a> Codegen<'a> {
#[must_use]
pub fn with_options(mut self, options: CodegenOptions) -> Self {
self.quote = if options.single_quote { Quote::Single } else { Quote::Double };
self.print_comments = options.print_comments();
self.print_any_comment = options.print_any_comment();
self.print_legal_comment = options.print_legal_comment();
self.print_annotation_comment = options.print_annotation_comment();
self.options = options;
self
}
Expand All @@ -195,9 +204,9 @@ impl<'a> Codegen<'a> {
self.quote = if self.options.single_quote { Quote::Single } else { Quote::Double };
self.source_text = program.source_text;
self.code.reserve(program.source_text.len());
if self.print_comments {
if self.print_any_comment {
if program.comments.is_empty() {
self.print_comments = false;
self.print_any_comment = false;
} else {
self.build_comments(&program.comments);
}
Expand Down
105 changes: 58 additions & 47 deletions crates/oxc_codegen/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,5 @@
use std::path::PathBuf;

/// Legal comment
///
/// <https://esbuild.github.io/api/#legal-comments>
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub enum LegalComment {
/// Do not preserve any legal comments (default).
#[default]
None,
/// Preserve all legal comments.
Inline,
/// Move all legal comments to the end of the file.
Eof,
/// Return all legal comments and link then to them with a comment to the provided string.
Linked(String),
/// Move all legal comments to a .LEGAL.txt file but to not link to them.
External,
}

impl LegalComment {
/// Is None.
pub fn is_none(&self) -> bool {
*self == Self::None
}

/// Is inline mode.
pub fn is_inline(&self) -> bool {
*self == Self::Inline
}

/// Is EOF mode.
pub fn is_eof(&self) -> bool {
*self == Self::Eof
}
}

/// Codegen Options.
#[derive(Debug, Clone)]
pub struct CodegenOptions {
Expand All @@ -55,18 +20,14 @@ pub struct CodegenOptions {

/// Print annotation comments, e.g. `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`.
///
/// Only takes into effect when `comments` is false.
///
/// Default is `false`.
/// Default is `true`.
pub annotation_comments: bool,

/// Print legal comments.
///
/// Only takes into effect when `comments` is false.
///
/// <https://esbuild.github.io/api/#legal-comments>
///
/// Default is [LegalComment::None].
/// Default is [LegalComment::Inline].
pub legal_comments: LegalComment,

/// Override the source map path. This affects the `sourceMappingURL`
Expand All @@ -83,19 +44,69 @@ impl Default for CodegenOptions {
single_quote: false,
minify: false,
comments: true,
annotation_comments: false,
legal_comments: LegalComment::default(),
annotation_comments: true,
legal_comments: LegalComment::Inline,
source_map_path: None,
}
}
}

impl CodegenOptions {
pub(crate) fn print_comments(&self) -> bool {
!self.minify && (self.comments || self.legal_comments.is_inline())
/// Minify whitespace and remove comments.
pub fn minify() -> Self {
Self {
single_quote: false,
minify: true,
comments: false,
annotation_comments: false,
legal_comments: LegalComment::None,
source_map_path: None,
}
}

pub(crate) fn print_any_comment(&self) -> bool {
self.comments
}

pub(crate) fn print_legal_comment(&self) -> bool {
self.comments || !self.legal_comments.is_none()
}

pub(crate) fn print_annotation_comment(&self) -> bool {
self.comments || self.annotation_comments
}
}

/// Legal comment
///
/// <https://esbuild.github.io/api/#legal-comments>
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum LegalComment {
/// Do not preserve any legal comments.
None,
/// Preserve all legal comments (default).
Inline,
/// Move all legal comments to the end of the file.
Eof,
/// Return all legal comments and link then to them with a comment to the provided string.
Linked(String),
/// Move all legal comments to a .LEGAL.txt file but to not link to them.
External,
}

impl LegalComment {
/// Is None.
pub fn is_none(&self) -> bool {
*self == Self::None
}

pub(crate) fn print_annotation_comments(&self) -> bool {
!self.minify && (self.comments || self.annotation_comments)
/// Is inline mode.
pub fn is_inline(&self) -> bool {
*self == Self::Inline
}

/// Is EOF mode.
pub fn is_eof(&self) -> bool {
*self == Self::Eof
}
}
10 changes: 10 additions & 0 deletions crates/oxc_codegen/tests/integration/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ pub mod legal {
snapshot_options("legal_eof_comments", &cases(), &options);
}

#[test]
fn legal_eof_minify_comment() {
let options = CodegenOptions {
minify: true,
legal_comments: LegalComment::Eof,
..Default::default()
};
snapshot_options("legal_eof_minify_comments", &cases(), &options);
}

#[test]
fn legal_linked_comment() {
let options = CodegenOptions {
Expand Down
Loading
Loading