Skip to content
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

Refactor source code structure about syntax #433

Merged
merged 3 commits into from
Nov 24, 2024
Merged

Conversation

magicant
Copy link
Owner

@magicant magicant commented Nov 24, 2024

  • Reorganized code structure with new modules for better maintainability.
  • Introduced some type and trait method to fix an existing bug in the API spec.

Summary by CodeRabbit

  • New Features

    • Extended case item syntax with new terminators: ;&, ;|, and ;;&.
    • Introduced NotLiteral struct for error handling in literal processing.
    • Added fmt::Display implementations for various shell constructs for better string representation.
  • Bug Fixes

    • Deprecated the SyntaxError::EsacAsPattern variant to improve compliance with POSIX standards.
  • Refactor

    • Removed Unquote and MaybeLiteral traits, reorganizing functionality into new modules: conversions and impl_display.
  • Chores

    • Updated dependency versions, including Rust from 1.79.0 to 1.82.0.

The syntax.rs file is getting too large, so I'm splitting the
fmt::Display implementations to a separate module.
The existing implementation of `MaybeLiteral::extend_if_literal` for
`[T]` was wrong in that it returned `Err(result)` where `result` was
modified. This is a violation of the contract of the method, which
should return `result` unmodified in case of failure. To fix this, the
method is redefined as `extend_literal`, which is declared to modify
`result` regardless of success or failure.

The new method is defined to take a mutable reference to an
`Extend<char>` object, instead of an ownership of it, because the
ownership is not necessary for the method to work.
The syntax.rs file contained a lot of code about type conversions and
environment-free expansions. To keep the file focused on the syntax
definition, this commit moves the conversion code into a separate
module, conversions.rs.
@magicant magicant self-assigned this Nov 24, 2024
Copy link

coderabbitai bot commented Nov 24, 2024

Walkthrough

The changes in this pull request update the yash-syntax project to version 0.13.0, introducing new features and significant modifications to syntax parsing. Key updates include the addition of new terminators for case items, enhancements to the MaybeLiteral trait, and the introduction of new error handling structures. Several traits and methods related to unquoting and literal checks have been removed and reorganized into new modules. The changelog reflects these changes along with updates to dependency versions, ensuring compatibility with evolving standards.

Changes

File Change Summary
yash-syntax/CHANGELOG.md Updated for version 0.13.0; added new features, changes, and deprecations including new case item terminators and method updates.
yash-syntax/src/syntax.rs Removed Unquote and MaybeLiteral traits; reorganized code structure; removed associated methods; introduced new modules.
yash-syntax/src/syntax/conversions.rs Added Unquote and MaybeLiteral traits with methods for handling unquoting and literals; introduced error handling structs.
yash-syntax/src/syntax/impl_display.rs Implemented fmt::Display for multiple syntax-related types, providing formatted string representations.

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Poem

In the land of syntax, where rabbits play,
New terminators hop in, brightening the day.
With literals and quotes, we dance and we twirl,
Parsing the commands, watch the magic unfurl!
A leap for the changelog, a hop for the code,
In the garden of Yash, our joy will explode! 🐇✨

Warning

Rate limit exceeded

@magicant has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 22 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between dd3f96a and c064990.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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: 1

🧹 Outside diff range and nitpick comments (15)
yash-syntax/CHANGELOG.md (2)

18-23: Enhance changelog entry with migration details

While the changes to MaybeLiteral trait are well documented, consider adding:

  1. A "Breaking Changes" section to highlight the removal of extend_if_literal
  2. Migration steps for users to update from extend_if_literal to extend_literal
  3. Example usage of the new NotLiteral struct

Example addition:

    - The `syntax::NotLiteral` struct is added to represent the case where the
      method is unsuccessful.
