feat: resolve rule id for ScanResult#1707
Conversation
WalkthroughThe 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 Changes
Sequence DiagramsequenceDiagram
participant CombinedScan
participant ScanResultInner
participant ScanResult
CombinedScan->>ScanResultInner: Populate scan data
ScanResultInner->>ScanResult: Convert using into_result()
ScanResult-->>CombinedScan: Return processed scan results
Poem
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov ReportAttention: Patch coverage is
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. |
There was a problem hiding this comment.
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.
ScanResultInneruses indexes referencingRuleConfig. It is unclear if there's any plan to handle invalid indexes. Documenting or enforcing index validity could help prevent potential panics when converting toScanResult.crates/cli/src/scan.rs (1)
154-157: Refactor for consistency between diffs and matches processing.Here,
match_rule_diff_on_fileis invoked only forscanned.diffs. For clarity, consider grouping or naming the calls in a similar manner when handlingscanned.matches.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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:
- The indices are populated during scanning by
CombinedScanwhich owns the rules vector CombinedScan::new()constructs the rules vector and maintains it throughout its lifetime- The indices used in
diffsandmatchesare only created withinCombinedScan's scan operation, which has access to its own rules vector length - The
get_rule()method is only called throughinto_result()using indices that were created by the sameCombinedScaninstance
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
169a2f9 to
513346e
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
crates/config/src/combined.rs (2)
9-13: Improved type safety with direct rule references!The restructured
ScanResultwith direct references toRuleConfiginstead 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
'tand'rto clarify their purposes, as they play a crucial role in ensuring reference validity.
24-54: Consider simplifying unused suppression handlingThe 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
📒 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
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
crates/config/src/combined.rs (2)
29-43: Consider consistent sorting for all diffsCurrently, 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 casesThe test suite could be strengthened by adding the following test cases:
- Verify the order of results when multiple matches are found
- Test the behavior when
separate_fix=true- 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
📒 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:
- The sorting of diffs with unused suppressions
- 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
Summary by CodeRabbit
Code Improvements
ScanResultstructure for improved type safety and clarity.Error Handling
LspErrorenum for more structured error management.Performance