-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Port ESLint core rule no-compare-neg-zero #71
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
Conversation
## Summary This PR ports the ESLint core rule `no-compare-neg-zero` to rslint, disallowing comparisons against -0. Follow-up task of PR #70. ## Implementation Details - ✅ Created new rule in `internal/rules/no_compare_neg_zero/` - ✅ Detects comparisons against negative zero (-0) - ✅ Checks all comparison operators (>, >=, <, <=, ==, ===, !=, !==) - ✅ Works for -0 on either side of the comparison - ✅ Registered in global rule registry ## Rule Behavior The rule disallows comparing against -0 because such comparisons will match both +0 and -0, which is likely unintended. The proper way to check for negative zero is using Object.is(x, -0). ### Invalid Patterns ```javascript // Equality operators x === -0; -0 === x; x == -0; -0 == x; // Comparison operators x > -0; -0 > x; x >= -0; -0 >= x; x < -0; -0 < x; x <= -0; -0 <= x; ``` ### Valid Patterns ```javascript // Compare against positive zero x === 0; 0 === x; // Use Object.is() for accurate -0 detection Object.is(x, -0); // Other negative numbers x === -1; // String comparisons x === '-0'; ``` ## Test Coverage - ✅ Ported comprehensive test cases from ESLint's test suite - ✅ **14 valid test cases** covering various scenarios - ✅ **12 invalid test cases** with expected error detection - ✅ Tests include: - All comparison operators (>, >=, <, <=, ==, ===, !=, !==) - Negative zero on both left and right sides - Valid alternatives (positive zero, Object.is()) - String comparisons - Other negative numbers ## Test Plan - [x] Rule implementation follows rslint patterns - [x] All test cases ported from ESLint - [ ] Tests pass (requires full build environment with submodules) - [ ] Manual testing with example code - [ ] Integration with existing linter setup ## References - ESLint Rule: https://eslint.org/docs/latest/rules/no-compare-neg-zero - ESLint Source: https://github.com/eslint/eslint/blob/main/lib/rules/no-compare-neg-zero.js - ESLint Tests: https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-compare-neg-zero.js - Related PR #70: #70 ## Files Changed - `internal/config/config.go` - Added rule registration (2 lines) - `internal/rules/no_compare_neg_zero/no_compare_neg_zero.go` - Complete rule implementation (93 lines) - `internal/rules/no_compare_neg_zero/no_compare_neg_zero_test.go` - Comprehensive test suite (125 lines) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
🤖 This pull request has been linked to DevBird Task #1117 View the task details and manage the automated development workflow in DevBird. Learn more about DevBird here or the announcement blog post here. |
📋 DevBird Task PromptObjectivePort the ESLint core rule Documentation & Resources
Rule DescriptionDisallows comparing against -0. Implementation Requirements
Test Requirements
Success Criteria
This comment was automatically added by DevBird. You can disable this feature in DevBird Settings. |
Code Review: Port ESLint core rule no-compare-neg-zeroThank you for this contribution! I've reviewed the implementation of the Positive Aspects
Issues Found1. Critical: Incorrect AST Node Kind Check (no_compare_neg_zero.go:35)The // Current implementation (line 34-37)
switch operand.Kind {
case ast.KindNumericLiteral:
numLiteral := operand.AsNumericLiteral()
if numLiteral \!= nil && numLiteral.Text() == "0" {Issue: The fallback check at line 40-44 for case ast.KindNumericLiteral:
text := operand.Text()
if text == "0" {
return true
}The Recommendation: Simplify to match the pattern used in 2. Potential Bug: Unverified FunctionalityThe test plan shows "Tests pass (requires full build environment with submodules)" is unchecked. Given the uncertainty in the Recommendation: The tests should be run before merging to verify the implementation works as expected. 3. Code Quality: Redundant Fallback Case (no_compare_neg_zero.go:40-44)case ast.KindFirstLiteralToken:
// Some parsers might use FirstLiteralToken for numeric literals
if operand.Text() == "0" {
return true
}This comment "Some parsers might use..." indicates uncertainty. In a strongly-typed Go codebase with typescript-go, there should be a single, predictable AST node kind for numeric literals. Recommendation: Remove this fallback after determining the correct node kind, or add a comment explaining when this case actually occurs based on testing. 4. Minor: Inconsistent Nil Checks (no_compare_neg_zero.go:36-37)numLiteral := operand.AsNumericLiteral()
if numLiteral \!= nil && numLiteral.Text() == "0" {The code calls case ast.KindNumericLiteral:
if operand.Text() == "0" {
return true
}Recommendations
Performance ConsiderationsNo performance concerns. The rule efficiently checks only binary expressions and uses simple AST traversal. Security ConsiderationsNo security concerns. This is a static analysis rule with no runtime implications or external inputs. Test CoverageTest coverage is excellent with comprehensive valid and invalid cases. Once the implementation is verified to work correctly, the tests should provide good confidence. Suggested FixHere's how I would rewrite // isNegativeZero checks if a node represents -0
func isNegativeZero(node *ast.Node) bool {
if node == nil || node.Kind \!= ast.KindPrefixUnaryExpression {
return false
}
prefix := node.AsPrefixUnaryExpression()
if prefix == nil || prefix.Operator \!= ast.KindMinusToken {
return false
}
operand := prefix.Operand
if operand == nil || operand.Kind \!= ast.KindNumericLiteral {
return false
}
return operand.Text() == "0"
}SummaryThis is a solid implementation that follows project conventions well. The main concern is verifying that the AST node kind detection actually works as expected. Please run the tests in the full build environment and confirm the rule correctly detects all invalid cases before merging. Status: Approved pending test verification and minor code simplification |
- Changed ast.SyntaxKind to ast.Kind (correct type name) - Removed duplicate case for ast.KindFirstLiteralToken - Changed numLiteral.Text() to numLiteral.Text (field, not method) - Added getOperatorText helper function to convert operator Kind to string - Used getOperatorText instead of calling Text() on Token node All tests now pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: PR #71 - Port ESLint core rule no-compare-neg-zeroSummaryThis PR successfully ports the ESLint ✅ Strengths
🔍 Code Quality & Best PracticesIssues Found1. Missing Edge Cases in isNegativeZero (Medium Priority)Location: The current implementation only checks for numeric literals with text "0", but doesn't handle:
Recommendation: Add additional checks for alternative zero formats. 2. Unnecessary Map Allocation (Performance)Location: The 3. Error Reporting Location (Low Priority)Location: Consider reporting on the specific 🐛 Potential BugsNo Critical Bugs Found ✓The logic appears sound with good nil checks throughout. ⚡ Performance ConsiderationsOverall Performance: Good The implementation is efficient. Main improvement would be moving 🔒 Security ConcernsNo Security Issues Found ✓🧪 Test CoverageExcellent ✓Coverage includes:
Optional enhancements: Test alternative numeric zero formats, nested expressions, TypeScript-specific cases. 📋 Recommendations SummaryMedium Priority
Low Priority
✅ VerdictLGTM with minor suggestions 🎉 This is a well-implemented rule. The code is clean, well-tested, and follows project conventions. The suggested improvements are optional enhancements rather than blockers. Recommendation: Approve and merge. Review generated with Claude Code |
This PR ports the ESLint core rule `no-cond-assign` to rslint, disallowing assignment operators in conditional expressions. Follow-up task of PR #71. ## Implementation Details - Created new rule in `internal/rules/no_cond_assign/` - Detects assignment operators in conditional test expressions - Supports two modes: "except-parens" (default) and "always" - Works with if, while, do-while, for, and ternary conditional expressions - Registered in global rule registry ## Rule Behavior The rule prevents assignment operators in conditional expressions, which can easily be confused with comparison operators. This helps avoid bugs caused by unintended variable mutations during conditional evaluations. ### Mode: "except-parens" (Default) Allows assignments in conditionals only when properly parenthesized: - For if/while/do-while/for: Single parentheses suffice - For ternary expressions: Double parentheses required ### Mode: "always" Disallows all assignment operators in conditionals, regardless of parentheses. ### Invalid Patterns (except-parens mode) ```javascript // Missing parentheses if (x = 0) { } while (x = 0) { } do { } while (x = x + 1); for (; x += 1;) { } ``` ### Valid Patterns (except-parens mode) ```javascript // Properly parenthesized assignments if ((someNode = someNode.parentNode) !== null) { } while ((a = b)) { } do { } while ((a = b)); for (; (a = b);) { } // Comparisons (not assignments) if (x === 0) { } while (x < 5) { } ``` ## Test Coverage - Ported comprehensive test cases from ESLint's test suite - **28 valid test cases** covering various scenarios - **30 invalid test cases** with expected error detection - Tests include: - Both "except-parens" and "always" modes - All conditional statement types - Properly/improperly parenthesized assignments - Comparison operators (should pass) - Compound assignment operators (+=, -=, etc.) ## References - ESLint Rule: https://eslint.org/docs/latest/rules/no-cond-assign - ESLint Source: https://github.com/eslint/eslint/blob/main/lib/rules/no-cond-assign.js - ESLint Tests: https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-cond-assign.js - Related PR #71: #71 ## Files Changed - `internal/config/config.go` - Added rule registration (2 lines) - `internal/rules/no_cond_assign/no_cond_assign.go` - Complete rule implementation (294 lines) - `internal/rules/no_cond_assign/no_cond_assign_test.go` - Comprehensive test suite (217 lines) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
## Summary This PR ports the ESLint core rule `no-cond-assign` to rslint, disallowing assignment operators in conditional expressions. Follow-up task of PR #71. ## Implementation Details - ✅ Created new rule in `internal/rules/no_cond_assign/` - ✅ Detects assignment operators in conditional test expressions - ✅ Supports two modes: "except-parens" (default) and "always" - ✅ Works with if, while, do-while, for, and ternary conditional expressions - ✅ Registered in global rule registry ## Rule Behavior The rule prevents assignment operators in conditional expressions, which can easily be confused with comparison operators. This helps avoid bugs caused by unintended variable mutations during conditional evaluations. ### Mode: "except-parens" (Default) Allows assignments in conditionals only when properly parenthesized: - For if/while/do-while/for: Single parentheses suffice - For ternary expressions: Double parentheses required ### Mode: "always" Disallows all assignment operators in conditionals, regardless of parentheses. ### Invalid Patterns (except-parens mode) ```javascript // Missing parentheses if (x = 0) { } while (x = 0) { } do { } while (x = x + 1); for (; x += 1;) { } // Nested in logical expressions if (a && (b = c)) { } while (a || (b = c)) { } ``` ### Valid Patterns (except-parens mode) ```javascript // Properly parenthesized assignments if ((someNode = someNode.parentNode) !== null) { } while ((a = b)) { } do { } while ((a = b)); for (; (a = b);) { } // Comparisons (not assignments) if (x === 0) { } while (x < 5) { } ``` ### Invalid Patterns (always mode) ```javascript // All assignments forbidden, even with parentheses if ((x = 0)) { } while ((x = 0)) { } if (someNode || (someNode = parentNode)) { } ``` ## Test Coverage - ✅ Ported comprehensive test cases from ESLint's test suite - ✅ **28 valid test cases** covering various scenarios - ✅ **30 invalid test cases** with expected error detection - ✅ Tests include: - Both "except-parens" and "always" modes - All conditional statement types (if, while, do-while, for, ternary) - Properly/improperly parenthesized assignments - Comparison operators (should pass) - Compound assignment operators (+=, -=, *=, etc.) - Nested logical expressions - Arrow functions and regular functions - Switch statements (assignments in case clauses) ## Test Plan - [x] Rule implementation follows rslint patterns - [x] All test cases ported from ESLint - [ ] Tests pass (requires full build environment with submodules) - [ ] Manual testing with example code - [ ] Integration with existing linter setup ## References - ESLint Rule: https://eslint.org/docs/latest/rules/no-cond-assign - ESLint Source: https://github.com/eslint/eslint/blob/main/lib/rules/no-cond-assign.js - ESLint Tests: https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-cond-assign.js - Related PR #71: #71 ## Files Changed - `internal/config/config.go` - Added rule registration (2 lines) - `internal/rules/no_cond_assign/no_cond_assign.go` - Complete rule implementation (294 lines) - `internal/rules/no_cond_assign/no_cond_assign_test.go` - Comprehensive test suite (217 lines) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Summary
This PR ports the ESLint core rule
no-compare-neg-zeroto rslint, disallowing comparisons against -0.Follow-up task of PR #70.
Implementation Details
internal/rules/no_compare_neg_zero/Rule Behavior
The rule disallows comparing against -0 because such comparisons will match both +0 and -0, which is likely unintended. The proper way to check for negative zero is using
Object.is(x, -0).Invalid Patterns
Valid Patterns
Test Coverage
Test Plan
References
Files Changed
internal/config/config.go- Added rule registration (2 lines)internal/rules/no_compare_neg_zero/no_compare_neg_zero.go- Complete rule implementation (93 lines)internal/rules/no_compare_neg_zero/no_compare_neg_zero_test.go- Comprehensive test suite (125 lines)🤖 Generated with Claude Code