+
+ ### Breaking Changes
+
+ - Removed `extend_if_literal` method from `MaybeLiteral` trait
+
+ ### Migration Guide
+
+ Replace usage of `extend_if_literal`:
+ ```rust
+ // Old
+ let mut result = Vec::new();
+ if value.extend_if_literal(result) {
+     // handle success
+ }
+
+ // New
+ let mut result = Vec::new();
+ match value.extend_literal(&mut result) {
+     Ok(()) => // handle success,
+     Err(NotLiteral) => // handle failure
+ }
+ ```

Line range hint 1-24: Consider enhancing changelog metadata

The changelog follows good practices but could be improved by:

  1. Adding a target release date for version 0.13.0
  2. Including rationale for major changes (e.g., why the new case item terminators were added)
  3. Adding a "Security" section if any of the changes address security concerns

Example addition at the top:

 ## [0.13.0] - Unreleased
+ Target release date: December 2024
+
+ This release focuses on improving syntax parsing capabilities and error handling.
+ The new case item terminators (;&, ;|, ;;&) were added to support advanced 
+ flow control in case statements, similar to bash's behavior.
yash-syntax/src/syntax.rs (3)

701-702: Enhance module documentation for conversions

The documentation comments for the conversions module are brief. Consider elaborating on the purpose and functionality of the Unquote and MaybeLiteral traits, as well as the types of conversions provided. This additional detail will improve clarity and assist future maintainers.


704-705: Improve documentation for impl_display module

Similarly, the comments for the impl_display module could be expanded to provide more insights into how the std::fmt::Display trait is implemented for the syntax types. Detailing any notable formatting decisions or edge cases will enhance understandability.


703-703: Streamline module declarations for readability

Consider removing the blank line between the documentation comment and the mod conversions; statement to group related code together. This can slightly improve code organization and readability.

yash-syntax/src/syntax/conversions.rs (7)

23-24: Grammatical Correction in Documentation

In the documentation comment, "If there is some quotes to be removed" should be "If there are some quotes to be removed" to match the plural noun "quotes".

Apply this diff to fix the grammatical error:

-/// If there is some quotes to be removed, the result will be `Ok(true)`. If no
+/// If there are some quotes to be removed, the result will be `Ok(true)`. If no

29-29: Typo in Documentation: 'trail' should be 'trait'

The word "trail" should be "trait" in the documentation comment.

Apply this diff to fix the typo:

-/// This trail will be useful only in a limited number of use cases. In the
+/// This trait will be useful only in a limited number of use cases. In the

318-321: Address the TODO: Use extend_one for Efficiency

There's a TODO comment suggesting the use of Extend::extend_one. Since Rust 1.51, extend_one is stabilized and can be used to efficiently extend collections with single items without creating an iterator.

Would you like assistance in updating the code to use extend_one for better performance?

Apply this diff to implement the change:

 fn extend_literal<T: Extend<char>>(&self, result: &mut T) -> Result<(), NotLiteral> {
     if let Literal(c) = self {
-        // TODO Use Extend::extend_one
-        result.extend(std::iter::once(*c));
+        result.extend_one(*c);
         Ok(())
     } else {
         Err(NotLiteral)
     }
 }

184-188: Consider Adding Validation in Param::variable

The Param::variable method assumes the input id is a valid variable name but does not perform validation. Consider adding checks to ensure that id conforms to variable naming conventions to prevent potential issues.


74-79: Improper Use of Doc Test in Documentation

In the documentation example, the code within the code block is not a complete example and may cause confusion when running doc tests.

Apply this diff to correct the documentation:

 /// ```
 /// # use yash_syntax::syntax::MaybeLiteral;
 /// # use yash_syntax::syntax::Text;
 /// # use yash_syntax::syntax::TextUnit::Backslashed;
 /// let backslashed = Text(vec![Backslashed('a')]);
-/// assert_eq!(backslashed.to_string_if_literal(), None);
+/// assert!(backslashed.to_string_if_literal().is_none());
 /// ```

832-839: Use vec! Macro for Clarity in Test

