Skip to content

Conversation

@yruslan
Copy link
Collaborator

@yruslan yruslan commented Nov 21, 2025

Closes #801

Summary by CodeRabbit

Release Notes

  • New Features & Improvements

    • Enhanced validation for nested group fields within segment redefines
    • Improved handling to support gaps between consecutive segment redefines
  • Tests

    • Added test coverage for segment redefine validation scenarios

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

This PR modifies the COBOL parser's segment redefine validation logic to permit non-contiguous segment redefines (allowing gaps) while maintaining validation that all gap-separated segments belong to the same redefine group and satisfy grouping constraints.

Changes

Cohort / File(s) Summary
Segment redefine validation logic
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/asttransform/SegmentRedefinesMarker.scala
Adds validation for nested Group fields that are redefines within a segment redefine context. Introduces fieldMightBeRedefine flag to allow redefines between segment redefines. Adjusts control flow to skip recursive processing of nested fields when within an active redefine state (redefineGroupState != 0).
Segment redefine test coverage
cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/parse/SegmentRedefinesSpec.scala
Adds three new test cases: validating gaps in segment redefines are permitted when segments share the same redefine base; ensuring the first segment must be redefined somewhere in the sequence; and confirming non-redefined fields between segment redefines raise IllegalStateException.

Sequence Diagram

sequenceDiagram
    participant Parser as Segment Redefine Processor
    participant GroupField as Group Field (Nested)
    participant Validator as Validation Logic

    rect rgb(220, 240, 255)
    Note over Parser,Validator: Processing Group Within Redefine State (redefineGroupState == 1)
    end

    alt Group is itself a Redefine (g.redefines nonEmpty)
        Parser->>Validator: Check if field is valid redefine
        alt Field is REDEFINE or redefined by another
            Validator-->>Parser: ✓ Valid, continue
        else Field not in redefine group
            Validator-->>Parser: ✗ Throw IllegalStateException
        end
    else Group is not a Redefine
        Parser->>Validator: Check if field might be a redefine<br/>(fieldMightBeRedefine = true)
        Validator-->>Parser: Pass flag to ensure validation
        Note over Parser: "Allow redefines in between<br/>segment redefines"
        alt redefineGroupState == 0 (outside active redefine)
            Parser->>GroupField: Recurse into processGroupFields
        else redefineGroupState != 0 (inside active redefine)
            Parser->>GroupField: Return field as-is<br/>(no deeper processing)
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Validation branch logic: Verify the new guard condition correctly enforces that nested redefines within a segment redefine state are themselves valid redefines.
  • Control flow change: Confirm the recursion guard (only recurse when redefineGroupState == 0) doesn't inadvertently skip processing of fields that should be examined deeper.
  • fieldMightBeRedefine flag: Ensure the flag correctly captures the intent to allow gaps between non-contiguous segment redefines.
  • Test cases: Validate that the three new tests adequately cover the gap-permitting behavior, first-segment requirement, and error conditions.

Poem

🐰 Hopping through redefines with joy and cheer,
Gaps between segments now welcome here!
No need for every step in between,
The finest parser you've ever seen!

Pre-merge checks and finishing touches

✅ 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 directly describes the main change: allowing gaps between segment redefined fields with a common base redefine, which aligns with the primary objective of the PR.
Linked Issues check ✅ Passed The code changes implement the proposed solution: validation allows gaps in segment redefines as long as they share a common base field, matching the requirement in issue #801.
Out of Scope Changes check ✅ Passed All changes are scoped to the segment redefine validation logic and corresponding tests; no unrelated modifications are present.
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
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/801-allow-gaps-in-segment-redefines

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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 and usage tips.

@github-actions
Copy link

JaCoCo code coverage report - 'cobol-parser'

Overall Project 91.52% 🍏
File Coverage
SegmentRedefinesMarker.scala 90.54% 🍏

@github-actions
Copy link

JaCoCo code coverage report - 'spark-cobol'

There is no coverage information present for the Files changed

Total Project Coverage 81.1% 🍏

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/parse/SegmentRedefinesSpec.scala (1)

91-116: Test coverage for gaps feature is good but could be more thorough.

The test correctly validates that SEGMENT-A, SEGMENT-C, and SEGMENT-D are marked as segment redefines while SEGMENT-B (the gap) is not. However, the assertions only check 4 of the 6 children in the copybook.

