Commit graph

116 commits

Author SHA1 Message Date
overlookmotel
bfd0b0da17 ci(benchmark): make lexer benchmark more realistic (#8573)
The lexer benchmarks had a problem. The lexer alone cannot make sense of regexp literals, template literals, or JSX text elements - it needs the parser "driving" it.

So lexer was producing plenty of errors on some benchmarks. This is unrealistic - when driven by the parser, the lexer produces no errors. Generating diagnostics is relatively expensive, so this was skewing the benchmarks somewhat.

Solve this by cleaning up the input source text to replace these syntaxes with string literals prior to running the benchmarks.

Unfortunately lexer benchmarks don't exercise the code paths for these syntaxes, but there isn't much we can do about that. We can judge by the parser benchmarks, which are the more important ones anyway.
2025-01-18 01:47:07 +00:00
Boshen
dba054f529
feat(tasks/benchmark): add mangler (#8470)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-01-14 10:08:13 +08:00
camc314
3c534aeb5a refactor(linter): refactor LintBuilder to prep for nested configs (#8034)
More simplification/preparations for nested configurations:

1. renames `LinterBuilder` to `ConfigStoreBuilder`
2. moves the `options` logic out of `LintBuilder`
3. make `ConfigStoreBuilder::build()` return a result (currently always returns OK, but it will return errors when nested config is implemented

The next steps to implement nested config which i hope to do in the next week are:
1. refactor the `from_oxlintrc` to accept a file path
2. introduce a new method on `ConfigStoreBuilder` (name TBC) that walks all child directories, collecting `.oxlintrc` files. these will be put into `ConfigStore` as a hash map of path > config.
2025-01-05 04:08:26 +00:00
overlookmotel
6f8bb1cebf
ci(benchmarks): simplify benchmarks (#7939)
Pure refactor. Use `bench_function` instead of `bench_with_input` and
just borrow data from outside closure. This shortens the code and (I
think) makes it easier to read.
2024-12-16 22:01:01 +08:00
overlookmotel
3c73e86f8c ci(codegen): simplify codegen benchmark (#7938)
Follow-on after #7934. Pure refactor. Make codegen benchmark simpler.
2024-12-16 13:51:40 +00:00
camc314
9b3a2beaa3 refactor(benchmark): transform code before codegen (#7934)
@overlookmotel suggested this [here](https://github.com/oxc-project/oxc/pull/7926#discussion_r1886023496).
2024-12-16 13:08:11 +00:00
Boshen
348d4f451a feat(sourcemap): move oxc_sourcemap to github.com/oxc-project/oxc-sourcemap (#7604)
It's mostly stable so we can v1.0.0 it.

And we will create cyclic dependency with StringWizard soon.
2024-12-03 11:59:43 +00:00
Boshen
0f3f67a05a refactor(linter): add capability of adding semantic data to module record (#7561)
closes #5814
closes #5816
2024-12-01 08:14:43 +00:00
Boshen
c2ced15dfd feat(parser,linter)!: use a different ModuleRecord for linter (#7554)
The parser returns a simple `ModuleRecord` that is allocated in the arena for performance reasons.

The linter uses a more complicated, `Send` + `Sync` `ModuleRecord` that will hold more cross-module information.

The next step is to return more esm information from the parser to eliminated the need of the `oxc_module_lexer` crate.
2024-11-30 16:02:01 +00:00
Boshen
0be5233c84 refactor(semantic)!: remove ModuleRecord from Semantic (#7548)
`ModuleRecord` will eventually be moved to be linter specific thing for cross module data sharing, which means we can add more data to it.
2024-11-29 16:30:54 +00:00
Boshen
8a788b8f4b feat(parser)!: Build ModuleRecord directly in parser (#7546)
This has the benefit of:

* expose dynamic import / import meta info from parser
* 1 less ast shallow in semantic builder
* no ast walk in oxc's module lexer
* some more benefits coming soon
2024-11-29 14:50:42 +00:00
camc314
3dcac1ae0b feat(linter): react/exhaustive-deps (#7151)
Firstly, a massive thanks to @alisnic for starting this (incredibly complicated) lint rule in https://github.com/oxc-project/oxc/pull/2637 !

still a draft. current state:

3x false positives (all todo with refs)

3x false negatives (TS will catch these
13x false negatvies todo with refs
1x false negative TODO

closes  #2637
relates to #2174
2024-11-12 11:42:47 +00:00
Boshen
846711cf41 feat(transformer)!: change API to take a &TransformOptions instead of TransformOptions (#7213)
closes #7185

`TransformOption`s has an initialization cost, it should be initialized once and shared across files.
2024-11-09 06:01:13 +00:00
Dunqing
70e2582726 ci(transformer): enable unfinished plugins in benchmark (#7040)
Even the plugins are unfinished, we still want to enable all of them to track the performance changes during the development.
2024-11-02 15:17:21 +00:00
Boshen
fcaba4a92a feat(transformer): add TransformerOptions::env with EnvOptions (#7037) 2024-10-31 12:30:32 +00:00
Boshen
8d9a2da9f3 ci(benchmark): add small test file to linter benchmark (#6572)
closes #6540
2024-10-15 02:37:22 +00:00
Boshen
435a89c6e4 refactor(oxc): remove useless allocator.alloc(program) calls (#6571) 2024-10-15 02:21:20 +00:00
Dunqing
c67acfaae7 chore(transformer): turns off async_to_generator plugin in enable_all (#6554)
The plugin is not ready to test
2024-10-15 02:08:28 +00:00
Boshen
91c87dd380 refactor(codegen)!: remove Codegen::enableSourceMap API (#6452) 2024-10-12 04:56:43 +00:00
Boshen
cb8f4210c3 refactor(prettier)!: remove source_text argument from constructor (#6448) 2024-10-11 06:27:33 +00:00
Boshen
520096030a refactor(oxc)!: remove passing Trivias around (#6446)
part of #6426
2024-10-11 06:09:25 +00:00
Boshen
2b7be08af4 feat(ast)! add source_text to Program (#6444) 2024-10-11 04:13:41 +00:00
DonIsaac
80266d85c9 feat(linter)!: support plugins in oxlint config files (#6088)
> Closes #5046
This PR migrates the linter crate and oxlint app to use the new `LinterBuilder` API. This PR has the following effects:

1. `plugins` in oxlint config files are now supported
2. irons out weirdness when using CLI args and config files together. CLI args are now always applied on top of config file settings, overriding them.

# Breaking Changes
Before, config files would override rules set in CLI arguments. For example, running this command:
```sh
oxlint -A correctness -c oxlintrc.json
```
With this config file
```jsonc
// oxlintrc.json
{
  "rules": {
    "no-const-assign": "error"
  }
}
```
Would result in a single rule, `no-const-assign` being turned on at an error level with all other rules disabled (i.e. set to "allow").

Now, **CLI arguments will override config files**. That same command with the same config file will result with **all rules being disabled**.

## Details

For a more in-depth explanation, assume we are running the below command using the `oxlintrc.json` file above:
```sh
oxlint -A all -W correctness -A all -W suspicious -c oxlintrc.json
```

### Before
> Note: GitHub doesn't seem to like deeply nested lists. Apologies for the formatting.

Here was the config resolution process _before_ this PR:
<details><summary>Before Steps</summary>

1. Start with a default set of filters (["correctness", "warn"]) if no filters were passed to the CLI. Since some were, the filter list starts out empty.
2. Apply each filter taken from the CLI from left to right. When a filter allows a rule or category, it clears the configured set of rules. So applying those filters looks like this
  a. start with an empty list `[]`
  b. `("all", "allow")` -> `[]`
  c. `("correctness", "warn")` -> `[ <correctness rules> ]`
  d. `("all", "allow")` -> `[]`
  e. `("suspicious", "warn")` -> `[ <suspicious rules> ]`. This is the final rule set for this step
3. Apply overrides from `oxlintrc.json`. This is where things get a little funky, as mentioned in point 2 of what this PR does. At this point, all rules in the rules list are only from the CLI.
  a. If a rule is only set in the CLI and is not present in the config file, there's no effect
  b. If a rule is in the config file but not the CLI, it gets inserted into the list.
  c. If a rule is already in the list and in the config file
    i. If the rule is only present once (e.g. `"no-loss-of-precision": "error"`), unconditionally override whatever was in the CLI with what was set in the config file
    ii. If the rule is present twice (e.g. `"no-loss-of-precision": "off", "@typescript-eslint/no-loss-of-precision": "error"`),
      a. if all rules in the config file are set to `allow`, then turn the rule off
      b. If one of them is `warn` or `deny`, then update the currently-set rule's config object, but _leave its severity alone_.

  So, for our example, the final rule set would be `[<all suspicious rules: "warn">, no-const-assign: "error"]`

</details>

### After
Rule filters were completely re-worked in a previous PR. Now, lint filters aren't kept on hand-only the rule list is.

<details><summary>After Steps</summary>

1. Start with the default rule set, which is all correctness rules for all enabled plugins (`[<all correctness rules: "warn">]`)
2. Apply configuration from `oxlintrc.json` _first_.
  a. If the rule is warn/deny exists in the list already, update its severity and config object. If it's not in the list, add it.
  b. If the rule is set to allow, remove it from the list.

  The list is now `[<all correctness rules except no-const-assign: "warn">, no-const-assign: "error"]`.

3. Apply each filter taken from the CLI from left to right. This works the same way as before. So, after they're applied, the list is now `[<suspicous rules: "warn">]`

</details>
2024-10-10 19:21:50 +00:00
Boshen
020bb80b65 refactor(codegen)!: change to CodegenReturn::code and CodegenReturn::map (#6310) 2024-10-06 05:05:47 +00:00
overlookmotel
4f6bc79734 refactor(transformer)!: remove source_type param from Transformer::new (#6251)
Closes #6248.
2024-10-03 00:21:01 +00:00
overlookmotel
911e4e58ab ci(minifier): minifier benchmark measure only the minifier itself (#6222)
Minifier benchmark currently includes the time to run parser and semantic as well as the minifier itself. Similar to transformer benchmark, only measure the minifier itself in the benchmark.

This will give us a clearer picture of performance changes, and should also reduce variance in the benchmarks.
2024-10-01 17:43:39 +00:00
Boshen
84a5816d03
feat(isolated_declarations): add stripInternal (#5878)
closes #3906
closes #5687
closes #3958

---------

Co-authored-by: Dunqing <dengqing0821@gmail.com>
2024-09-19 23:14:47 +08:00
Boshen
db4f16a98f refactor(semantic): call with_trivias before build_with_jsdoc (#5875) 2024-09-19 04:12:57 +00:00
overlookmotel
2e93548816 ci(transformer): enable arrow function transform in transformer benchmark (#5851) 2024-09-18 11:08:27 +00:00
overlookmotel
3230ae5842 feat(semantic): add SemanticBuilder::with_excess_capacity (#5762)
Add `SemanticBuilder::with_excess_capacity` method to request that `SemanticBuilder` over-allocate space in `Semantic`'s `Vec`s.

Use this method to reserve 200% extra capacity for transformer to create more scopes, symbols and references.

200% is an unscientific guess of how much extra capacity is required. Obviously it depends on what transforms are enabled and content of the source code.
2024-09-14 15:02:16 +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
DonIsaac
9e9435f03b refactor(linter): add LintFilter (#5685)
Re-creation of #5329
2024-09-11 03:19:04 +00:00
DonIsaac
5ae9b48509 refactor(linter): start internal/external split of OxlintOptions (#5659)
re-creation of #5141
2024-09-10 03:19:04 +00:00
Boshen
b06052501a refactor(semantic)!: remove source_type argument from SemanticBuilder::new (#5553)
Realized we can get the source type from the AST.

The next PR will introduce `unambiguous` to `SourceType` and directly set `Program::source_type` to either `script` or `module`.
2024-09-06 16:40:10 +00:00
Boshen
32d4bbb519
feat(transformer): add TransformOptions::enable_all method (#5495)
Make it **really** explicit about which transformer options are being
turned on. I also need this in monitor-oxc.
2024-09-06 12:04:06 +08:00
Boshen
c3cfbfb480 chore: clippy::allow_attributes (#5521)
https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#expectlint

https://rust-lang.github.io/rust-clippy/master/index.html#/allow_attributes
2024-09-06 03:07:02 +00:00
Boshen
9c937e06e8 fix(benchmark): do not measure initialization of transformer options (#5442)
relates #5267
2024-09-04 14:52:21 +00:00
dalaoshu
4473779074
feat(linter/node): implement no-exports-assign (#5370) 2024-09-03 07:53:14 -04:00
Dunqing
783a31beb6 ci(benchmark/transformer): enable all > es6 plugins (#5324)
There is a bug in the react refresh plugin, I will fix it in follow-up PR and enable the plugin in the benchmark
2024-08-30 09:30:17 +00:00
Boshen
3ae94b8801
refactor(semantic): change build_module_record to accept &Path instead of PathBuf 2024-08-30 12:24:49 +08:00
DonIsaac
270fc53401 chore(bench): include fixers in linter benchmarks (#5307)
Fixing code is an important part of linter logic. We want to make sure fixers for each rule, and the code responsible for applying those fixes, are included in benchmarks.

As it currently stands, fixer closures are applied regardless of whether the user wants fixers to be applied. However, this is an implementation detail and is subject to change. I  also want to bench the performance of `Fixer`.
2024-08-28 23:19:43 +00:00
overlookmotel
b479afdafc ci: transformer benchmark measure transformer itself only (#5193)
Transformer benchmark measure only the transformer itself. Parse, generate `Semantic`, and drop `Semantic` outside of the measured section.

This should:

1. Give us greater visibility of how changes to transformer affect its performance.
2. Reduce variance in transformer benchmarks, since they will no longer include the variance introduced by `SemanticBuilder`.

Not ready to merge yet. We should first add an "end to end" benchmark testing the entire compilation process (parse - semantic - transform - minify - codegen).

This PR depends on https://github.com/Boshen/criterion2.rs/pull/49. This PR currently makes Oxc's dependency on `criterion2` a git dependency on that PR's branch. That can be changed once the upstream PR is merged.
2024-08-27 01:53:27 +00:00
overlookmotel
7c4f009521
refactor(ci): include drop in semantic benchmark (#5245)
Include dropping `Semantic` in semantic benchmark measure.

If you create a `Semantic`, you have to drop it, so the time it takes to
drop is part of the cost of using this API, and we should be working to
reduce it. Therefore I think it should be included in the benchmark.

It'll be interesting to see what effect a PR like #5232 which removes a
bunch of `Vec`s from `Semantic` has on the drop time.
2024-08-27 09:30:52 +08:00
Boshen
293668bebd
chore(tasks): parse regular expression in parser benchmark (#5212) 2024-08-26 13:11:09 +08:00
Boshen
4b49cf8ce4 feat(transformer): always pass in symbols and scopes (#5087)
We no longer need to build semantic data inside the transformer.

The caller should be responsible for handling semantic data and its
errors.

The best way to achieve this in via `CompilerInterface`.

closes #3565
2024-08-22 16:06:31 +00:00
overlookmotel
e42ac3a2a0
feat(sourcemap): add ConcatSourceMapBuilder::from_sourcemaps (#4639)
Introduce new method `ConcatSourceMapBuilder::from_sourcemaps`.

Where all the sourcemaps being concatenated exist at time that you
create `ConcatSourceMapBuilder`, it's faster to use `from_sourcemaps`,
because it pre-allocates enough space for the data it will hold and so
avoids memory copying.

Before:

```rs
let mut builder = ConcatSourceMapBuilder::default();
builder.add_sourcemap(&sourcemap1, 0);
builder.add_sourcemap(&sourcemap2, 100);
builder.add_sourcemap(&sourcemap3, 100);
let combined = builder.into_sourcemap();
```

After:

```rs
let builder = ConcatSourceMapBuilder::from_sourcemaps(&[
    (&sourcemap1, 0),
    (&sourcemap2, 100),
    (&sourcemap3, 200),
]);
let combined = builder.into_sourcemap();
```
2024-08-06 14:08:17 +08:00
Boshen
0f5e982d19 perf(minifier): only visit arrow expression after dropping console.log (#4677) 2024-08-06 04:20:41 +00:00
Boshen
e78cba6464 refactor(minifier): ast passes infrastructure (#4625)
After studying google closure compiler, I'm leaning towards a multi-ast-pass infrastructure for the minifier.

This is one of the few places where we are going to trade maintainability over performance, given the goal of the minifier is compression size not performance.

All of the terminologies and separation of concerns are aligned with google closure compiler.

Infrastructure of `terser` and `esbuild` are not suitable for us to study nor pursuit. Their code are so tightly coupled - I failed to comprehend any of them every time I try to walk through a piece of optmization. Google closure compiler despite being written in Java, it's actually the most readable minifier out there.

To improve performance between ast passes, I envision a change detection system over a portion of the code.

The benchmark will demonstrate the performance regression of running 5 ast passes instead of 2.

To complete this PR, I need to figure out "fix-point" and order of these ast passes.
2024-08-04 11:58:39 +00:00
overlookmotel
27fd0628ef
refactor(sourcemap)!: avoid passing Results (#4541)
Refactor building sourcemap JSON to avoid passing `Result`s. `Serialize::serialize` is infallible here as writing to a `Vec<u8>` is infallible.
2024-07-30 04:23:49 +00:00
overlookmotel
affd7685de
fix(benchmark): sourcemap benchmark properly test ConcatSourceMapBuilder (#4528)
Make 2 changes to sourcemap benchmark:

1. Move counting line breaks in output text to outside of the measured loop. This operation is reasonably expensive, and isn't part of what we're trying to measure.

2. It looks like benchmark is trying to measure concatenating 2 source maps, but `for i in 0..1` was actually only concatenating 1.
2024-07-29 11:14:40 +00:00