Skip to content

fix: handle operators in constructor default arguments - #449

Open
ravenCrown0627 wants to merge 1 commit into
cpplint:developfrom
ravenCrown0627:fix/constructor-default-operators
Open

fix: handle operators in constructor default arguments#449
ravenCrown0627 wants to merge 1 commit into
cpplint:developfrom
ravenCrown0627:fix/constructor-default-operators

Conversation

@ravenCrown0627

@ravenCrown0627 ravenCrown0627 commented Jul 23, 2026

Copy link
Copy Markdown

Fixes #223.

Supersedes #426 and addresses the review feedback left there.

What changed

  • Treat <<, <<=, and <= as operators rather than template openers when collapsing constructor arguments.
  • Stop collapsing when no following comma-separated argument remains.
  • Add regression cases for <, <=, <<, and <<= in different parameter positions.

Root cause

CheckForNonStandardConstructs counted every < when balancing template arguments. An operator in a constructor default value therefore looked like an unmatched template opener, and the comma-collapsing loop read past the end of constructor_args.

Review follow-up

  • Keep the regex replacement inline instead of adding a global compiled regex.
  • Keep the comments terse and the operator explanation beside the expression.
  • Rotate parameter positions in the tests.

Validation

  • pytest: 231 passed, 96.46% coverage
  • ruff check and ruff format --check
  • pylint cpplint.py
  • mypy cpplint.py cpplint_clitest.py cpplint_unittest.py

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection of single-argument constructors when default arguments contain bitshift or comparison operators.
    • Reduced false positives caused by operators being mistaken for template syntax.
  • Tests

    • Added coverage for constructor arguments using bitshift and relational operators.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d6c3524-2498-4e6d-9a2d-7764951daaff

📥 Commits

Reviewing files that changed from the base of the PR and between 95551c6 and 2e8aa7d.

📒 Files selected for processing (2)
  • cpplint.py
  • cpplint_unittest.py

📝 Walkthrough

Walkthrough

Constructor argument collapsing now distinguishes shift and relational operators from template brackets, and tests cover explicit single-argument constructor detection for these expressions in default arguments.

Changes

Constructor argument parsing

Layer / File(s) Summary
Operator-aware argument collapsing
cpplint.py, cpplint_unittest.py
The parser uses operator-aware bracket balancing and index-based merging, with tests covering <<, <<=, <=, and < expressions in constructor defaults.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: aaronliu0130, janmarsino98

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main fix for constructor default-argument operators.
Linked Issues check ✅ Passed The changes address #223 by preventing the IndexError when << appears in constructor default arguments and add regression coverage.
Out of Scope Changes check ✅ Passed The code and tests stay focused on the constructor-argument parsing bug without unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ravenCrown0627
ravenCrown0627 marked this pull request as ready for review July 23, 2026 15:08

@yangfan-yf-yf yangfan-yf-yf left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed the current diff and the regression paths. The bounds check prevents the IndexError from #223, and the operator handling preserves the existing template/function-parameter comma collapsing. I also ran pytest --no-cov locally on Python 3.12 / Windows: 231 passed.

Comment thread cpplint.py

# collapse arguments so that commas in template parameter lists and function
# argument parameter lists don't split arguments in two
# Collapse commas inside template and function parameter lists.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a reason for this change?

Comment thread cpplint.py
Comment on lines +3952 to +3953
re.sub(r"<<=?|<=", "", constructor_arg).count("<") > constructor_arg.count(">")
or constructor_arg.count("(") > constructor_arg.count(")")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems very inefficient. We were already using .count to do four optimized single-character passes, and now we add a regex pass on top of that. Not to mention we're sort of simulating regex with the consuming (del) of tokens below, and adding onto our misery by going over parts of constructor_arg we've already searched again with each loop. Surely we can simplify at least this part to O(n).

@androvonx95 androvonx95 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Confirmed the fix at 2e8aa7d: A(int b, int c, int a = 1 << 1), A(int a = 1 << 1) and A(bool a = 1 < 2, int b = 0) all raise IndexError on develop and are clean here, with no change I could find on >>, >=, <=> or nested-template arguments. Full suite passes (206).

On @aranliu0130 's O(n) point, splitting on top-level commas in one pass drops both the regex and the repeated re-scanning, replacing the split(",") + collapse loop entirely:

constructor_args = []
arg_text = explicit_constructor_match.group(2)
current = []
depth = 0
i = 0

while i < len(arg_text):
    if arg_text[i : i + 2] in ("<<", "<="):  # operators, not template brackets
        current.append(arg_text[i : i + 2])
        i += 2
        continue

    char = arg_text[i]
    if char in "<(":
        depth += 1
    elif char in ">)":
        depth = max(depth - 1, 0)
    elif char == "," and not depth:
        constructor_args.append("".join(current))
        current = []
        i += 1
        continue

    current.append(char)
    i += 1

constructor_args.append("".join(current))

<<= falls out of the << branch, and clamping the decrement keeps <=> and stray > from breaking the depth count. I ran this on current develop: 206 tests pass, and it matches this PR's behavior on all four of your new cases plus the ones above.

Also worth reverting the comment rewording on line 3946 unless it was intentional as that's the other question raised in review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error occurred in default value that with << in constructor

4 participants