Commit graph

3339 commits

Author SHA1 Message Date
overlookmotel
514228ad42
deps(allocator): disable serde dep by default (#3120)
`oxc_allocator` currently depends on `serde`, although it's generally
not required.

This PR puts the dependency behind a feature `serialize`.

NB: `serde` is needed for the crate's tests, but this can be enabled by
adding it to `dev-dependencies` and putting the impls behind
`#[cfg(any(feature = "serialize", test))]`.
2024-04-28 22:17:32 +08:00
Wang Wenzhe
8f31ad618e
chore(linter/tree-shaking): uncomment function and identifier test cases (#3119) 2024-04-28 22:05:33 +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
264404431c
chore: fix renovate error "Use matchDepNames instead of matchPackageNames" 2024-04-28 14:49:23 +08:00
Vasilii A
dcda1f6128
fix(cli): update --format documentation (#3118)
Refs: #3039 #3044
2024-04-28 11:56:10 +08:00
Dunqing
c3d8a85eb5
feat(semantic): report that enum member must have initializer (#3113)
See
https://www.typescriptlang.org/play/?target=99#code/KYOwrgtgBAglDeAoKKoEMoF4oFk0BcALAOgGcBLEACgEYBKAGmVQCMmBfRRUSKAIQTMUGbACIaAJgDMopqihtEnRABtg+KADMwIAMZYoVOlgB8USVIDc3cNADCg+SK07dRuaw6IgA
2024-04-27 22:08:02 +08:00
Yuji Sugiura
1f12aee149
refactor(linter/jsdoc): Misc improvements (#3109)
- [x] Always use resolved_tag_name
- [x] Nits syntax, naming fixes
- [x] Split up utils
2024-04-27 21:47:33 +08:00
overlookmotel
17131d23b8
refactor(prettier): reduce recursion (#3112)
Use a loop rather than recursive function call.
2024-04-27 10:54:14 +08:00
谭光志
cd600fade4
feat(linter): add more "ban-ts-comment" test cases. (#3107)
https://github.com/oxc-project/oxc/issues/2934

| name           | passed | failed |
| -------------- | ------ | ------ |
| ts-expect-error| 14     | 20     |
| ts-ignore      | 15     | 20     |
| ts-nocheck     | 11     | 9      |
| ts-check       | 11     | 8      |
| total          | 51     | 57
2024-04-26 22:54:05 +08:00
Boshen
5d0f165f51
ci: "Coverage and check diff" -> "Check Conformance" 2024-04-26 21:31:44 +08:00
cinchen
bef8a71b9d
feat(linter): eslint-plugin-jest/require-hook (#3110)
part of https://github.com/oxc-project/oxc/issues/492

Rule Detail: [link](https://github.com/jest-community/eslint-plugin-jest/blob/main/src/rules/require-hook.ts)
2024-04-26 21:26:28 +08:00
Todor Andonov
388ee5135a
feat(linter): typescript-eslint/prefer-enum-initializers (#3097) 2024-04-26 21:09:05 +08:00
Ali Rezvani
51de41cc7a
fix(index): add example_generated to create the docs. (#3106)
This dummy feature is for generating the documentations made by macros, I've missed it in my initial fork.
2024-04-26 20:37:38 +08:00
Ali Rezvani
df2beb2d75
chore: make oxc_index dependency on serde optional. (#3103)
nothing fancy here, just a simple change.
2024-04-26 20:34:59 +08:00
Yuji Sugiura
5866086d17
feat(linter/jsdoc): Implement no-defaults rule (#3098)
Part of #1170

>
https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-defaults.md#repos-sticky-header
2024-04-26 00:03:21 +08:00
overlookmotel
0185eb2edc
refactor(ast): remove duplicate TSNamedTupleMember representation (#3101)
Removes duplicate representation of a `TSTupleElement` which is a
`TSNamedTupleMember`.

Closes #3100.
2024-04-25 19:16:24 +08:00
Boshen
78875b79fe
feat(transformer): implement typescript namespace (#3025)
Co-authored-by: Dunqing <dengqing0821@gmail.com>
2024-04-25 10:26:11 +00:00
Ali Rezvani
ac72d08592
chore: cleanup the dependencies on static_assertions and oxc_index. (#3095)
We used to export `static_assertions` as part of the `oxc_index`. It
would've made sense back when it was only a vessel for exporting other
crates - although even then it wouldn't make much sense other than being
convenient - Now with it turning into a port of `index_vec` and
potentially getting bigger as the result of specific needs of the
project; It makes much more sense to stop exporting it from `oxc_index`
and use the crate directly in places that used to use what `oxc_index`
were exporting.


PS: we may want to follow up this with an `oxc_asset` crate containing
our own set of assertion tools which would also export
`static_assertions`.
2024-04-25 16:56:23 +08:00
Ali Rezvani
8618f6b32a
chore(index): fork index_vec crate. (#3092)
related to #3086
2024-04-25 06:09:53 +00:00
Dunqing
2dd96df847
feat(semantic): report namespace related errors (#3093)
See
https://www.typescriptlang.org/play/?target=99#code/GYVwdgxgLglg9mABAIzgEwJ4AoCUiDeAUIomAIYC2ApgM4AOZEViAIgQL6HtA
2024-04-25 14:01:58 +08:00
Yuji Sugiura
fa3d9d23a0
feat(linter/jsdoc): Implement implements-on-classes rule (#3081)
Part of #1170

>
https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/implements-on-classes.md

`contexts` option is not supported for now.
2024-04-25 10:14:28 +08:00
Ali Rezvani
08b2612245
improvement(linter/unicorn): use root_node method in the no_process_exit rule. (#3091) 2024-04-25 09:13:38 +08:00
Ali Rezvani
a43054bec5
improvement(linter/unicorn): use root_node method in the no_empty_file rule. (#3090) 2024-04-25 09:07:40 +08:00
Ali Rezvani
71da1a1d72
improvement(linter/tree_shaking): use root_node in the no_side_effects_in_initialization rule. (#3089) 2024-04-25 09:01:41 +08:00
Ali Rezvani
69e464b19a
improvement(linter/ts): use root_node method in the triple_slash_reference rule. (#3088) 2024-04-25 08:55:29 +08:00
Ali Rezvani
c49f6922c2
improvement(linter/nextjs): use root_node method in no_async_client_component rule. (#3087) 2024-04-25 08:49:30 +08:00
Ali Rezvani
dcb2528861
fix(semantic): revert test code pushed to the main by accident. (#3085)
I'm terribly sorry, I've reverted the wrong commit in #3084.
2024-04-25 08:43:49 +08:00
Ali Rezvani
8d17ab36c3
fix(semantic): allow root_node to be empty for empty trees. (#3084)
related to #3082, #3030 and #3069
2024-04-25 01:10:59 +08:00
Wang Wenzhe
8de7399b08
chore(tasks): observe nursery rule in benchmark (#3082) 2024-04-24 23:03:52 +08:00
Wang Wenzhe
88ded0cef5
feat(linter/tree-shaking): support ForStatement (#3078) 2024-04-24 00:32:47 +08:00
Yuji Sugiura
d109767330
feat(linter/jsdoc): Implement check-tag-names rule (#3029)
Part of #1170 

-
https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-tag-names.md#user-content-check-tag-names-options-definedtags

(This time, I'm less confident that I have implemented correctly. 😓 )
2024-04-24 00:32:14 +08:00
Yuji Sugiura
45649db86e
fix(tasks/rulegen): Follow #3037, settings handling update (#3077) 2024-04-23 13:28:52 +08:00
Ali Rezvani
ac1a40fb43
feat(ast): add callee_name method to the CallExpression. (#3076)
Adds a simple way to get the name of a given `CallExpression`.
2024-04-23 09:47:23 +08:00
overlookmotel
ab445d6acd
chore(deps): update benchmark pnpm dependencies (#3075)
Update pnpm dependencies for benchmarks. Alter usage of `tar` package
for changes to exports in v7.

Fixes
https://github.com/oxc-project/oxc/pull/3056#issuecomment-2068362398.
2024-04-23 08:21:17 +08:00
Wang Wenzhe
c3ec710b3d
feat(linter/tree-shaking): support ExportNamedDeclaration (#3072) 2024-04-23 02:19:34 +08:00
overlookmotel
942b2ba084
refactor(ast): add array element Elision type (#3074)
Pure refactor. This change does nothing except makes it more consistent
with other types which are also just a wrapper around `Span` e.g.
`NullLiteral` and `TSThisType`.
2024-04-23 02:05:11 +08:00
overlookmotel
81f90fd8b0
fix(ast): do not include trailing_comma in JSON AST (#3073)
Don't include `trailing_comma` fields in JSON AST, for compat with
ESTree (#2854).
2024-04-23 02:04:32 +08:00
谭光志
be9cdfcd83
feat(linter): eslint/no-await-in-loop (#3070)
[no-await-in-loop](https://eslint.org/docs/latest/rules/no-await-in-loop)
2024-04-22 21:43:32 +08:00
Boshen
99d46f9e48
Release oxlint and vscode extension v0.3.1 2024-04-22 16:00:17 +08:00
Boshen
a5a73517f8
fix(linter): fix unwanted plugin rules being enabled 2024-04-22 16:00:17 +08:00
Boshen
b29aabd6f1
Release oxlint and vscode extension v0.3.0 2024-04-22 12:57:38 +08:00
Boshen
fc88208e60
Release napi oxc-parser@v0.9.0 2024-04-22 12:56:40 +08:00
Boshen
559bca86c5
Release crates v0.12.5 2024-04-22 12:52:17 +08:00
Boshen
b88dfd7cee
fix(linter): support -D all -D nursery 2024-04-22 12:43:12 +08:00
Boshen
8d17bb4052
feat(linter): --deny all should not enable nursery rules
closes #3067
2024-04-22 12:34:32 +08:00
Todor Andonov
c2ad8f82de
feat(linter): implement fixer for typescript-eslint/consistent-type-definitions (#3045)
This is a continuation of https://github.com/oxc-project/oxc/pull/2885.

closes https://github.com/oxc-project/oxc/issues/2933

Note for reviewers: please take a look at how the new test cases are
defined. I just copy-pasted them from
[here](c33f497ad8/packages/eslint-plugin/tests/rules/consistent-type-definitions.test.ts (L67))
and I'm not sure if this is how it should be done. I also added a few
more test cases.
2024-04-22 12:13:33 +08:00
Boshen
5241e1e127
refactor(cli): improve --help documentation 2024-04-22 11:14:51 +08:00
Boshen
023c1acfd0
chore(linter): remove unused "timing" variable 2024-04-22 11:08:50 +08:00
Boshen
ae72be1964
feat(linter): remove all ESLint Stylistic rules
They are out of scopes of this project.

closes #3066
closes #3040
2024-04-22 11:05:13 +08:00
Boshen
58d6438efb
feat(linter): change no-empty-static-block to correctness 2024-04-22 11:05:13 +08:00