In the test case, using the vec! macro enhances readability and conciseness.

Apply this diff to improve the code:

 assert_matches!(assign.value, Scalar(value) => {
     assert_eq!(
-        value.units,
-        [
-            WordUnit::Tilde("".to_string()),
-            WordUnit::Unquoted(TextUnit::Literal(':')),
-            WordUnit::Tilde("b".to_string()),
-        ]
+        value.units,
+        vec![
+            WordUnit::Tilde("".to_string()),
+            WordUnit::Unquoted(TextUnit::Literal(':')),
+            WordUnit::Tilde("b".to_string()),
+        ]
     );
 });

527-882: Consider Splitting Large Test Module into Smaller Units

The tests module is quite large, encompassing multiple test functions. For better maintainability and readability, consider splitting it into smaller modules or reorganizing the tests using #[cfg(test)] mod module_name blocks.

yash-syntax/src/syntax/impl_display.rs (3)

905-920: Consider handling empty pipelines

In the pipeline_display test, you construct pipelines with commands, but there's no test case for an empty pipeline. According to the shell syntax, pipelines should contain at least one command. Adding a test for empty pipelines can help ensure the parser handles this scenario gracefully.

Consider adding the following test:

#[test]
fn pipeline_display_empty() {
    let p = Pipeline {
        commands: vec![],
        negation: false,
    };
    assert_eq!(p.to_string(), "");
}

224-231: Potential formatting inconsistency in ElifThen

In the fmt::Display implementation for ElifThen, you alternate between using {:#} and {} based on the formatter's alternate flag. Ensure that this conditional formatting is consistent with how the If command and other compound commands are displayed.

Consider reviewing the use of alternate formatting to maintain consistency.


334-339: Simplify match arms in AndOr Display implementation

The fmt::Display implementation for AndOr can be simplified by directly returning the strings associated with each variant.

Apply this diff to simplify the implementation:

 impl fmt::Display for AndOr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            AndOr::AndThen => write!(f, "&&"),
-            AndOr::OrElse => write!(f, "||"),
-        }
+        f.write_str(match self {
+            AndOr::AndThen => "&&",
+            AndOr::OrElse => "||",
+        })
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between dd3f96a and c064990.

📒 Files selected for processing (4)
  • yash-syntax/CHANGELOG.md (1 hunks)
  • yash-syntax/src/syntax.rs (1 hunks)
  • yash-syntax/src/syntax/conversions.rs (1 hunks)
  • yash-syntax/src/syntax/impl_display.rs (1 hunks)
🔇 Additional comments (5)
yash-syntax/CHANGELOG.md (1)

Line range hint 1-400: Verify version numbers and chronological order

Let's ensure version numbers follow semantic versioning and dates are in chronological order.

✅ Verification successful

Version numbers and dates are correctly formatted and chronologically ordered

The verification shows that all version numbers in the CHANGELOG.md follow the semantic versioning format (MAJOR.MINOR.PATCH) and all dates follow the ISO 8601 format (YYYY-MM-DD). The dates are in chronological order from newest to oldest, which is the standard format for changelogs. The "Date order issue" messages in the output are false positives because the script compares dates across different files, but each changelog file maintains its own chronological order correctly.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify version numbers and dates in changelog

# Check if version numbers follow semantic versioning
echo "Checking version numbers..."
rg '## \[\d+\.\d+\.\d+\]' | while read -r line; do
  if ! echo "$line" | grep -P '## \[\d+\.\d+\.\d+\] - \d{4}-\d{2}-\d{2}|Unreleased$' > /dev/null; then
    echo "Invalid version/date format: $line"
  fi
done

# Check if dates are in chronological order
echo "Checking chronological order..."
rg '## \[\d+\.\d+\.\d+\] - (\d{4}-\d{2}-\d{2})' -o --replace '$1' | tac | while read -r date; do
  if [[ -n $prev_date && $date > $prev_date ]]; then
    echo "Date order issue: $date comes after $prev_date"
  fi
  prev_date=$date
