Skip to content

feat: resolve rule id for ScanResult#1707

Merged
HerringtonDarkholme merged 3 commits into
mainfrom
feat-fixable-unused
Dec 29, 2024
Merged

feat: resolve rule id for ScanResult#1707
HerringtonDarkholme merged 3 commits into
mainfrom
feat-fixable-unused

Conversation

@HerringtonDarkholme

@HerringtonDarkholme HerringtonDarkholme commented Dec 28, 2024

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Code Improvements

    • Refined rule scanning and matching process for enhanced clarity.
    • Updated ScanResult structure for improved type safety and clarity.
    • Streamlined internal logic for handling scan matches.
  • Error Handling

    • Introduced new LspError enum for more structured error management.
  • Performance

    • Simplified rule retrieval and processing mechanisms for better efficiency.

@coderabbitai

coderabbitai Bot commented Dec 28, 2024

Copy link
Copy Markdown
Contributor

Walkthrough

The pull request introduces significant modifications to the rule scanning and result processing mechanisms across multiple crates. The changes primarily focus on restructuring how rules and matches are handled, moving from an index-based approach to direct rule references. The modifications affect the scan.rs, combined.rs, and lib.rs files, updating the data structures and methods to improve type safety, simplify logic, and enhance the overall clarity of the code.

Changes

File Changes
crates/cli/src/scan.rs - Updated consume_items method for direct rule references
- Modified match_rule_diff_on_file method signature and parameter order
- Changed default rule pattern in unused_suppression_rule_config
crates/config/src/combined.rs - Modified ScanResult struct with new lifetime and generic parameters
- Introduced ScanResultInner struct
- Updated scan method to return new ScanResult type
- Added into_result method for converting scan results
crates/lsp/src/lib.rs - Updated get_diagnostics method to directly use rule references
- Added new LspError enum for error handling

Sequence Diagram

sequenceDiagram
    participant CombinedScan
    participant ScanResultInner
    participant ScanResult
    
    CombinedScan->>ScanResultInner: Populate scan data
    ScanResultInner->>ScanResult: Convert using into_result()
    ScanResult-->>CombinedScan: Return processed scan results
Loading

Poem

🐰 A Rabbit's Ode to Code Refactoring 🔧
Rules dance with matches, no index in sight,
Lifetimes and generics, now shining so bright!
Scanning simplified, with references clear,
Our code leaps forward without a fear
Refactoring magic, a programmer's delight! 🚀


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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

@codecov

codecov Bot commented Dec 28, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 90.47619% with 6 lines in your changes missing coverage. Please review.

Project coverage is 87.34%. Comparing base (a4510c1) to head (8091f51).
Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
crates/cli/src/scan.rs 66.66% 3 Missing ⚠️
crates/config/src/combined.rs 96.22% 2 Missing ⚠️
crates/lsp/src/lib.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1707      +/-   ##
==========================================
+ Coverage   87.24%   87.34%   +0.09%     
==========================================
  Files          96       96              
  Lines       15449    15477      +28     
==========================================
+ Hits        13479    13518      +39     
+ Misses       1970     1959      -11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
crates/config/src/combined.rs (1)

15-21: Consider clarifying the inner type or adding docs for future maintenance.

ScanResultInner uses indexes referencing RuleConfig. It is unclear if there's any plan to handle invalid indexes. Documenting or enforcing index validity could help prevent potential panics when converting to ScanResult.

crates/cli/src/scan.rs (1)

154-157: Refactor for consistency between diffs and matches processing.

Here, match_rule_diff_on_file is invoked only for scanned.diffs. For clarity, consider grouping or naming the calls in a similar manner when handling scanned.matches.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1c68280 and be37672.

📒 Files selected for processing (3)
  • crates/cli/src/scan.rs (4 hunks)
  • crates/config/src/combined.rs (5 hunks)
  • crates/lsp/src/lib.rs (1 hunks)
🔇 Additional comments (7)
crates/config/src/combined.rs (3)

9-13: Great addition of lifetime parameters to make rule references more explicit.

By including both 't and 'r, you ensure that nodes and rules safely reference their respective data. This promotes clarity and type safety, reducing the need to rely on index-based lookups.


191-195: Return type changes and rule resolution logic look consistent.

The transition to returning ScanResult in scan and calling into_result is coherent with the new design. get_rule returning an &'r RuleConfig<L> is clear—just ensure all indexes remain valid.

Also applies to: 247-247, 250-250


23-41: Validate index lookups in into_result or confirm constraints.

While self.diffs and self.matches are resolved by combined.get_rule(idx), there's no explicit check if idx is valid. If the codebase always ensures correctness, consider at least a debug assertion or doc comment to clarify.

Generate a script to see if any code passes an out-of-range index to get_rule:

✅ Verification successful

Let me gather more information about how the indices are populated.


Let me try a different approach to find the struct definitions and index population.


