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

feat(linter): implement unicorn/no-useless-undefined #4079

Merged
merged 15 commits into from
Jul 11, 2024

Conversation

cblh
Copy link
Contributor

@cblh cblh commented Jul 7, 2024

Resolves #3870

Hey there, thought I'd give this a try as it's tagged "good first issue" :) Let me know if there's anything that needs to change

Another part of the code also needs modification:
https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/no-useless-undefined.js#L95

I tried to modify it. If there are any issues with these modifications, please let me know.

fn is_has_function_return_type(node: &AstNode, ctx: &LintContext<'_>) -> bool {
    let Some(parent_node) = ctx.nodes().parent_node(node.id()) else {
        return false;
    };
    match parent_node.kind() {
        AstKind::ArrowFunctionExpression(arrow_func_express) => {
            arrow_func_express.return_type.is_some()
        }
        AstKind::Function(func) => func.return_type.is_some(),
        _ => is_has_function_return_type(parent_node, ctx),
    }
}

Copy link

graphite-app bot commented Jul 7, 2024

Your org has enabled the Graphite merge queue for merging into main

Add the label “merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix.

You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link.

@github-actions github-actions bot added the A-linter Area - Linter label Jul 7, 2024
Copy link

codspeed-hq bot commented Jul 7, 2024

CodSpeed Performance Report

Merging #4079 will not alter performance

Comparing cblh:feature/20240704no-useless-undefined (cd39baf) with main (ddfa343)

Summary

✅ 31 untouched benchmarks

cblh added 2 commits July 8, 2024 09:56
…hod_call`, refine diagnostics, and handle more cases.

- Introduced `ast_util::is_method_call` to streamline method call checks.
- Enhanced diagnostics and suggested fixes for clearer code.
- Updated static set `FUNCTION_NAMES` to manage function names more efficiently.
- Extended handling for `return`, `yield`, arrow functions, and variable declarations using `undefined`.
…clarity and efficiency.

Simplified the deletion logic in `impl Rule for NoUselessUndefined` to handle `undefined` removal more efficiently.
@cblh cblh force-pushed the feature/20240704no-useless-undefined branch from 6f0c636 to c330e11 Compare July 8, 2024 02:16
cblh added 2 commits July 8, 2024 10:19
- Updated `no_useless_undefined` rule to handle cases where `undefined` is used in parameter initializers, assignment expressions, and return statements in functions with explicit return types.
- Added utility function `is_has_function_return_type` to check if a function has an explicit return type.
- Added multiple new test cases to cover scenarios including:
  - Object properties and class fields with `undefined`.
  - Functions and methods returning `undefined`.
  - Various valid uses of `undefined` that should not trigger the rule.
  - Improved handling of nested functions returning `undefined`.
- Improved existing test cases to ensure the rule correctly ignores cases where `undefined` is necessary.
- Added TODO comments for potential future enhancements.
@cblh cblh force-pushed the feature/20240704no-useless-undefined branch from 8829b2b to 584d20f Compare July 8, 2024 11:21
@cblh cblh requested a review from DonIsaac July 8, 2024 12:02
cblh added 3 commits July 9, 2024 09:04
Modified the `NoUselessUndefined` struct to set default values for `check_arguments` and `check_arrow_function_body` to `true`. This change ensures that these fields are initialized with `true` when using the `Default` trait.

- Removed `Default` derive macro from `NoUselessUndefined`.
- Implemented custom `Default` trait for `NoUselessUndefined` to set `check_arguments` and `check_arrow_function_body` to `true`.
…egory

- Changed the category of `NoUselessUndefined` rule from `pedantic` to `suspicious` for better classification.
- Fixed `is_undefined` function to handle cases where the argument is not an expression.
- Ensured `is_undefined` function correctly checks for undefined identifiers in arguments.
@cblh cblh requested a review from DonIsaac July 9, 2024 07:26
cblh added 3 commits July 10, 2024 19:40
…fined` rule

- Updated `no_useless_undefined.rs` to correctly traverse and handle parenthesized expressions containing `undefined`.
- Modified test cases to include scenarios with parenthesized `undefined`.
- Updated snapshot file to reflect changes in linting behavior and error messages.

Previously, the linter did not handle `undefined` wrapped in parentheses correctly, leading to missed linting opportunities. This update ensures that `undefined` within any number of nested parentheses is properly identified and linted.
@DonIsaac
Copy link
Collaborator

I'll run this fixer using oxc-ecosystem-ci, and if it looks good we should be able to merge.

Copy link
Collaborator

@DonIsaac DonIsaac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM: I ran the fixer and saw no parse errors on a second pass. I'd like another review from a second pair of eyes if possible, @mysteryven think you could give me a hand?

@Boshen Boshen requested a review from mysteryven July 11, 2024 02:47
@mysteryven
Copy link
Member

mysteryven commented Jul 11, 2024

test('extension is not outdated when there is no local and gallery', () => {
    const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, () => undefined, undefined, undefined, undefined, undefined);
    assert.strictEqual(extension.outdated, false);
});