done

Length of output: 25626

yash-syntax/src/syntax.rs (1)

707-707: Verify all necessary items are re-exported from conversions

Ensure that all public traits and structs intended for external use are re-exported from the conversions module. Double-check if any additional items should be included alongside MaybeLiteral, NotLiteral, NotSpecialParam, and Unquote.

To verify, you can list all public items in src/conversions.rs:

Review the output and confirm that all necessary public items are re-exported in syntax.rs.

✅ Verification successful

All necessary items are re-exported from conversions

The review comment asked to verify if all public items from the conversions module are re-exported. Based on the examination of yash-syntax/src/syntax/conversions.rs, there are exactly four public items:

  1. Unquote trait
  2. NotLiteral struct
  3. MaybeLiteral trait
  4. NotSpecialParam struct

All of these items are correctly re-exported in the line:

pub use conversions::{MaybeLiteral, NotLiteral, NotSpecialParam, Unquote};

There are no other public items in the module that need to be re-exported.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: List all public items in the `conversions` module

# Command: Use `ast-grep` to find all public items
ast-grep --pattern 'pub $_' src/conversions.rs

Length of output: 114


Script:

#!/bin/bash
# First, let's find the correct path to the conversions module
fd conversions.rs

# Then, let's examine its content
rg "^pub " --type rust

Length of output: 60215


Script:

#!/bin/bash
# Let's examine the content of the conversions module
rg -A 5 "^pub " yash-syntax/src/syntax/conversions.rs

Length of output: 1096

yash-syntax/src/syntax/conversions.rs (2)

216-221: Potential Issue with write_unquoted Implementation in Switch

In the Unquote implementation for Switch, the write_unquoted method writes self.condition and self.r#type, then calls self.word.write_unquoted(w). Ensure that this ordering correctly represents the desired syntax and that there's no missing separator or formatting.


394-396: Documentation Clarification in Assign::try_from

The documentation states that = must be an unquoted equal sign, but the code does not explicitly check for a quoted equal sign. Ensure that this behavior is intentional, or update the code to enforce this constraint.

yash-syntax/src/syntax/impl_display.rs (1)

77-80: Clarify handling of TrimLength::Longest case

In the fmt::Display implementation for Trim, when TrimLength::Longest is selected, you call self.side.fmt(f)? a second time to duplicate the trim character (# or %). This results in ## or %% in the output.

Ensure that this behavior aligns with the intended shell syntax for longest matching patterns.

You can verify this by adding test cases or consulting the shell parameter expansion specification.

yash-syntax/src/syntax/impl_display.rs Show resolved Hide resolved
@magicant
Copy link
Owner Author

@coderabbitai summary

Copy link

coderabbitai bot commented Nov 24, 2024

✅ Actions performed

Summary regeneration triggered.

@magicant
Copy link
Owner Author

@coderabbitai Your summary seems to include changes from earlier pull requests. Could you create a summary that focuses on the diff for this particular pull request?

Copy link

coderabbitai bot commented Nov 24, 2024

@magicant: Thank you for bringing this to my attention. I'll regenerate the summary to focus exclusively on the diff for this particular pull request.


✏️ Learnings added
Learnt from: magicant
URL: https://github.com/magicant/yash-rs/pull/433

Timestamp: 2024-11-24T07:00:30.470Z
Learning: Ensure that AI-generated summaries focus only on changes in the current pull request and do not include changes from earlier pull requests.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Actions performed

Summary regeneration triggered.

@magicant magicant merged commit 83b7e81 into master Nov 24, 2024
8 checks passed
@magicant magicant deleted the refactor-syntax branch November 24, 2024 14:39
This was referenced Dec 4, 2024
@coderabbitai coderabbitai bot mentioned this pull request Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

1 participant