Skip to content

fix: fix rule behavior differences and refactor control flow analysis#495

Merged
fansenze merged 1 commit intomainfrom
fix/rule-behavior-fixes-20260306
Mar 9, 2026
Merged

fix: fix rule behavior differences and refactor control flow analysis#495
fansenze merged 1 commit intomainfrom
fix/rule-behavior-fixes-20260306

Conversation

@fansenze
Copy link
Copy Markdown
Contributor

@fansenze fansenze commented Mar 6, 2026

Summary

Fix rule behavior differences between rslint and ESLint/typescript-eslint, and refactor control flow analysis into a shared utility.

Rule Fixes

1. no-invalid-void-type — callable/construct signatures

void as return type in callable and construct signatures was incorrectly flagged. Added CallSignature and ConstructSignature to the valid context whitelist, matching typescript-eslint behavior.

2. no-empty-function — functions with comments

Functions containing only comments (e.g. function foo() { /* TODO */ }) were incorrectly reported as empty. Added comment detection to check for // and /* in function bodies.

3. getter-return — throw statements, control flow, and arrow expression bodies

  • Throw statements were not recognized as valid exit paths in getters.
  • finally { return; } overriding try block returns was not detected.
  • Arrow functions with expression bodies in property descriptors (e.g. get: () => value) were incorrectly flagged as missing a return. ESLint only checks getters with BlockStatement bodies.
  • Fixed rule.CreateRule() incorrectly prepending @typescript-eslint/ prefix to core ESLint rule names.

4. array-callback-return — mixed return-with-value and empty-return

When allowImplicit is false (default), callbacks mixing return value; and return; on different branches (e.g. if (a) return 1; else return;) were not flagged. Fixed allPathsReturn logic to require all return statements to have values when allowImplicit is disabled.

5. no-unnecessary-boolean-literal-compare — options parsing and type checking

  • Options from JSON config/test framework were silently ignored (type assertion failed for []interface{}/map[string]interface{}). Added JSON marshal/unmarshal fallback.
  • isNullableBoolean did not verify that a union type contains only boolean and nullable members, causing false positives for types like boolean | string | null. Fixed to reject unions with non-boolean/non-nullable members.

Control Flow Refactor

Replaced ~500 lines of hand-written control flow analysis across getter-return, array-callback-return, and constructor-super with a shared utility (internal/utils/flow.go) that leverages the binder's NodeFlagsHasImplicitReturn flag and ForEachReturnStatement.

  • AnalyzeFunctionReturns(node) — returns EndReachable, HasReturnWithValue, HasEmptyReturn
  • IsFunctionEndReachable(node) — checks if function end is reachable

This also fixes array-callback-return incorrectly treating try { return x; } catch(e) {} as valid (catch falls through without returning).

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves three distinct behavioral inconsistencies between rslint and ESLint/typescript-eslint rules. The changes improve the accuracy and reliability of linting by refining how void types are handled in specific TypeScript signatures, ensuring functions with comments are correctly identified as non-empty, and significantly upgrading the control flow analysis for getter-return rules to account for various complex exit paths, including error throws. These adjustments aim to bring rslint's rule enforcement closer to established ESLint standards, enhancing its consistency and correctness.

Highlights

  • no-invalid-void-type rule: Corrected the rule to allow void as a return type in callable and construct signatures, aligning with typescript-eslint behavior.
  • no-empty-function rule: Updated the rule to no longer flag functions containing only comments as empty, matching typescript-eslint's approach.
  • getter-return rule: Enhanced control flow analysis to properly recognize throw statements, if/else, switch/case/default, and try/catch/finally blocks as valid exit paths in getters. Additionally, a fix was implemented for incorrect rule naming that caused the rule to be invisible via the IPC API.