Consider adding assertions for completeness:

     assert(!parsedCopybook.ast.children.head.asInstanceOf[Group].children(0).asInstanceOf[Group].isSegmentRedefine)
     assert(parsedCopybook.ast.children.head.asInstanceOf[Group].children(1).asInstanceOf[Group].isSegmentRedefine)
     assert(!parsedCopybook.ast.children.head.asInstanceOf[Group].children(2).asInstanceOf[Group].isSegmentRedefine)
     assert(parsedCopybook.ast.children.head.asInstanceOf[Group].children(3).asInstanceOf[Group].isSegmentRedefine)
+    assert(parsedCopybook.ast.children.head.asInstanceOf[Group].children(4).asInstanceOf[Group].isSegmentRedefine)
+    assert(!parsedCopybook.ast.children.head.asInstanceOf[Group].children(5).asInstanceOf[Group].isSegmentRedefine)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6c0057 and 1db0ebc.

📒 Files selected for processing (2)
  • cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/asttransform/SegmentRedefinesMarker.scala (1 hunks)
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/parse/SegmentRedefinesSpec.scala (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/asttransform/SegmentRedefinesMarker.scala (1)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/ast/Group.scala (1)
  • withUpdatedIsSegmentRedefine (102-104)
cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/parse/SegmentRedefinesSpec.scala (2)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/CopybookParser.scala (2)
  • CopybookParser (42-490)
  • parseTree (198-241)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/policies/FillerNamingPolicy.scala (2)
  • FillerNamingPolicy (21-32)
  • SequenceNumbers (22-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Spark 3.5.7 on Scala 2.12.20
  • GitHub Check: Spark 3.5.7 on Scala 2.13.17
  • GitHub Check: Spark 3.4.4 on Scala 2.12.20
  • GitHub Check: Spark 2.4.8 on Scala 2.11.12
  • GitHub Check: test (2.12.20, 2.12, 3.3.4, 0, 80, 20)
🔇 Additional comments (5)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/asttransform/SegmentRedefinesMarker.scala (3)

76-77: Validation logic correctly enforces single redefine group.

The check ensures that once inside a redefine group (state=1), any new segment redefine field must itself be a REDEFINE (have a non-empty redefines clause) or be redefined by another field. This prevents mixing different redefine groups and correctly enforces that gaps are only allowed within the same redefine family.

The condition g.redefines.isEmpty is checked when redefineGroupState == 1, meaning after the base segment redefine has been encountered. Since the base field (first in the group) doesn't have a redefines clause, it sets state to 1. Any subsequent segment redefine without a redefines clause would indicate a new redefine group, which is correctly rejected here.


83-88: Gap-allowing logic correctly implemented.

The fieldMightBeRedefine flag enables the key feature: when inside a redefine group (state=1), fields that are themselves redefines (have non-empty redefines clause) are treated as potential segment redefines. This prevents the state from transitioning to 2, allowing subsequent segment redefines to be found even when there are intervening redefine fields.

The logic correctly distinguishes between:

  • Fields that are redefines (allowed as gaps): fieldMightBeRedefine = true
  • Fields that are not redefines (would end the group): fieldMightBeRedefine = false

90-94: Recursion guard aligns with segment redefine level constraints.

The change to only recurse when redefineGroupState == 0 is correct. Once segment redefines are found at the current level (state > 0), there's no need to search deeper levels since the validation rules require "all segment fields should belong to the level 1 (one level down record root level)". This optimization prevents unnecessary recursion while maintaining correct validation.

cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/parse/SegmentRedefinesSpec.scala (2)

145-168: Test correctly validates that base segment must be redefined.

This test ensures that SEGMENT-A (which is not redefined by any field and doesn't redefine another field) cannot be used as a segment redefine. The expected error message correctly identifies that SEGMENT_A was not found in the valid redefine structure.

The copybook structure creates two separate redefine groups:

  • SEGMENT-B (base) → SEGMENT-C → SEGMENT-D
  • SEGMENT-A (standalone, not part of any redefine group)

Since segment redefines must all belong to the same redefine group, SEGMENT-A is correctly rejected.


170-193: Test correctly validates no non-redefined fields between segment redefines.

This test ensures that SEGMENT-C (which is a base field that doesn't redefine anything, even though it's redefined by SEGMENT-D) cannot appear between segment redefines from a different group. The error message correctly identifies that SEGMENT_C is not a REDEFINE or redefined by another field in the same group as SEGMENT-A and SEGMENT-B.

The validation enforces that once inside a redefine group, only fields that are themselves redefines (have a REDEFINES clause) can appear before the next segment redefine.

@yruslan yruslan merged commit 4ae45f3 into master Nov 21, 2025
7 checks passed
@yruslan yruslan deleted the feature/801-allow-gaps-in-segment-redefines branch November 21, 2025 08:52
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.

Allow gaps in segment redefines

2 participants