Commit graph

62 commits

Author SHA1 Message Date
Boshen
7bf970a4b6 refactor(linter)!: remove tree_shaking plugin (#7372)
This rule has been in `nursery` for a long time and I don't see it
coming out of `nursery` in the foreseeable future.

closes #7031
clsoes #7057
2024-11-20 11:46:29 +00:00
BitterGourd
94865a9390
feat(rulegen): support outdent and dedent tagged template expressions (#6866)
close #6645

---------

Co-authored-by: Don Isaac <donald.isaac@gmail.com>
2024-11-09 17:26:27 +08:00
Cam McHenry
04b4bae5c5
feat(rulegen): add module definitions for new rules (#6845)
Makes new rule creation a little bit easier by automatically adding the
rule definition to `rules.rs` with the proper alphabetical order.

Example:



https://github.com/user-attachments/assets/c9584986-7d08-4f91-bce2-501a8441e446
2024-10-24 15:47:07 +08:00
Dmitry Zakharov
25a49a5700
feat(rulegen): add import to rulegen (#6631)
Added for fast rule creation
2024-10-16 17:05:40 -04:00
Boshen
435a89c6e4 refactor(oxc): remove useless allocator.alloc(program) calls (#6571) 2024-10-15 02:21:20 +00:00
camchenry
02d5637dbc perf(ast-tools): use FxHashMap over std::collections::HashMap (#5997) 2024-09-23 18:28:54 +00:00
camchenry
b240b42eb9 fix(rulegen): handle raw string literals correctly (#5991)
Currently, we are not handling raw string literals correctly and just translating them as normal Rust string literals, which causes compile errors and also misses some cases. This PR updates it so that we detect usage of `String.raw` and translate it as a Rust raw string literal.

Before:

<img width="867" alt="Screenshot 2024-09-23 at 10 02 21 AM" src="https://github.com/user-attachments/assets/7c042537-d6c2-4141-a119-0ed846bce59d">

After:

<img width="832" alt="Screenshot 2024-09-23 at 10 01 27 AM" src="https://github.com/user-attachments/assets/759f6647-a675-42eb-b39d-c0e88f689536">
2024-09-23 16:24:19 +00:00
DonIsaac
d24985ed51 feat(linter): add oxc-security/api-keys (#5906)
## What This PR does
Adds a new `oxc-security/api-key` rule that scans for hard-coded API keys.

It is broken up into "secret rules", where each one is responsible for finding a different kind of key. It is architecturally identical to how lint rules themselves. This PR also includes the first of these rules, for AWS access key IDs.

Logic and rules are based on [keyhunter](https://github.com/Donisaac/keyhunter). I've licensed that repo under GNU GPLv3, but it's my code and I can do what I want with it 😈 (read: I'm fine with it being MIT for oxc).

This PR is a complete feature in its own right, but does not represent the end of this work. See https://github.com/oxc-project/backlog/issues/116 to track overall progress.
2024-09-22 22:39:56 +00:00
dalaoshu
d18c896a2c
perf(rust): use cow_utils instead (#5664)
Related to #5586 and #5662

---------

Co-authored-by: Boshen <boshenc@gmail.com>
2024-09-11 18:39:30 +08:00
Don Isaac
a266b45167
feat(rulegen): improve examples in documentation (#4815) 2024-08-10 18:48:59 -04:00
dalaoshu
6cf38cb776
chore(tasks): support init vitest lint rule (#4752)
Related to #4656
2024-08-08 16:27:50 +08:00
Jelle van der Waa
1f8968a521
feat(linter): Add eslint-plugin-promise rules: avoid-new, no-new-statics, params-names (#4293)
This introduces the `eslint-plugin-promise` plugin and implements three
relatively simple rules.

Split off from https://github.com/oxc-project/oxc/pull/4252
2024-07-17 09:21:20 +08:00
mysteryven
4414774d7d chore(tasks/rulegen): generate options for fix cases (#4076)
Our fixer support rule option, and we need to generate `options` for them.

328445b4ca/crates/oxc_linter/src/tester.rs (L238)

cc @eryue0220
2024-07-07 03:01:55 +00:00
overlookmotel
4f7ff7e3ad perf: do not pass &Atom to functions (#3818)
`Atom` is just a wrapper around `&str`, so better not to pass `&Atom` to functions, as that's a double-reference. Prefer `Atom` or `&str` instead to avoid indirection.
2024-06-22 04:48:00 +00:00
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
Wang Wenzhe
8212090a43
feat(tasks/rulegen): support generate fix cases (#3600) 2024-06-10 17:16:50 +08:00
Boshen
29163e1d85 feat(rulegen): preserve languageOptions as a comment (#3410)
closes #3366

so the implementer can decide on what to do with it
2024-05-25 15:44:24 +00:00
Boshen
4f76cb6f38 refactor(linter): merge deepscan rules into oxc rules (#3327) 2024-05-17 11:56:06 +00:00
Dunqing
64cd8a9d69 feat(rulegen): support filename option (#3240) 2024-05-11 14:53:48 +00: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
Yuji Sugiura
45649db86e
fix(tasks/rulegen): Follow #3037, settings handling update (#3077) 2024-04-23 13:28:52 +08:00
branchseer
f159f60084
Make ast types covariant over the allocator lifetime. (#2943)
## Why

Due to the usage of `&'alloc mut T` in `oxc_allocator::Box`, and
`bumpalo::collections::Vec` in `oxc_allocator::Vec`, ast types are
currently invariant over their allocator lifetime `'a`. This prevents
`ouroboros` from generating `borrow_*` on ast type fields, leading to
the unfriendly `with_*` api:
c250b288ef/crates/oxc_parser/examples/multi-thread.rs (L82-L84)

## How

- For `oxc_allocator::Vec`, switch to `allocator_api2::vec::Vec`, which
has a covariant relationship with the allocator lifetime.
- For `oxc_allocator::Box`, use `std::ptr::NonNull` which is
specifically designed to be covariant. I don't use
`allocator_api2::boxed::Box` because it holds the allocator for
dropping, so the size is bigger.

## Downside

Now that `oxc_allocator::Box` uses the unsafe `NonNull`. It has to be a
private field to be safe. This make it impossible to do `Box(....)`
pattern matching.
2024-04-12 18:12:18 +08:00
Wang Wenzhe
65f38dc0db
fix(tasks/rulegen): read quasi in TaggedTemplateExpression (#2903) 2024-04-07 10:41:14 +08:00
Wang Wenzhe
f8e8af2a66
feat(task): init eslint-plugin-tree-shaking rule (#2662) 2024-03-10 22:07:34 +08:00
Wang Wenzhe
588e94604c
chore(tasks): replace \" with single double quote (#2663) 2024-03-10 22:02:35 +08:00
Yuji Sugiura
f66fb886b3
fix(tasks/rulegen): Parse 'export default' test file for plugin-jsdoc (#2510) 2024-02-26 14:31:51 +08:00
kaykdm
2ceba79dcd
feat(tasks): add eslint-plugin-n rulegen (#2272)
related: https://github.com/oxc-project/oxc/issues/493

Support generate rules from
[eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n).
2024-02-02 18:50:58 +08:00
hjio
a95a16c2ae
feat(linter): complete custom components setting (#2234)
- add custom components setting
- let tasks/rulegen generate settings

---------

Co-authored-by: huangjunjie.coder <huangjunjie.coder@bytedance.com>
2024-02-01 23:28:11 +08:00
Don Isaac
97b1984d74
build(linter): add new-react-perf rulegen task (#2040)
Adds a new linter rule generation task, `just new-react-perf-rule`, for
incorporating rules from
[eslint-plugin-react-perf](https://github.com/cvazac/eslint-plugin-react-perf)
into oxc.

Since this library has its own testing utilities and only 4 rules, I
didn't bother writing code to port over test cases. If we deem this
requisite I'll add this to the rulegen task.
2024-01-16 12:48:19 +08:00
Boshen
b386177af2
refactor(linter): move away from tuples for test cases (#2011)
closes #1956
2024-01-13 16:23:16 +08:00
Yuji Sugiura
8a7efc2c3b
feat(tasks): Add eslint-plugin-jsdoc rulegen (#1965)
Hello. 👋🏻 

This PR makes `just new-jsdoc-rule xxxx` command works.

---

Initially, I planned to implement some basic rules later.
However, after struggling for half a day, I realized that it would be
challenging for a beginner like me to do it now. 😓

Once I have looked for something else I can do, and/or read more into
the codebase, I hope to be able to try again at some point.
2024-01-09 21:37:24 +08:00
Wenzhe Wang
f46ed71d8a
feat(tasks): add eslint-plugin-next rulegen (#1921)
closes: #1905

Support generate rules from
[eslint-plugin-next](https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-plugin).
2024-01-07 10:23:22 +08:00
Cameron
266667b892
chore: add deepscan to rulegen (#1748) 2023-12-20 12:29:28 +08:00
Wenzhe Wang
a96e4281ab
fix(rulegen): support creating cases in outdent (#1704)
fix: #1694
2023-12-17 13:45:23 +08:00
Cameron
959703631e
chore: add new-oxc-rule to rulegen (#1703) 2023-12-17 10:44:38 +08:00
Trevor Manz
8f5e9831df
feat(rulegen): Add jsx-a11y rulegen (#1119)
Adds the `just new-jsx-a11y-rule` for bootstrapping
`eslint-plugin-jsx-a11y` linting rules.

One tricky thing about the tests in that repo is that the aren't
provided as array expressions
(e.g., `[case0, case1, case2, ...]`) but rather separate arguments to
`[].concat()`
(e.g., `[].concat(case0, case1, case2, ...)`). There is probably a more
elegant way to match
these expressions, but this is what I came up with.

The other thing I introduced in this PR is prefer Rust's raw strings
(`r#`) when generating the
test cases. Sometimes running `just new-*` spit out unescaped back
quotes, which caused issues.
2023-10-31 13:18:48 +08:00
Dunqing
8816649e3c
feat(rulegen): escape from to \” (#1059) 2023-10-25 22:31:09 +08:00
Boshen
a75582046b
refactor(codegen): do not use (code, option) tuple if there are no configurations (#1038)
closes #1035
2023-10-23 16:40:56 +08:00
Cameron
72cf9ec725
chore(rulegen) Add rule gen for react rules (#1023) 2023-10-21 22:39:19 +08:00
Boshen
903854dac0
refactor(ast): fix the lifetime annotations around Vist and VisitMut (#973) 2023-10-10 17:05:48 +08:00
阿良仔
0fef2d317a
chore: proxy detection for all tasks (#801)
related PR: #740
2023-08-27 17:24:28 +08:00
Boshen
2f0ff28f47
Rust 1.72.0 (#784) 2023-08-24 23:02:19 +08:00
EYHN
1781318f44
fix(rulegen): handle join('\n') style test code (#763)
# 1. Support join('\n')

I'm trying to run `just new-rule no-unexpected-multiline`, It found
rulegen not support test code pieced together using `array.json("\n")`,
like

```js
{
  code: [
      "const x = aaaa<",
      "  test",
      ">/*",
      "test",
      "*/`foo`"
  ].join("\n")
}
```

I found this kind of code widely in the eslint codebase, so it will be
great if we can support this.


![](https://github.com/web-infra-dev/oxc/assets/13579374/195ed4ba-1efb-4c3f-9e49-0ebdb5527506)

# 2. remove extra `,`

And I found when meet unsupported code, rulegen will generate an extra
`,`, so I added a filter at


45cf5fc3da/tasks/rulegen/src/main.rs (L363)

# 3. handle escape string

The escape `/` and trailing `/` in the javascript code will break
rulegen. example: `"\"abc\\\n(123)\""`

I made the following changes:

```diff
- test_code.replace('\n', "\n\t\t\t")
+ test_code.replace('\n', "\n\t\t\t").replace('\\', "\\\\").replace('\"', "\\\"")
```
2023-08-19 23:19:51 +08:00
Kei Sakamoto
2fde2255f9
feat(linter): implement eslint-plugin-unicorn/no-instanceof-array (#752)
implement
[eslint-plugin-unicorn/no-instanceof-array](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-array.md).
Related issue: #684
2023-08-17 17:08:03 +08:00
Devin-Yeung
c0b06a5700
feat(rulegen): automatically detect proxy (#740)
detect `HTTP_PROXY/HTTPS_PROXY/ALL_PROXY` environments automatically,
since visiting https://raw.githubusercontent.com sometimes need proxy,
upstream PR
[algesten/ureq#649](https://github.com/algesten/ureq/pull/649)
2023-08-15 13:32:09 +08:00
Wenzhe Wang
0c645170a8
feat(linter): valid-describe-callback(eslint-plugin-jest) (#706) 2023-08-12 16:47:49 +08:00
Alexandr Metreniuc
f8358a148a
feat(linter): @typescript-eslint/no-namespace (#703) 2023-08-09 23:02:24 +08:00
Wenzhe Wang
de110828cc
fix(task): update taggedTemplateExpression template (#676)
For generate test cases like:

```js
{
    code: dedent`
      afterAll(async (done) => {
        await myAsyncTask();
        done();
      });
    `,
    errors: [{ messageId: 'useAwaitInsteadOfCallback', line: 1, column: 17 }],
},
```
2023-08-02 11:46:15 +08:00
Boshen
e25f6e2dd4
chore(rust): rust cargo fmt and fix clippy warnings 2023-07-04 15:41:30 +08:00