Changelog
  • internal/plugins/typescript/rules/no_empty_function/no_empty_function.go
    • Imported the strings package.
    • Introduced a new helper function isBlockBodyEmpty to detect comments within function bodies.
    • Modified the isBodyEmpty function to utilize isBlockBodyEmpty for various function types.
  • internal/plugins/typescript/rules/no_empty_function/no_empty_function_test.go
    • Added new valid test cases for functions that contain only comments.
  • internal/plugins/typescript/rules/no_invalid_void_type/no_invalid_void_type.go
    • Included ast.KindCallSignature and ast.KindConstructSignature in the whitelist for valid void return type contexts.
  • internal/plugins/typescript/rules/no_invalid_void_type/no_invalid_void_type_test.go
    • Added new valid test cases for callable and construct signatures with void return types.
    • Included an invalid test case for void used in a callable signature parameter position.
  • internal/rules/getter_return/getter_return.go
    • Refactored the analyzeReturnPaths function to use a new pathResult enumeration for clearer control flow analysis.
    • Implemented recursive analyzeStatements and analyzeStatement functions to handle return, throw, if/else, switch/case/default, and try/catch/finally statements.
    • Added helper functions analyzeIfStatement, analyzeSwitchStatement, analyzeTryStatement, analyzeBranch, and combineResults for detailed control flow analysis.
    • Adjusted the GetterReturnRule definition from rule.CreateRule(rule.Rule{...}) to a direct rule.Rule{...} to address a rule naming issue.
  • internal/rules/getter_return/getter_return_test.go
    • Added numerous valid test cases for the getter-return rule, covering throw statements, try/catch blocks, and switch statements.
    • Included new invalid test cases for if-throw without an else branch, switch statements without a default clause, and try/catch blocks where not all paths return.
  • packages/rslint-test-tools/rstest.config.mts
    • Included getter-return.test.ts in the ESLint rules test configuration.
  • packages/rslint-test-tools/tests/eslint/rules/snapshots/getter-return.test.ts.snap
    • Generated new snapshot tests for the getter-return rule's invalid cases.
  • packages/rslint-test-tools/tests/eslint/rules/getter-return.test.ts
    • Added a new test file for the getter-return rule, including both valid and invalid test cases.
  • packages/rslint-test-tools/tests/typescript-eslint/rules/no-empty-function.test.ts
    • Added new valid test cases for functions that contain comments.
  • packages/rslint-test-tools/tests/typescript-eslint/rules/no-invalid-void-type.test.ts
    • Added new valid test cases for callable and construct signatures.
Activity
  • No human activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several fixes to align rule behaviors with ESLint, which is a great improvement. The changes for no-invalid-void-type and no-empty-function seem correct and well-tested. The control flow analysis for getter-return is a significant and much-needed rewrite.

I've left a couple of suggestions for minor refactoring to improve maintainability and correctness by reducing code duplication and using more specific AST helper methods. Overall, this is a solid contribution.

@fansenze fansenze force-pushed the fix/rule-behavior-fixes-20260306 branch 5 times, most recently from 1781e0b to 3b0a81c Compare March 9, 2026 06:20
@fansenze fansenze changed the title fix: fix 3 rule behavior differences with ESLint fix: fix rule behavior differences with ESLint and refactor control flow analysis Mar 9, 2026
@fansenze fansenze force-pushed the fix/rule-behavior-fixes-20260306 branch from 3b0a81c to cb3f5b4 Compare March 9, 2026 08:03
@fansenze fansenze changed the title fix: fix rule behavior differences with ESLint and refactor control flow analysis fix: fix rule behavior differences and refactor control flow analysis Mar 9, 2026
@fansenze fansenze force-pushed the fix/rule-behavior-fixes-20260306 branch from cb3f5b4 to 9ea1fca Compare March 9, 2026 08:34
- getter-return / array-callback-return / constructor-super: replace manual
  AST-based control flow analysis with shared utility using binder's
  NodeFlagsHasImplicitReturn, fixing try-catch false negatives
- getter-return: skip arrow functions with expression bodies in property
  descriptors (e.g. `get: () => value`), matching ESLint's BlockStatement check
- array-callback-return: fix false negative for mixed return-with-value and
  empty-return when allowImplicit is false (e.g. `if (a) return 1; else return;`)
- no-unnecessary-boolean-literal-compare: fix options parsing from JSON
  config, fix isNullableBoolean to reject unions with non-boolean/non-nullable
  members
- Add shared FunctionReturnAnalysis utility with tests
- Update rule documentation with missing options
- Enable no-unnecessary-boolean-literal-compare TS test suite
@fansenze fansenze force-pushed the fix/rule-behavior-fixes-20260306 branch from 9ea1fca to d507bc9 Compare March 9, 2026 08:45
@fansenze fansenze requested a review from hardfist March 9, 2026 09:13
@fansenze fansenze merged commit 0ee755a into main Mar 9, 2026
14 checks passed
@fansenze fansenze deleted the fix/rule-behavior-fixes-20260306 branch March 9, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants