Commit graph

50 commits

Author SHA1 Message Date
Boshen
051ceb6539
chore: improve some format by running cargo +nightly fmt 2024-06-19 00:48:30 +08:00
Boshen
982e6f08df chore: make println and eprintln opt-in (#3712)
I noticed accidental `println` can be merged, which isn't really nice.
2024-06-17 10:40:34 +00:00
Boshen
f6752b482f
feat!(ast): make Trivias clonable by adding Arc (#3638)
This makes `Trivias` cloneable and stops us from using `Rc::new` and
`Rc::clone` everywhere.

`Trivias` is rarely cloned so an `Arc` should suffice.
2024-06-12 13:16:10 +08:00
renovate[bot]
56a0db8621
chore(deps): update dependency rust to v1.78.0 (#3151) 2024-05-03 00:01:42 +08:00
overlookmotel
7e1fe36c68
refactor(ast): squash nested enums (#3115)
OK, this is a big one...

I have done this as part of work on Traversable AST, but I believe it
has wider benefits, so thought better to spin it off into its own PR.

## What this PR does

This PR squashes all nested AST enum types (#2685).

e.g.: Previously:

```rs
pub enum Statement<'a> {
    BlockStatement(Box<'a, BlockStatement<'a>>),
    /* ...other Statement variants... */
    Declaration(Declaration<'a>),
}

pub enum Declaration<'a> {
    VariableDeclaration(Box<'a, VariableDeclaration<'a>>),
    /* ...other Declaration variants... */
}
```

After this PR:

```rs
#[repr(C, u8)]
pub enum Statement<'a> {
    BlockStatement(Box<'a, BlockStatement<'a>>) = 0,
    /* ...other Statement variants... */

    VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
    /* ...other Declaration variants... */
}

#[repr(C, u8)]
pub enum Declaration<'a> {
    VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
    /* ...other Declaration variants... */
}
```

All `Declaration`'s variants are combined into `Statement`, but
`Declaration` type still exists.

As both types are `#[repr(C, u8)]`, and the discriminants are aligned, a
`Declaration` can be transmuted to a `Statement` at zero cost.

This is the same thing as #2847, but here applied to *all* nested enums
in the AST, and with improved helper methods.

No enums increase in size, and a few get smaller. Indirection is reduced
for some types (this removes multiple levels of boxing).

## Why?

1. It is a prerequisite for Traversable AST (#2987).
2. It would help a lot with AST Transfer (#2409) - it solves the only
remaining blocker for this.
3. It is a step closer to making the whole AST `#[repr(C)]`.

## Why is it a good thing for the AST to be `#[repr(C)]`?

Oxc's direction appears to be increasingly to build up control over the
fundamental primitives we use, in order to unlock performance and
features. We have our own allocator, our own custom implementations for
`Box` and `Vec`, our own `IndexVec` (TBC). The AST is the central
building block of Oxc, and taking control of its memory layout feels
like a step in this same direction.

Oxc has a major advantage over other similar libraries in that it keeps
all the AST data in an arena. This opens the door to treating the AST
either as Rust types or as *pure data* (just bytes). That data can be
moved around and manipulated beyond what Rust natively allows.

However, to enable that, the types need to be well-specified, with
completely stable layouts. `#[repr(C)]` is the only tool Rust provides
to do this.

Once the types are `#[repr(C)]`, various features become possible:

1. Cheap transfer of the AST across boundaries without ser/deser - the
property used by AST Transfer.
2. Having multiple versions of the AST (standard, read-only,
traversable), and these AST representations can be converted to one
other at zero cost via transmute - the property used by Traversable AST
scheme.
3. Caching AST data on disk (#3079) or transferring across network.
4. Stuff we haven't thought of yet!

Allowing the AST to be treated as pure data will likely unlock other
"next level" features further down the track (caching for "edge
bundling" comes to mind).

## The problem with `#[repr(C)]`

It's not *required* to squash nested enums to make the AST `#[repr(C)]`.

But the problem with `#[repr(C)]` is that it disables some compiler
optimizations. Without `#[repr(C)]`, the compiler squashes enums itself
in some cases (which is how `Statement` is currently 16 bytes). But
making the types `#[repr(C)]` as they are currently disables this
optimization.

So this PR essentially makes explicit what the compiler is already doing
- and in fact goes a bit further with the optimization than the compiler
is able to, in squashing 3 or 4 layers of nested enums (the compiler
only does up to 2 layers).

## Implementation

One enum "inheriting" variants from another is implemented with
`inherit_variants!` macro.

```rs
inherit_variants! {
#[repr(C, u8)]
pub enum Statement<'a> {
    BlockStatement(Box<'a, BlockStatement<'a>>),
    /* ...other Statement variants... */
    
    // `Declaration` variants added here by `inherit_variants!` macro
    @inherit Declaration
    // `ModuleDeclaration` variants added here by `inherit_variants!` macro
    @inherit ModuleDeclaration
}
}
```

The macro is *fairly* lightweight, and I think the above is quite easy
to understand. No proc macros.

The macro also implements utility methods for converting between enums
e.g. `Statement::as_declaration`. These methods are all zero-cost
(essentially transmutes).

New patterns for dealing with nested enums are introduced:

Creation:

```rs
// Old
let stmt = Statement::Declaration(Declaration::VariableDeclaration(var_decl));

// New
let stmt = Statement::VariableDeclaration(var_decl);
```

Conversion:

```rs
// Old
let stmt = Statement::Declaration(decl);

// New
let stmt = Statement::from(decl);
```

Testing:

```rs
// Old
if matches!(stmt, Statement::Declaration(_)) { }
if matches!(stmt, Statement::ModuleDeclaration(m) if m.is_import()) { }

// New
if stmt.is_declaration() { }
if matches!(stmt, Statement::ImportDeclaration(_)) { }
```

Branching:

```rs
// Old
if let Statement::Declaration(decl) = &stmt { decl.do_stuff() };

// New
if let Some(decl) = stmt.as_declaration() { decl.do_stuff() };
```

Matching:

```rs
// Old
match stmt {
    Statement::Declaration(decl) => visitor.visit(decl),
}

// New (exhaustive match)
match stmt {
    match_declaration!(Statement) => visitor.visit(stmt.to_declaration()),
}

// New (alternative)
match stmt {
    _ if stmt.is_declaration() => visitor.visit(stmt.to_declaration()),
}
```

New syntax has pluses and minuses vs the old. `match` syntax is worse,
but when working with a deeply nested enum, the code is much nicer -
it's shorter and easier to read.

This PR removes 200 lines from the linter with changes like this:


https://github.com/oxc-project/oxc/pull/3115/files#diff-dc417ff57352da6727a760ec6dee22de6816f8231fb69dbef1bf05d478699103L92-R95

```diff
- let AssignmentTarget::SimpleAssignmentTarget(simple_assignment_target) =
-     &assignment_expr.left
- else {
-     return;
- };
- let SimpleAssignmentTarget::AssignmentTargetIdentifier(ident) =
-     simple_assignment_target
+ let AssignmentTarget::AssignmentTargetIdentifier(ident) = &assignment_expr.left
else {
    return;
};
```
2024-04-28 20:40:37 +08:00
Boshen
0f86333437
refactor(ast): refactor Trivias API - have less noise around it (#2692) 2024-03-12 20:16:36 +08:00
magic-akari
61afa70bb8
feat(prettier): print with_clause (#2632) 2024-03-07 12:22:30 +08:00
Boshen
be6b8b7ce6
[BREAKING CHANGE] Change Atom to Atom<'a> to make it safe (#2497)
Part of #2295

This PR splits the `Atom` type into `Atom<'a>` and `CompactString`.

All the AST node strings now use `Atom<'a>` instead of `Atom` to signify
it belongs to the arena.

It is now up to the user to select which form of the string to use.

This PR essentially removes the really unsafe code 


93742f89e9/crates/oxc_span/src/atom.rs (L98-L107)

which can lead to 

![image](https://github.com/oxc-project/oxc/assets/1430279/8c513c4f-19b0-4b63-b61c-e07c187c95b5)
2024-02-26 19:34:40 +08:00
Boshen
d08abc638e refactor(ast): s/NumberLiteral/NumericLiteral to align with estree 2024-02-21 21:41:08 +08:00
Boshen
83cb78fbb0
feat(coverage): add prettier idempotency test (#2403)
feat(coverage): add prettier idempotency test

closes #1329

feat(prettier_conformance): enable TypeScript
2024-02-12 16:20:09 +08:00
Boshen
70a0076eed
refactor: remove global allocator from non-user facing apps (#2401)
The runtime performance gains does not out weight the compilation speed from
building the custom allocators, which takes about a minute to build on
slower machines.
2024-02-12 14:09:05 +08:00
Boshen
15a8857927
refactor(prettier): improve print_statement_sequence (#2383) 2024-02-11 00:16:26 +08:00
Dunqing
3268d7d66e
feat(tasks/prettier): add some information for debug no spec calls (#2333) 2024-02-07 16:55:59 +08:00
Boshen
e8dc68c525
chore: update prettier to v3.2.5 (#2332) 2024-02-06 22:55:43 +08:00
Boshen
a69b76ab77
chore: update snapshots 2024-01-15 21:13:05 +08:00
Dunqing
0c19991471
feat(prettier): print CallExpression arguments correctly (#1631) 2023-12-10 15:59:13 +08:00
Wenzhe Wang
bb4a2c7930
chore: fix typo (#1627) 2023-12-04 21:52:50 +08:00
Wenzhe Wang
cfe207fb53
feat(tasks): ignore some invalid cases and support read parser from source text (#1616) 2023-12-03 21:17:47 +08:00
Wenzhe Wang
9af24842a8
fix(tasks): escape more special characters (#1615)
We also need escape `$` and `\`:
9527e65a38/packages/snapshot/src/port/inlineSnapshot.ts (L78-L94)
2023-12-03 16:56:18 +08:00
Wenzhe Wang
2f90ca1b54
fix(tasks): find the right output to diff (#1596) 2023-12-03 15:29:13 +08:00
Wenzhe Wang
9f38072002
feat(tasks): add visualize_end_of_line (#1593) 2023-11-30 23:42:57 +08:00
Dunqing
39188d00e1
feat(prettier): support arrowParens option (#1592) 2023-11-30 17:41:34 +08:00
Boshen
e6681a8683
feat(prettier_conformance): ignore more stage3 features (#1584) 2023-11-29 19:51:41 +08:00
Boshen
e6f85a9a62
chore(prettier_conformance): remove stage3 export-default-from (#1580) 2023-11-29 19:03:26 +08:00
Dunqing
63b9d2cf81
feat(prettier/conformance): print options (#1579) 2023-11-29 18:37:38 +08:00
Dunqing
f19032e102
feat(prettier): support quoteProps option in PropertyKey (#1578) 2023-11-29 18:32:30 +08:00
Boshen
f7cb7838e5
chore(prettier_conformance): ignore range / cursor tests; ignore module-blocks 2023-11-28 23:30:32 +08:00
Boshen
6ea1bf2f18
Revert "chore(prettier_conformance): temporary disable code coverage"
This reverts commit e1266c69f9.
2023-11-28 17:34:59 +08:00
Boshen
32b19561a8
chore(prettier_conformance): ignore bind-expressions (#1535) 2023-11-24 20:26:27 +08:00
Dunqing
aa8656df0f
feat(task/prettier-confromance): escape template literal (#1493) 2023-11-22 15:30:59 +08:00
Dunqing
f06f0f2078
feat(task/prettier-confromance): ignore tests with non-standard syntax (#1492) 2023-11-22 11:01:26 +08:00
Boshen
064353c97e
feat(prettier): turn off preserve_parens and start working on need-parens (#1487) 2023-11-21 16:26:56 +00:00
Dunqing
51a78e2223
feat(prettier): support print inner comment in CallExpression (#1475) 2023-11-21 12:28:46 +08:00
Boshen
27dc1ed1b2
chore(prettier_conformance): ignore more non-es6 syntax (#1437) 2023-11-19 23:15:24 +08:00
Boshen
95f1b3beba
chore(prettier_conformance): ignore stage3 and multiparser tests (#1432) 2023-11-19 18:47:39 +08:00
Wenzhe Wang
3c567d6549
task(prettier): add diff view (#1428) 2023-11-19 17:13:25 +08:00
Boshen
d0a70d0626
feat(prettier): print class method and read tab width (#1413) 2023-11-18 22:42:53 +08:00
Boshen
24c2580435
chore(prettier_conformance): remove stage 3 features 2023-11-18 16:13:12 +08:00
Boshen
1dcd29a91b
feat(prettier): support endOfLine option (#1377) 2023-11-17 20:50:17 +08:00
Dunqing
badf6f51cf
feat(task/prettier-conformance): splitting test cases by file (#1373) 2023-11-17 20:14:00 +08:00
Dunqing
9b94226531
feat(prettier): support single_quote option (#1366) 2023-11-17 14:07:29 +08:00
Dunqing
a099d06866
fix(tasks/prettier-conformance): incorrect snapshot (#1352)
fix(tasks/prettier-conformance): incorrect snapshot

fix: lint
2023-11-16 20:43:32 +08:00
Dunqing
638bd1ce23
feat(tasks/prettier-conformance): allow specifying filter as specific files (#1343)
This is useful in directories with a large number of files, so that we only need to focus on the file we are debugging.
2023-11-16 15:56:47 +08:00
Dunqing
ba0e4d1a6a
feat(tasks/prettier-conformance): parse the specs and pass the correct options to prettier (#1327)
### This PR did the following things.

1. Parse specs
2. Collect `run_spec's` arguments
3. Pass the correct `PrettierOptions` to the `Prettier`
4. Printing snapshots correctly
2023-11-15 13:30:44 +08:00
Boshen
5f316626f6
feat(prettier): add the basics of comment printing (#1313) 2023-11-14 12:32:03 +00:00
Boshen
e1266c69f9
chore(prettier_conformance): temporary disable code coverage 2023-11-14 15:13:25 +08:00
Dunqing
f13e9aa69d
feat(task/prettier-conformance): incorrect compatibility percentage (#1292) 2023-11-14 12:22:27 +08:00
Cameron
561c73d88c
feat(printer) Basic Printer options (#1278) 2023-11-14 09:37:18 +08:00
Boshen
5c1637b786
feat(prettier): add some basic formatting functions (#1266) 2023-11-13 13:27:53 +00:00
Boshen
4a6f54cc1a
feat(prettier_conformance): add prettier test runner (#1262) 2023-11-13 20:14:35 +08:00