Skip to content
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

refactor(ast_codegen): replace Windows-style line breaks with Unix-style #4769

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
168 changes: 84 additions & 84 deletions crates/oxc_ast_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,84 @@
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
/// returns `#[repr(C, u8)]` if `enum_` has any non-unit variant,
/// Otherwise it would return `#[repr(u8)]`.
fn enum_repr(enum_: &syn::ItemEnum) -> TokenStream2 {
if enum_.variants.iter().any(|var| !matches!(var.fields, syn::Fields::Unit)) {
quote!(#[repr(C, u8)])
} else {
quote!(#[repr(u8)])
}
}
/// This attribute serves two purposes,
/// First, it is a marker for our codegen to detect AST types. Furthermore.
/// It is also a lightweight macro; All of its computation is cached and
/// it only applies the following changes without any complex operation:
///
/// * Prepend `#[repr(C)]` to structs
/// * Prepend `#[repr(C, u8)]` to fieldful enums e.g. `enum E { X: u32, Y: u8 }`
/// * Prepend `#[repr(u8)]` to unit (fieldless) enums e.g. `enum E { X, Y, Z, }`
/// * Prepend `#[derive(oxc_ast_macros::Ast)]` to all structs and enums
///
#[proc_macro_attribute]
#[allow(clippy::missing_panics_doc)]
pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::Item);
let repr = match input {
syn::Item::Enum(ref enum_) => enum_repr(enum_),
syn::Item::Struct(_) => quote!(#[repr(C)]),
_ => {
unreachable!()
}
};
let expanded = quote! {
#[derive(::oxc_ast_macros::Ast)]
#repr
#input
};
TokenStream::from(expanded)
}
/// Dummy derive macro for a non-existent trait `Ast`.
///
/// Does not generate any code.
/// Only purpose is to allow using `#[scope]`, `#[visit]`, and other attrs in the AST node type defs.
/// These "marker" attributes are used in codegen.
#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive))]
pub fn ast_derive(_item: TokenStream) -> TokenStream {
TokenStream::new()
}
/// Derive macro generating an impl of the trait `CloneIn`.
///
/// NOTE: This is an internal macro!
/// # Panics
///
#[proc_macro_derive(CloneIn)]
pub fn derive_clone_in(item: TokenStream) -> TokenStream {
let item = syn::parse_macro_input!(item as syn::Item);
match &item {
syn::Item::Struct(syn::ItemStruct { ident, generics, .. })
| syn::Item::Enum(syn::ItemEnum { ident, generics, .. })
if generics.params.is_empty() =>
{
quote! {
#[automatically_derived]
impl<'alloc> ::oxc_allocator::CloneIn<'alloc> for #ident {
type Cloned = #ident;
fn clone_in(&self, _: &'alloc ::oxc_allocator::Allocator) -> Self::Cloned {
std::clone::Clone::clone(self)
}
}
}
.into()
}
_ => panic!("At the moment `CloneIn` derive macro only works for types without lifetimes and/or generic params"),
}
}
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;