https://github.com/microsoft/vscode/blob/c37f4a49e28831cec1aec1af0f626edaada1f7ce/src/vs/workbench/contrib/extensions/test/electron-sandbox/extension.test.ts#L29-L32

Our fixer need to run twice to fix this, tested on unicorn/no-useless-undefined, it needs once.

Other parts are also look good to me.

@cblh
Copy link
Contributor Author

cblh commented Jul 11, 2024

test('extension is not outdated when there is no local and gallery', () => {
    const extension = instantiationService.createInstance(Extension, () => ExtensionState.Installed, () => undefined, undefined, undefined, undefined, undefined);
    assert.strictEqual(extension.outdated, false);
});

https://github.com/microsoft/vscode/blob/c37f4a49e28831cec1aec1af0f626edaada1f7ce/src/vs/workbench/contrib/extensions/test/electron-sandbox/extension.test.ts#L29-L32

Our fixer need to run twice to fix this, tested on unicorn/no-useless-undefined, it needs once.

Other parts are also look good to me.

ok, I will fix it

@cblh
Copy link
Contributor Author

cblh commented Jul 11, 2024

@mysteryven @DonIsaac

Why our fixer need to run twice

            if i64::from(start) <= last_pos {
                return;
            }

https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/fixer.rs#L278

I found that span is an interval that is closed on the left and open on the right. It should not be <=, which will cause the continuous interval to be skipped. It should be <.

The test case needs to be modified to allow continuous interval modification, but I found that it will cause no_useless_escape test failure

https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/fixer.rs#L520

    const REMOVE_START: Fix = Fix::delete(Span::new(0, 4));
    const REPLACE_ID: Fix = Fix { span: Span::new(4, 10), content: Cow::Borrowed("foo") };
    fn apply_two_fix_when_the_start_the_same_as_the_previous_end() {
        let result = get_fix_result(vec![
            create_message(remove_start(), Some(REMOVE_START)),
            create_message(replace_id(), Some(REPLACE_ID)),
        ]);
        assert_eq!(result.fixed_code, TEST_CODE.replace("var answer", "foo"));
        assert!(result.fixed);
    }

@mysteryven
Copy link
Member

I found that span is an interval that is closed on the left and open on the right. It should not be <=, which will cause the continuous interval to be skipped. It should be <.

Since it not the issue about current rule, let's merge this PR first.

@mysteryven mysteryven merged commit bbe6137 into oxc-project:main Jul 11, 2024
27 checks passed
@github-actions github-actions bot mentioned this pull request Jul 17, 2024
Boshen added a commit that referenced this pull request Jul 17, 2024
## [0.6.1] - 2024-07-17

### Features

- 83c2c62 codegen: Add option for choosing quotes; remove slow
`choose_quot` method (#4219) (Boshen)
- 1f8968a linter: Add eslint-plugin-promise rules: avoid-new,
no-new-statics, params-names (#4293) (Jelle van der Waa)
- a4dc56c linter: Add fixer for
unicorn/no_useless_promise_resolve_reject (#4244) (Burlin)
- 6fb808f linter: Add typescript-eslint/no-confusing-non-null-assertion
(#4224) (Jaden Rodriguez)
- 126b66c linter: Support eslint-plugin-vitest/valid-describe-callback
(#4185) (cinchen)
- 05b9a73 linter: Support eslint-plugin-vitest/valid-expect (#4183)
(cinchen)
- 3e56b2b linter: Support eslint-plugin-vitest/no-test-prefixes (#4182)
(cinchen)
- 3016f03 linter: Let fixer functions return a `None` fix (#4210)
(DonIsaac)
- bbe6137 linter: Implement unicorn/no-useless-undefined (#4079)
(Burlin)
- 20cdb1f semantic: Align class scope with typescript (#4195) (Dunqing)

### Bug Fixes

- 9df60da linter: Correct find first non whitespace logic in
@typescript-eslint/consistent-type-imports (#4198) (mysteryven)
- 67240dc linter: Not ignore adjacent spans when fixing (#4217)
(mysteryven)
- dd07a54 linter: Global variables should always check the builtin
variables (#4209) (Jelle van der Waa)
- 351ecf2 semantic: Incorrect resolve references for `TSTypeQuery`
(#4310) (Dunqing)
- 1108f2a semantic: Resolve references to the incorrect symbol (#4280)
(Dunqing)

### Performance

- 0fdc88b linter: Optimize no-dupe-keys (#4292) (lucab)

### Refactor

- 2c7bb9f ast: Pass final `ScopeFlags` into `visit_function` (#4283)
(overlookmotel)
- aa22073 codegen: Improve print API (#4196) (Boshen)
- b5a8f3c linter: Use get_first_parameter_name from unicorn utils
(#4255) (Jelle van der Waa)
- 7089a3d linter: Split up fixer code into separate files (#4222)
(DonIsaac)
- ace4f1f semantic: Update the order of `visit_function` and `Visit`
fields in the builder to be consistent (#4248) (Dunqing)
- 7f1addd semantic: Correct scope in CatchClause (#4192) (Dunqing)

Co-authored-by: Boshen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linter Area - Linter
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(linter): eslint-plugin-unicorn/no-useless-undefined
5 participants