Based on the code analysis, I can now provide a final response:

Index safety is guaranteed by CombinedScan's construction

The indices used in ScanResultInner are safe because:

  1. The indices are populated during scanning by CombinedScan which owns the rules vector
  2. CombinedScan::new() constructs the rules vector and maintains it throughout its lifetime
  3. The indices used in diffs and matches are only created within CombinedScan's scan operation, which has access to its own rules vector length
  4. The get_rule() method is only called through into_result() using indices that were created by the same CombinedScan instance

While an explicit bounds check could add defense-in-depth, it's not strictly necessary as the indices are internally managed and cannot be created outside the scanning process.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for usage of `get_rule` calls to check index references
rg --context 3 "get_rule\s*\(" 

Length of output: 2779


Script:

#!/bin/bash
# Search for where diffs and matches are populated with indices
ast-grep --pattern 'struct ScanResultInner {
  $$$
}'

# Also check the implementation of CombinedScan
ast-grep --pattern 'struct CombinedScan {
  $$$
}'

Length of output: 108


Script:

#!/bin/bash
# Search for struct definitions and their fields
rg --type rust -A 10 "struct (ScanResultInner|CombinedScan)" 

# Look for where indices might be populated
rg --type rust -B 3 -A 3 "diffs.*=|matches.*="

Length of output: 23441

crates/lsp/src/lib.rs (1)

208-208: Directly iterating over (rule, ms) improves code readability.

Removing the need to call scan.get_rule(id) inside the loop is a welcome simplification.

crates/cli/src/scan.rs (3)

182-182: Switch to {"any": []} effectively broadens rule matching scope.

Previously, {"pattern": "a"} was a limited placeholder. Using {"any":[]} may better reflect a generic match.


271-271: Iterating (rule, matches) fosters type safety.

This approach avoids potential index-based errors by directly referencing the RuleConfig.


303-308: Prefer the new tuple order for clarity in match_rule_diff_on_file.

Reversing the parameter order is consistent with ScanResult storing (rule, NodeMatch). This helps avoid confusion regarding which element is the RuleConfig.

and also make unused comment fixable. fix #1624

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
crates/config/src/combined.rs (2)

9-13: Improved type safety with direct rule references!

The restructured ScanResult with direct references to RuleConfig instead of indices is a significant improvement:

  • Eliminates potential index-out-of-bounds errors
  • Provides better compile-time guarantees
  • Makes the relationship between rules and matches more explicit

Consider documenting the lifetime parameters 't and 'r to clarify their purposes, as they play a crucial role in ensuring reference validity.


24-54: Consider simplifying unused suppression handling

The unused suppression handling logic could be extracted into a separate method for better readability and maintainability.

Consider refactoring like this:

 impl<'t, D: Doc> ScanResultInner<'t, D> {
+  fn handle_unused_suppressions<'r, L: Language>(
+    unused: Vec<NodeMatch<'t, D>>,
+    rule: &'r RuleConfig<L>,
+    separate_fix: bool,
+  ) -> (Vec<(&'r RuleConfig<L>, NodeMatch<'t, D>)>, Vec<(&'r RuleConfig<L>, Vec<NodeMatch<'t, D>>)>) {
+    if separate_fix {
+      (unused.into_iter().map(|nm| (rule, nm)).collect(), vec![])
+    } else {
+      let mut supprs = unused;
+      supprs.sort_unstable_by_key(|nm| nm.range().start);
+      (vec![], vec![(rule, supprs)])
+    }
+  }
+
   pub fn into_result<'r, L: Language>(
     self,
     combined: &CombinedScan<'r, L>,
     separate_fix: bool,
   ) -> ScanResult<'t, 'r, D, L> {
     let mut diffs: Vec<_> = self
       .diffs
       .into_iter()
       .map(|(idx, nm)| (combined.get_rule(idx), nm))
       .collect();
     let mut matches: Vec<_> = self
       .matches
       .into_iter()
       .map(|(idx, nms)| (combined.get_rule(idx), nms))
       .collect();
     if let Some(rule) = combined.unused_suppression_rule {
-      if separate_fix {
-        diffs.extend(self.unused_suppressions.into_iter().map(|nm| (rule, nm)));
-        diffs.sort_unstable_by_key(|(_, nm)| nm.range().start);
-      } else {
-        let mut supprs = self.unused_suppressions;
-        supprs.sort_unstable_by_key(|nm| nm.range().start);
-        matches.push((rule, supprs));
-      }
+      let (mut new_diffs, mut new_matches) = 
+        Self::handle_unused_suppressions(self.unused_suppressions, rule, separate_fix);
+      diffs.append(&mut new_diffs);
+      matches.append(&mut new_matches);
     }
     ScanResult {
       diffs,
       matches,
       unused_suppressions: vec![],
     }
   }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between be37672 and 513346e.

📒 Files selected for processing (2)
  • crates/cli/src/scan.rs (4 hunks)
  • crates/config/src/combined.rs (7 hunks)
