Skip to content

Conversation

@h1alexbel
Copy link
Member

@h1alexbel h1alexbel commented Apr 2, 2025

In this PR I've introduced new lint: missing-rho-reference, that issues defect with error severity, in case of \rho reference (.^) is missing inside abstract object, reference refers to. I also left several puzzles to be implemented later.

closes #13
History:

Summary by CodeRabbit

  • New Features

    • Added detection and reporting of missing rho references in EO language code, providing clear error messages when a reference is not found.
  • Documentation

    • Introduced documentation explaining missing rho reference errors, including examples of incorrect and correct usage.
  • Tests

    • Added multiple test cases to verify correct detection of missing and present rho references, including deeply nested scenarios and sibling object references.

@h1alexbel
Copy link
Member Author

@maxonfjvipon the changes are very experimental, I'm not sure about the way of navigating over parent objects from \rho reference. Could you take a look, please?

@h1alexbel
Copy link
Member Author

@maxonfjvipon WDYT?

@h1alexbel h1alexbel marked this pull request as draft May 21, 2025 10:09
@github-actions
Copy link
Contributor

github-actions bot commented May 21, 2025

🚀 Performance Analysis

All benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information.

Click to see the detailed report
Test Base Score PR Score Change % Change Unit Mode
benchmarks.SourceBench.scansXmir (size=S) 6126.497 6342.179 215.682 3.52% ms/op Average Time
benchmarks.SourceBench.scansXmir (size=M) 6747.124 6719.733 -27.390 -0.41% ms/op Average Time
benchmarks.SourceBench.scansXmir (size=L) 7718.794 7756.474 37.680 0.49% ms/op Average Time
benchmarks.SourceBench.scansXmir (size=XL) 9234.893 9245.781 10.888 0.12% ms/op Average Time
benchmarks.SourceBench.scansXmir (size=XXL) 21895.827 22199.978 304.151 1.39% ms/op Average Time

⚠️ Performance loss: benchmarks.SourceBench.scansXmir (size=S) is slower by 215.682 ms/op (3.52%)
✅ Performance gain: benchmarks.SourceBench.scansXmir (size=M) is faster by 27.390 ms/op (0.41%)
⚠️ Performance loss: benchmarks.SourceBench.scansXmir (size=L) is slower by 37.680 ms/op (0.49%)
⚠️ Performance loss: benchmarks.SourceBench.scansXmir (size=XL) is slower by 10.888 ms/op (0.12%)
⚠️ Performance loss: benchmarks.SourceBench.scansXmir (size=XXL) is slower by 304.151 ms/op (1.39%)

@h1alexbel h1alexbel marked this pull request as ready for review May 21, 2025 13:57
@h1alexbel
Copy link
Member Author

@maxonfjvipon WDYT?

@h1alexbel h1alexbel requested a review from maxonfjvipon May 21, 2025 13:57
Copy link
Member

@maxonfjvipon maxonfjvipon left a comment

Choose a reason for hiding this comment

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

@h1alexbel let's add the next test pack:

[] > foo
  x > @
    []
      ^.bar > @

it should not complain

@yegor256
Copy link
Member

yegor256 commented Jul 7, 2025

@h1alexbel what's up with this one?

@h1alexbel
Copy link
Member Author

@yegor256 plan to finish it soon

@coderabbitai
Copy link

coderabbitai bot commented Jul 7, 2025

Walkthrough

A new XSLT stylesheet for detecting missing rho (^.) references in EO language XML is introduced, alongside documentation and multiple YAML-based test cases. The stylesheet checks for missing references, while the tests verify correct detection and non-detection of missing or present rho references in various nested object scenarios.

Changes

File(s) Change Summary
src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl Added XSLT stylesheet to detect missing rho references in EO XML.
src/main/resources/org/eolang/motives/errors/missing-rho-reference.md Added documentation explaining missing rho reference errors, with examples.
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object.yaml Added test: verifies no error for valid sibling rho reference.
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object-from-deeply-nested.yaml Added test: verifies no error for valid deep nested rho reference.
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-when-parent-has-multiple-objects.yaml Added test: verifies no error for valid rho reference when parent has multiple objects.
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catch-missing-rho-ref-from-deeply-nested.yaml Added test: detects missing rho reference in deeply nested context.
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catches-missing-rho-ref.yaml Added test: detects missing rho reference in a simple nested context.