/// returns `#[repr(C, u8)]` if `enum_` has any non-unit variant,
/// Otherwise it would return `#[repr(u8)]`.
fn enum_repr(enum_: &syn::ItemEnum) -> TokenStream2 {
if enum_.variants.iter().any(|var| !matches!(var.fields, syn::Fields::Unit)) {
quote!(#[repr(C, u8)])
} else {
quote!(#[repr(u8)])
}
}

/// This attribute serves two purposes,
/// First, it is a marker for our codegen to detect AST types. Furthermore.
/// It is also a lightweight macro; All of its computation is cached and
/// it only applies the following changes without any complex operation:
///
/// * Prepend `#[repr(C)]` to structs
/// * Prepend `#[repr(C, u8)]` to fieldful enums e.g. `enum E { X: u32, Y: u8 }`
/// * Prepend `#[repr(u8)]` to unit (fieldless) enums e.g. `enum E { X, Y, Z, }`
/// * Prepend `#[derive(oxc_ast_macros::Ast)]` to all structs and enums
///
#[proc_macro_attribute]
#[allow(clippy::missing_panics_doc)]
pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::Item);

let repr = match input {
syn::Item::Enum(ref enum_) => enum_repr(enum_),
syn::Item::Struct(_) => quote!(#[repr(C)]),

_ => {
unreachable!()
}
};

let expanded = quote! {
#[derive(::oxc_ast_macros::Ast)]
#repr
#input
};
TokenStream::from(expanded)
}

/// Dummy derive macro for a non-existent trait `Ast`.
///
/// Does not generate any code.
/// Only purpose is to allow using `#[scope]`, `#[visit]`, and other attrs in the AST node type defs.
/// These "marker" attributes are used in codegen.
#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive))]
pub fn ast_derive(_item: TokenStream) -> TokenStream {
TokenStream::new()
}

/// Derive macro generating an impl of the trait `CloneIn`.
///
/// NOTE: This is an internal macro!
/// # Panics
///
#[proc_macro_derive(CloneIn)]
pub fn derive_clone_in(item: TokenStream) -> TokenStream {
let item = syn::parse_macro_input!(item as syn::Item);
match &item {
syn::Item::Struct(syn::ItemStruct { ident, generics, .. })
| syn::Item::Enum(syn::ItemEnum { ident, generics, .. })
if generics.params.is_empty() =>
{
quote! {
#[automatically_derived]
impl<'alloc> ::oxc_allocator::CloneIn<'alloc> for #ident {
type Cloned = #ident;

fn clone_in(&self, _: &'alloc ::oxc_allocator::Allocator) -> Self::Cloned {
std::clone::Clone::clone(self)
}
}
}
.into()
}
_ => panic!("At the moment `CloneIn` derive macro only works for types without lifetimes and/or generic params"),
}
}
116 changes: 58 additions & 58 deletions crates/oxc_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
use proc_macro::TokenStream;
use syn::parse_macro_input;
mod declare_all_lint_rules;
mod declare_oxc_lint;
/// Macro used to declare an oxc lint rule
///
/// Every lint declaration consists of 2 parts:
///
/// 1. The documentation
/// 2. The lint's struct
///
/// # Example
///
/// ```
/// use oxc_macros::declare_oxc_lint;
///
/// declare_oxc_lint! {
/// /// ### What it does
/// /// Checks for usage of the `debugger` statement
/// ///
/// /// ### Why is this bad?
/// /// `debugger` statements do not affect functionality when a debugger isn't attached.
/// /// They're most commonly an accidental debugging leftover.
/// ///
/// ///
/// /// ### Example
/// /// ```javascript
/// /// const data = await getData();
/// /// const result = complexCalculation(data);
/// /// debugger;
/// /// ```
/// ///
/// /// ```
/// pub struct NoDebugger
/// }
/// ```
#[proc_macro]
pub fn declare_oxc_lint(input: TokenStream) -> TokenStream {
let metadata = parse_macro_input!(input as declare_oxc_lint::LintRuleMeta);
declare_oxc_lint::declare_oxc_lint(metadata)
}
/// Same as `declare_oxc_lint`, but doesn't do imports.
/// Enables multiple usages in a single file.
#[proc_macro]
pub fn declare_oxc_lint_test(input: TokenStream) -> TokenStream {
let mut metadata = parse_macro_input!(input as declare_oxc_lint::LintRuleMeta);
metadata.used_in_test = true;
declare_oxc_lint::declare_oxc_lint(metadata)
}
#[proc_macro]
pub fn declare_all_lint_rules(input: TokenStream) -> TokenStream {
let metadata = parse_macro_input!(input as declare_all_lint_rules::AllLintRulesMeta);
declare_all_lint_rules::declare_all_lint_rules(metadata)
}
use proc_macro::TokenStream;
use syn::parse_macro_input;

mod declare_all_lint_rules;
mod declare_oxc_lint;

/// Macro used to declare an oxc lint rule
///
/// Every lint declaration consists of 2 parts:
///
/// 1. The documentation
/// 2. The lint's struct
///
/// # Example
///
/// ```
/// use oxc_macros::declare_oxc_lint;
///
/// declare_oxc_lint! {
/// /// ### What it does
/// /// Checks for usage of the `debugger` statement
/// ///
/// /// ### Why is this bad?
/// /// `debugger` statements do not affect functionality when a debugger isn't attached.
/// /// They're most commonly an accidental debugging leftover.
/// ///
/// ///
/// /// ### Example
/// /// ```javascript
/// /// const data = await getData();
/// /// const result = complexCalculation(data);
/// /// debugger;
/// /// ```
/// ///
/// /// ```
/// pub struct NoDebugger
/// }
/// ```
#[proc_macro]
pub fn declare_oxc_lint(input: TokenStream) -> TokenStream {
let metadata = parse_macro_input!(input as declare_oxc_lint::LintRuleMeta);
declare_oxc_lint::declare_oxc_lint(metadata)
}

/// Same as `declare_oxc_lint`, but doesn't do imports.
/// Enables multiple usages in a single file.
#[proc_macro]
pub fn declare_oxc_lint_test(input: TokenStream) -> TokenStream {
let mut metadata = parse_macro_input!(input as declare_oxc_lint::LintRuleMeta);
metadata.used_in_test = true;
declare_oxc_lint::declare_oxc_lint(metadata)
}

#[proc_macro]
pub fn declare_all_lint_rules(input: TokenStream) -> TokenStream {
let metadata = parse_macro_input!(input as declare_all_lint_rules::AllLintRulesMeta);
declare_all_lint_rules::declare_all_lint_rules(metadata)
}