🔇 Additional comments (5)
crates/config/src/combined.rs (2)

15-21: Well-structured intermediate representation!

Good separation of concerns between internal index-based storage and external reference-based API.


142-143: Clean integration of unused suppression rule handling!

The addition of the unused suppression rule field and its setter method provides a clean way to handle suppression rules.

Also applies to: 174-176

crates/cli/src/scan.rs (3)

149-150: Improved unused suppression rule pattern!

The change to use {"any": []} instead of {"pattern": "a"} better represents the semantic meaning of unused suppressions, as it's not looking for a specific pattern but rather identifying unused directives.

Also applies to: 183-187


155-158: Clean adaptation to new ScanResult API!

The code cleanly adapts to the new reference-based ScanResult structure, maintaining type safety and clarity.

Also applies to: 304-309


Line range hint 324-327: Tests properly updated for new API!

The test assertions have been correctly updated to handle the new tuple structure of matches.

Let's verify test coverage for the new unused suppression handling:

Also applies to: 346-349

✅ Verification successful

Test coverage for unused suppression handling is present and adequate

The test coverage for unused suppression scenarios is verified through the test_non_used_suppression test case in crates/cli/src/scan.rs. The test includes scenarios for:

  • Regular logging without suppression
  • Unused suppression with rule 'test'
  • Multiple suppressions with the same rule
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check test coverage for unused suppression scenarios
rg -l 'unused.*suppression' crates/cli/src/scan.rs crates/config/src/combined.rs | xargs -I {} rg -A 5 '#\[test\]' {}

Length of output: 1641

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
crates/config/src/combined.rs (2)

29-43: Consider consistent sorting for all diffs

Currently, sorting by range start is only applied to unused suppressions. Consider applying consistent sorting to all diffs to maintain a predictable order in the output.

 let mut diffs: Vec<_> = self
   .diffs
   .into_iter()
   .map(|(idx, nm)| (combined.get_rule(idx), nm))
   .collect();
+diffs.sort_unstable_by_key(|(_, nm)| nm.range().start);
 if let Some(rule) = combined.unused_suppression_rule {
   if separate_fix {
     diffs.extend(self.unused_suppressions.into_iter().map(|nm| (rule, nm)));
-    diffs.sort_unstable_by_key(|(_, nm)| nm.range().start);
   } else {
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 41-42: crates/config/src/combined.rs#L41-L42
Added lines #L41 - L42 were not covered by tests


362-370: Enhance test coverage for edge cases

The test suite could be strengthened by adding the following test cases:

  1. Verify the order of results when multiple matches are found
  2. Test the behavior when separate_fix=true
  3. Test the interaction between fixes and unused suppressions

Here's a suggested test case structure:

#[test]
fn test_separate_fix_with_unused_suppression() {
    let source = r#"
    console.log('first') // ast-grep-ignore: test
    console.log('second')
    console.log('third') // ast-grep-ignore: not-test
    "#;
    let root = TypeScript::Tsx.ast_grep(source);
    let rule = create_rule();
    let mut scan = CombinedScan::new(vec![&rule]);
    scan.set_unused_suppression_rule(&rule);
    let pre = scan.find(&root);
    let scanned = scan.scan(&root, pre, true);
    
    // Verify diffs are sorted by position
    assert_eq!(scanned.diffs.len(), 3);
    let texts: Vec<_> = scanned.diffs
        .iter()
        .map(|(_, nm)| nm.text())
        .collect();
    assert_eq!(texts, vec![
        "console.log('first')",
        "console.log('second')",
        "console.log('third')",
    ]);
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 513346e and 8091f51.

📒 Files selected for processing (1)
  • crates/config/src/combined.rs (8 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
crates/config/src/combined.rs

[warning] 41-42: crates/config/src/combined.rs#L41-L42
Added lines #L41 - L42 were not covered by tests

🔇 Additional comments (3)
crates/config/src/combined.rs (3)

9-21: Well-structured type-safe implementation!

The new design with direct rule references instead of indices improves type safety and makes the relationship between rules and matches more explicit. The separation into ScanResult and ScanResultInner provides a clean abstraction for the conversion process.


Line range hint 9-370: Overall implementation looks solid!

The changes successfully improve type safety by moving from indices to direct rule references while maintaining good separation of concerns. The code is well-structured and mostly well-tested, with only minor suggestions for improvements.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 41-42: crates/config/src/combined.rs#L41-L42
Added lines #L41 - L42 were not covered by tests


24-54: Add test coverage for separate fix handling

The into_result implementation has untested code paths, specifically when separate_fix=true. Consider adding test cases to cover:

  1. The sorting of diffs with unused suppressions
  2. The behavior when separate_fix=true
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 41-42: crates/config/src/combined.rs#L41-L42
Added lines #L41 - L42 were not covered by tests

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.

1 participant