Sequence Diagram(s)

sequenceDiagram
    participant EO_XML as EO XML Input
    participant XSLT as missing-rho-reference.xsl
    participant Output as Defects XML

    EO_XML->>XSLT: Provide EO source as XML
    XSLT->>XSLT: For each object with @base starting with ^.
    XSLT->>XSLT: Resolve owner and attribute
    XSLT->>XSLT: Traverse ancestors to find attribute
    alt Attribute missing
        XSLT->>Output: Emit <defect> for missing rho reference
    else Attribute found
        XSLT->>Output: No defect emitted
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
Detect missing ^ (rho) references in EO source code (#13)
Correctly report missing rho references in nested and complex object scenarios (#13)
Do not report errors for valid rho references to present objects (#13)

Suggested labels

core

Suggested reviewers

  • maxonfjvipon
  • yegor256

Poem

A rabbit hopped through EO code,
Seeking rho refs down each road.
"Is 'message' there?" it asked with care,
And flagged the missing ones laid bare.
With tests and docs, the journey's done—
Hooray for linting, bugs on the run!
🐇✨


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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: 5

🧹 Nitpick comments (6)
src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl (1)

15-18: Address TODO comments before merging.

There are two significant TODO comments indicating:

  1. The report-missing template needs restructuring (lines 15-18)
  2. Auto-named objects are not fully supported (lines 37-40)

These should be addressed as they represent core functionality gaps.

Would you like me to help implement these TODO items or create issues to track them?

Also applies to: 37-40

src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object-from-deeply-nested.yaml (1)

1-21: Good coverage for deeply nested references.

This test appropriately covers the ^.^.message pattern.

Consider adding more edge cases like:

  • Triple nesting (^.^.^.attr)
  • References to non-existent deeply nested attributes
  • Mix of existing and non-existing references in the same object
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catches-missing-rho-ref.yaml (2)

4-8: Add message assertion & align style with sibling test

You only assert the count and the line number. Including a normalize-space() assertion for the exact message – as you already do in the “deeply-nested” sibling – would make the test stricter and prevent silent regressions in the wording.

   - /defects[count(defect[@severity='error'])=1]
   - /defects/defect[@line='4']
+  - /defects/defect[1][normalize-space()=
+    'The rho reference "hello" is missing in "foo" object']

1-8: Keep yamllint happy – disable long-line rule

The XPath in the previous suggestion (and even the current second assertion) breaches the default 80-char limit enforced by yamllint.
Add the same directive you already placed in the second test file to avoid CI noise.

----
+# yamllint disable rule:line-length
+---
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catch-missing-rho-ref-from-deeply-nested.yaml (2)

10-10: Quote the whole XPath to avoid YAML edge-cases

The scalar starts with / but contains an unbalanced single quote right after normalize-space()=.
While most YAML parsers swallow it, it is technically a plain-scalar gotcha and trips up stricter linters.
Wrap the whole XPath in single quotes (and escape the internal ones) or keep the current disable-rule comment but be explicit.

-  - /defects/defect[1][normalize-space()='The rho reference "messageeee" is missing in "foo" object']
+  - '/defects/defect[1][normalize-space()=''The rho reference "messageeee" is missing in "foo" object'']'

1-3: File-name consistency

Other resources follow the catches-… prefix.
Renaming this file to catches-missing-rho-ref-from-deeply-nested.yaml keeps naming uniform and eases grepping.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a4db4e and d73f842.

📒 Files selected for processing (7)
  • src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl (1 hunks)
  • src/main/resources/org/eolang/motives/errors/missing-rho-reference.md (1 hunks)
  • src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object-from-deeply-nested.yaml (1 hunks)
  • src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object.yaml (1 hunks)
  • src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-when-parent-has-multiple-objects.yaml (1 hunks)
  • src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catch-missing-rho-ref-from-deeply-nested.yaml (1 hunks)
  • src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/catches-missing-rho-ref.yaml (1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/main/resources/org/eolang/motives/errors/missing-rho-reference.md

[grammar] ~3-~3: The plural noun “objects” cannot be used with the article “an”. Did you mean “an existing object” or “existing objects”?
Context: ...] reference (^.) should point only to an existing objects. Incorrect: ```eo # Foo. [] > foo [...

(A_NNS)

🔇 Additional comments (2)
src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-to-present-object.yaml (1)

1-14: Well-structured test case.

This test correctly verifies that valid rho references to sibling objects don't trigger false positives.

src/test/resources/org/eolang/lints/packs/single/missing-rho-reference/allows-rho-ref-when-parent-has-multiple-objects.yaml (1)

1-15: Good test coverage for multiple siblings.

This test appropriately covers the case where the parent has multiple objects.

For now we ignore them, but we need to check them as well, as they are abstract
objects. Don't forget to add test packs with auto named objects.
-->
<xsl:if test="not($owner/o[@name=$attribute]) and not(contains($owner/@name, 'a🌵'))">
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent pattern matching for auto-named objects.

Line 41 uses contains() while line 25 uses starts-with() for checking the auto-named pattern. This inconsistency could lead to different behavior.

Apply consistent pattern matching:

-<xsl:if test="not($owner/o[@name=$attribute]) and not(contains($owner/@name, 'a🌵'))">
+<xsl:if test="not($owner/o[@name=$attribute]) and not(starts-with($owner/@name, 'a🌵'))">
🤖 Prompt for AI Agents
In src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl at line
41, replace the contains() function with starts-with() to match the pattern used
at line 25 for checking auto-named objects. This ensures consistent pattern
matching by using starts-with($owner/@name, 'a🌵') instead of contains(),
aligning the logic across the file.

<xsl:param name="attribute"/>
<xsl:param name="owner"/>
<xsl:choose>
<xsl:when test="$owner[not(eo:abstract(.))] or not(empty($owner/o[starts-with(@name, 'a🌵')]))">
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Logic appears inverted in the recursion condition.

The condition on line 25 seems to continue recursion when the owner is NOT abstract or HAS auto-named children. Based on the comment at line 13-14, shouldn't this skip auto-named objects instead? This logic appears inverted.

Consider reversing the logic:

-<xsl:when test="$owner[not(eo:abstract(.))] or not(empty($owner/o[starts-with(@name, 'a🌵')]))">
+<xsl:when test="$owner[eo:abstract(.)] and empty($owner/o[starts-with(@name, 'a🌵')])">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<xsl:when test="$owner[not(eo:abstract(.))] or not(empty($owner/o[starts-with(@name, 'a🌵')]))">
<xsl:when test="$owner[eo:abstract(.)] and empty($owner/o[starts-with(@name, 'a🌵')])">
🤖 Prompt for AI Agents
In src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl at line
25, the recursion condition incorrectly continues when the owner is not abstract
or has auto-named children, which is inverted. Modify the condition to skip
recursion for owners that are abstract or have auto-named children by reversing
the logic in the test expression accordingly.

Comment on lines +68 to +72
<xsl:variable name="position" select="(count(tokenize(@base, '\^')) - 1) * 2"/>
<xsl:call-template name="report-missing">
<xsl:with-param name="position" select="$position"/>
<xsl:with-param name="attribute" select="translate(translate(@base, '.^', ''), '$', '')"/>
<xsl:with-param name="owner" select="ancestor::node()[$position]"/>
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Unclear position calculation logic.

The position calculation (count(tokenize(@base, '\^')) - 1) * 2 lacks documentation. Why multiply by 2? This makes the code hard to understand and maintain.

Add documentation or verify the calculation:


🏁 Script executed:

#!/bin/bash
# Search for examples of rho references to understand the pattern
rg -A 5 -B 5 '\$\.\^' --type yaml

Length of output: 35


Here’s a deeper inspection across all XSL error templates to see if this “* 2” pattern recurs and how other templates document it:


🏁 Script executed:

#!/bin/bash
echo "1) Listing all missing-*-reference.xsl files:"
ls src/main/resources/org/eolang/lints/errors/missing-*-reference.xsl

echo
echo "2) Looking for all count(tokenize occurrences in these XSLs:"
rg -n "count(tokenize" src/main/resources/org/eolang/lints/errors/*.xsl

echo
echo "3) Checking how ancestor::node() is used elsewhere:"
rg -n "ancestor::node" src/main/resources/org/eolang/lints/errors/*.xsl

echo
echo "4) Finding the report-missing template definition for context:"
rg -n "<xsl:template name=\"report-missing\"" src/main/resources/org/eolang/lints/errors/*.xsl

Length of output: 2011


Document the position‐calculation logic

The (count(tokenize(@base,'\^')) - 1) * 2 expression is only used in missing-rho-reference.xsl, and nothing else in the repo uses that same pattern—so it really needs an explanatory comment. Without it, future maintainers will struggle to understand why each caret maps to “two levels” in the XSLT tree.

Please update src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl around line 68 to include a clear XSL comment, for example:

<!-- 
  Each '^' in @base represents a missing ρ-reference.
  We step up two ancestor nodes per caret, so:
    (count of '^') - 1  → number of jumps
    × 2                 → levels per jump 
-->
<xsl:variable name="position"
              select="(count(tokenize(@base, '\^')) - 1) * 2"/>
  • File: src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl
  • Lines: ~68
🤖 Prompt for AI Agents
In src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl around
line 68, add an explanatory XSL comment above the position variable declaration
to clarify the logic behind the expression (count(tokenize(@base, '\^')) - 1) *
2. The comment should explain that each '^' in @base represents a missing
ρ-reference and that the calculation steps up two ancestor nodes per caret,
detailing the meaning of each part of the expression for future maintainers.

Comment on lines +26 to +32
<xsl:variable name="up" select="ancestor::node()[$position + 1]"/>
<xsl:if test="name($up) = 'o'">
<xsl:call-template name="report-missing">
<xsl:with-param name="position" select="$position + 1"/>
<xsl:with-param name="attribute" select="$attribute"/>
<xsl:with-param name="owner" select="$up"/>
</xsl:call-template>
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fragile ancestor navigation logic.

Using ancestor::node()[$position + 1] is fragile as it depends on the exact node structure. Consider using a more robust approach like ancestor::o to specifically target object elements.

Verify that the position calculation correctly navigates to parent objects in all cases by examining the XML structure:


🏁 Script executed:

#!/bin/bash
# Search for test cases that might reveal the expected XML structure
fd -e yaml -e xml | xargs rg -l "missing-rho-reference|\\$\\.\\^" | head -10 | xargs cat

Length of output: 2048


Use ancestor::o for reliable object lookup

The current lookup

<xsl:variable name="up" select="ancestor::node()[$position + 1]"/>

depends on every ancestor (including text or comment nodes) and is brittle. Instead, pick the Nth object ancestor directly:

Replace

- <xsl:variable name="up" select="ancestor::node()[$position + 1]"/>
+ <xsl:variable name="up" select="(ancestor::o)[$position + 1]"/>

This way you only count <o> elements (object scopes), so the $position+1 lookup always lands on the correct object.

🤖 Prompt for AI Agents
In src/main/resources/org/eolang/lints/errors/missing-rho-reference.xsl around
lines 26 to 32, the variable 'up' is assigned using ancestor::node() which
includes all ancestor nodes and can lead to incorrect selection. Change the
XPath to use ancestor::o to select only object elements, ensuring the
$position+1 index correctly targets the intended object ancestor. Replace
ancestor::node()[$position + 1] with ancestor::o[$position + 1] to fix this.

Comment on lines +3 to +4
Each [rho][EO-specials] reference (`^.`) should point only to an existing
objects.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix grammar error in documentation.

-Each [rho][EO-specials] reference (`^.`) should point only to an existing
-objects.
+Each [rho][EO-specials] reference (`^.`) should point only to existing
+objects.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Each [rho][EO-specials] reference (`^.`) should point only to an existing
objects.
Each [rho][EO-specials] reference (`^.`) should point only to existing
objects.
🧰 Tools
🪛 LanguageTool

[grammar] ~3-~3: The plural noun “objects” cannot be used with the article “an”. Did you mean “an existing object” or “existing objects”?
Context: ...] reference (^.) should point only to an existing objects. Incorrect: ```eo # Foo. [] > foo [...

(A_NNS)

🤖 Prompt for AI Agents
In src/main/resources/org/eolang/motives/errors/missing-rho-reference.md around
lines 3 to 4, fix the grammar error by changing "objects" to "object" so the
sentence reads "Each [rho][EO-specials] reference (`^.`) should point only to an
existing object."

@h1alexbel
Copy link
Member Author

@h1alexbel let's add the next test pack:

[] > foo
  x > @
    []
      ^.bar > @

it should not complain

@maxonfjvipon why we should not complain in this case? Seems that bar object is missing inside foo object. Am I missing something?

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.

catch missing ^ references

3 participants