-
-
Notifications
You must be signed in to change notification settings - Fork 254
Implement LSP rule reloading with decoupled CLI logic #2154
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
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2154 +/- ##
==========================================
- Coverage 86.07% 86.02% -0.06%
==========================================
Files 107 107
Lines 16795 16900 +105
==========================================
+ Hits 14457 14538 +81
- Misses 2338 2362 +24 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Co-authored-by: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com>
Co-authored-by: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation duplicates logic of finding rules. I want to decouple rule finding from lsp crate.
Please pass a find_rule closure to lsp Backend
. And resue the logic in ast-grep-cli
@copilot please resolve code review feedback |
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis change introduces live rule reloading to the LSP server. It adds a Changes
Sequence Diagram(s)sequenceDiagram
participant LSP Client
participant LSP Server (Backend)
participant File System
LSP Client->>LSP Server (Backend): Initialize
LSP Server (Backend)->>LSP Client: Register file watchers for config files
File System-->>LSP Server (Backend): Notify config file change
LSP Server (Backend)->>LSP Server (Backend): Call rule_finder closure
LSP Server (Backend)->>LSP Server (Backend): Reload rules, update state
LSP Server (Backend)->>LSP Client: Republish diagnostics for open files
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes were found. Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧠 Learnings (6)📓 Common learnings
📚 Learning: when `find_rules` returns `(rulecollection, rulestats)`, we should handle both elements and ...
Applied to files:
📚 Learning: in the wasm build of tree-sitter, `parser::new()` returns a `result` type rather than directly retur...
Applied to files:
📚 Learning: the `overwriteresult` struct in `crates/cli/src/utils/rule_overwrite.rs` will have more override opt...
Applied to files:
📚 Learning: the `language` trait in ast-grep already has a `clone` bound, so traits that extend `language` (like...
Applied to files:
📚 Learning: the `language` trait in ast-grep already has a `clone` bound (`trait language: clone + 'static`), so...
Applied to files:
🔇 Additional comments (11)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Co-authored-by: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com>
I've successfully decoupled the rule finding logic from the LSP crate as requested. The changes include:
The LSP now reuses the CLI's robust rule finding implementation, ensuring consistency and eliminating duplication. Commit: 9618c72
Code review feedback has been resolved. The rule finding logic is now decoupled from the LSP crate and reuses the CLI implementation through a closure-based approach. All tests pass and the changes maintain the existing functionality while eliminating code duplication. Commit: 9618c72 |
@copilot please address the comments |
Co-authored-by: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please further address comments. Also apply cargo fmt and clippy before commit. @copilot
Please further address comments. Also apply cargo fmt and clippy before commit. @copilot |
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this 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
♻️ Duplicate comments (8)
crates/cli/src/config.rs (2)
219-220
: Remove unnecessary empty lineTwo consecutive empty lines are not needed here. Please remove one.
- - +
92-102
: Fix formatting issues with cargo fmtThe pipeline indicates formatting issues in this code segment. Please run
cargo fmt
to fix the code style.Additionally, per the previous review comment, consider whether this method should be moved to
crates/cli/src/lsp.rs
since it's specifically for LSP usage.#!/bin/bash # Verify if this method is only used by LSP rg -A 2 "make_rule_finder" --type rustcrates/lsp/Cargo.toml (1)
29-30
: Verify ifignore
andserde_yaml
dependencies are usedPrevious review comments indicated these dependencies might not be used. Please verify if they are actually needed.
#!/bin/bash # Check if 'ignore' crate is used in the lsp crate echo "Checking usage of 'ignore' crate:" rg "use ignore::" crates/lsp/src/ rg "ignore::" crates/lsp/src/ echo -e "\nChecking usage of 'serde_yaml' in the lsp crate:" rg "use serde_yaml" crates/lsp/src/ rg "serde_yaml::" crates/lsp/src/crates/lsp/src/lib.rs (5)
338-349
: Reduce indentation by flattening nested conditionsThe nested if-let can be flattened for better readability.
- if let Ok(rules) = self.rules.read() { - if let Some(note) = rules.get_rule(id).and_then(|r| r.note.clone()) { - let start = diagnostic.range.start; - let end = diagnostic.range.end; - let atom = self - .interner - .entry(id.clone()) - .or_insert_with(|| Arc::new(note.clone())) - .clone(); - notes.insert((start.line, start.character, end.line, end.character), atom); - } - } + let Ok(rules) = self.rules.read() else { continue }; + let Some(note) = rules.get_rule(id).and_then(|r| r.note.clone()) else { continue }; + let start = diagnostic.range.start; + let end = diagnostic.range.end; + let atom = self + .interner + .entry(id.clone()) + .or_insert_with(|| Arc::new(note.clone())) + .clone(); + notes.insert((start.line, start.character, end.line, end.character), atom);
717-728
: Reduce indentation in the loopFlatten the nested if-let structure for better readability.
for uri_str in open_files { - if let Ok(uri) = uri_str.parse::<Uri>() { - if let Some(mut versioned) = self.map.get_mut(&uri_str) { - // Republish diagnostics for this file - if let Some(diagnostics) = self.get_diagnostics(&uri, &versioned) { - versioned.notes = self.build_notes(&diagnostics); - self - .client - .publish_diagnostics(uri, diagnostics, Some(versioned.version)) - .await; - } - } - } + let Ok(uri) = uri_str.parse::<Uri>() else { continue }; + let Some(mut versioned) = self.map.get_mut(&uri_str) else { continue }; + + // Republish diagnostics for this file + let Some(diagnostics) = self.get_diagnostics(&uri, &versioned) else { continue }; + versioned.notes = self.build_notes(&diagnostics); + self + .client + .publish_diagnostics(uri, diagnostics, Some(versioned.version)) + .await; }
164-177
: Remove redundant file type checkingThe file watcher registration already specifies which files to watch (
*.yml
patterns). When this handler is called, it means a relevant file has changed, so just reload without additional filtering.- // Check if any of the changed files are configuration files - let mut config_changed = false; - for change in ¶ms.changes { - let uri = &change.uri; - if let Some(path) = uri.to_file_path() { - if let Some(filename) = path.file_name().and_then(|n| n.to_str()) { - if filename == "sgconfig.yml" || filename.ends_with(".yml") || filename.ends_with(".yaml") { - config_changed = true; - break; - } - } - } - } - - if config_changed { + // File watcher already filters for relevant files, so just reload + {
307-313
: Extract URI to path conversion logicThis URI to path conversion logic should be abstracted into a helper method for reusability.
+ fn uri_to_relative_path(&self, uri: &Uri) -> Option<PathBuf> { + let absolute_path = uri.to_file_path().ok()?; + let path = if let Ok(p) = absolute_path.strip_prefix(&self.base) { + p.to_path_buf() + } else { + absolute_path + }; + Some(path) + } + fn get_diagnostics( &self, uri: &Uri, versioned: &VersionedAst<StrDoc<L>>, ) -> Option<Vec<Diagnostic>> { - let absolute_path = uri.to_file_path()?; - let path = if let Ok(p) = absolute_path.strip_prefix(&self.base) { - p - } else { - &absolute_path - }; + let path = self.uri_to_relative_path(uri)?; let rules = self.rules.read().ok()?; - let rule_refs = rules.for_path(path); + let rule_refs = rules.for_path(&path);
633-641
: Fix file watcher patterns
- The
sgconfig.yml
pattern is redundant since*.yml
already includes it- Add
*.yaml
pattern to support both YAML file extensions- let config_watcher = FileSystemWatcher { - glob_pattern: GlobPattern::String("**/sgconfig.yml".to_string()), - kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete), - }; - - let rule_watcher = FileSystemWatcher { + let yml_watcher = FileSystemWatcher { glob_pattern: GlobPattern::String("**/*.yml".to_string()), kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete), }; + + let yaml_watcher = FileSystemWatcher { + glob_pattern: GlobPattern::String("**/*.yaml".to_string()), + kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete), + };Also update the registration to include both watchers:
serde_json::to_value(DidChangeWatchedFilesRegistrationOptions { - watchers: vec![config_watcher, rule_watcher], + watchers: vec![yml_watcher, yaml_watcher], }).map_err(|e| tower_lsp_server::jsonrpc::Error::invalid_params(e.to_string()))?
🧹 Nitpick comments (2)
crates/cli/src/config.rs (1)
248-249
: Remove unnecessary empty lineTwo consecutive empty lines are not needed here. Please remove one to maintain consistent formatting.
- - +crates/lsp/tests/basic.rs (1)
319-352
: Good test coverage for configuration file changesThe test correctly verifies the handling of watched file changes. Consider making the sleep duration configurable or using a more deterministic approach if possible.
- // Give some time for processing - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + // Give some time for async processing + // Consider using a more deterministic approach if the test becomes flaky + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Cargo.lock
is excluded by!**/*.lock
📒 Files selected for processing (5)
crates/cli/src/config.rs
(4 hunks)crates/cli/src/lsp.rs
(1 hunks)crates/lsp/Cargo.toml
(1 hunks)crates/lsp/src/lib.rs
(9 hunks)crates/lsp/tests/basic.rs
(3 hunks)
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1500
File: crates/cli/src/config.rs:60-60
Timestamp: 2024-10-08T18:41:57.037Z
Learning: When `find_rules` returns `(RuleCollection<SgLang>, RuleStats)`, we should handle both elements and add logging of `RuleStats` in the callers, such as in `crates/cli/src/verify.rs` and `crates/cli/src/lsp.rs`.
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1500
File: crates/cli/src/config.rs:60-60
Timestamp: 2024-10-05T19:26:12.834Z
Learning: When `find_rules` returns `(RuleCollection<SgLang>, RuleStats)`, we should handle both elements and add logging of `RuleStats` in the callers, such as in `crates/cli/src/verify.rs` and `crates/cli/src/lsp.rs`.
📚 Learning: when `find_rules` returns `(rulecollection, rulestats)`, we should handle both elements and ...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1500
File: crates/cli/src/config.rs:60-60
Timestamp: 2024-10-05T19:26:12.834Z
Learning: When `find_rules` returns `(RuleCollection<SgLang>, RuleStats)`, we should handle both elements and add logging of `RuleStats` in the callers, such as in `crates/cli/src/verify.rs` and `crates/cli/src/lsp.rs`.
Applied to files:
crates/cli/src/lsp.rs
crates/cli/src/config.rs
crates/lsp/tests/basic.rs
crates/lsp/src/lib.rs
📚 Learning: the `overwriteresult` struct in `crates/cli/src/utils/rule_overwrite.rs` will have more override opt...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1546
File: crates/cli/src/utils/rule_overwrite.rs:118-121
Timestamp: 2024-10-22T13:56:44.052Z
Learning: The `OverwriteResult` struct in `crates/cli/src/utils/rule_overwrite.rs` will have more override options added in the future, so it should be retained even if it currently only contains an `Option<Severity>`.
Applied to files:
crates/cli/src/lsp.rs
crates/cli/src/config.rs
📚 Learning: the `expand_end` function in `crates/config/src/fixer.rs` should return `node.range().end` instead o...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#843
File: crates/config/src/fixer.rs:167-181
Timestamp: 2024-10-08T18:41:57.037Z
Learning: The `expand_end` function in `crates/config/src/fixer.rs` should return `node.range().end` instead of `node.range().start` to correctly calculate the end of the range.
Applied to files:
crates/cli/src/lsp.rs
📚 Learning: `projectconfig::setup` returns a `result>`, so wrapping the result in `ok()` i...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1560
File: crates/cli/src/scan.rs:405-407
Timestamp: 2024-10-28T03:46:27.850Z
Learning: `ProjectConfig::setup` returns a `Result<Result<ProjectConfig>>`, so wrapping the result in `Ok()` is unnecessary.
Applied to files:
crates/cli/src/lsp.rs
crates/cli/src/config.rs
📚 Learning: in the `ast-grep-cli` application code, avoid unnecessary abstractions; functions don't need to acce...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1546
File: crates/cli/src/utils/rule_overwrite.rs:76-91
Timestamp: 2024-10-22T14:04:15.734Z
Learning: In the `ast-grep-cli` application code, avoid unnecessary abstractions; functions don't need to accept iterators instead of `Vec` if not required.
Applied to files:
crates/cli/src/lsp.rs
crates/lsp/Cargo.toml
crates/cli/src/config.rs
📚 Learning: in the `sg` cli application, the `-l` or `--lang` command argument depends on the configuration and ...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1560
File: crates/cli/src/lib.rs:0-0
Timestamp: 2024-10-28T03:45:43.551Z
Learning: In the `sg` CLI application, the `-l` or `--lang` command argument depends on the configuration and project being set up, so the configuration cannot be parsed using clap's `App` struct at that point.
Applied to files:
crates/cli/src/lsp.rs
crates/cli/src/config.rs
📚 Learning: ast-grep requires rust 1.65 or newer. it's acceptable to use syntax and features introduced in rust ...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1497
File: crates/cli/src/utils/mod.rs:174-175
Timestamp: 2024-09-29T21:59:50.675Z
Learning: ast-grep requires Rust 1.65 or newer. It's acceptable to use syntax and features introduced in Rust 1.65 or newer in ast-grep code.
Applied to files:
crates/lsp/Cargo.toml
📚 Learning: the `language` trait in ast-grep already has a `clone` bound, so traits that extend `language` (like...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1958
File: crates/core/src/tree_sitter.rs:262-268
Timestamp: 2025-04-28T19:41:29.191Z
Learning: The `Language` trait in ast-grep already has a `Clone` bound, so traits that extend `Language` (like `LanguageExt`) inherit this bound and don't need to specify it again.
Applied to files:
crates/lsp/Cargo.toml
crates/cli/src/config.rs
crates/lsp/src/lib.rs
📚 Learning: the `language` trait in ast-grep already has a `clone` bound (`trait language: clone + 'static`), so...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1958
File: crates/core/src/tree_sitter.rs:262-268
Timestamp: 2025-04-28T19:41:29.191Z
Learning: The `Language` trait in ast-grep already has a `Clone` bound (`trait Language: Clone + 'static`), so traits that extend `Language` (like `LanguageExt`) inherit this bound and don't need to specify it again.
Applied to files:
crates/lsp/Cargo.toml
crates/lsp/src/lib.rs
📚 Learning: in the ast-grep project, `tree-sitter-native` is not updated because `tree-sitter-facade-sg` require...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1652
File: Cargo.toml:35-38
Timestamp: 2024-12-08T20:23:06.671Z
Learning: In the ast-grep project, `tree-sitter-native` is not updated because `tree-sitter-facade-sg` requires a special patch update.
Applied to files:
crates/lsp/Cargo.toml
📚 Learning: in the `ast-grep` project, when writing tests for position calculations in `crates/core/src/node.rs`...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1630
File: crates/core/src/node.rs:710-718
Timestamp: 2024-11-30T01:59:37.083Z
Learning: In the `ast-grep` project, when writing tests for position calculations in `crates/core/src/node.rs`, positions should be calculated based on character counts rather than character widths.
Applied to files:
crates/lsp/Cargo.toml
📚 Learning: in the `ast-grep` repository, the existence of the `sg` binary after the build process is guaranteed...
Learnt from: philiptaron
PR: ast-grep/ast-grep#0
File: :0-0
Timestamp: 2024-07-27T01:25:27.298Z
Learning: In the `ast-grep` repository, the existence of the `sg` binary after the build process is guaranteed, making checks for its existence before installing shell completions unnecessary.
Applied to files:
crates/lsp/Cargo.toml
📚 Learning: in the `ast-grep` codebase, it's acceptable for some callers of `find_rules` to intentionally ignore...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1500
File: crates/cli/src/config.rs:60-60
Timestamp: 2024-10-08T18:41:57.037Z
Learning: In the `ast-grep` codebase, it's acceptable for some callers of `find_rules` to intentionally ignore the `RuleStats` returned in its tuple `(RuleCollection<SgLang>, RuleStats)` when the statistics are not needed.
Applied to files:
crates/cli/src/config.rs
📚 Learning: `errorcontext` is exported from `crates/cli/src/utils/mod.rs` using `pub use`....
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1497
File: crates/cli/src/lsp.rs:2-2
Timestamp: 2024-10-08T18:41:57.037Z
Learning: `ErrorContext` is exported from `crates/cli/src/utils/mod.rs` using `pub use`.
Applied to files:
crates/cli/src/config.rs
📚 Learning: in `crates/cli/src/utils/worker.rs`, implementing `from` for `items` is considered over-abstra...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1497
File: crates/cli/src/utils/worker.rs:69-77
Timestamp: 2024-10-08T18:41:57.037Z
Learning: In `crates/cli/src/utils/worker.rs`, implementing `From<T>` for `Items<T>` is considered over-abstraction and should be avoided.
Applied to files:
crates/cli/src/config.rs
📚 Learning: in the rust file `crates/core/src/node.rs` of the ast-grep project, the methods `start_pos()` and `e...
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1664
File: crates/core/src/node.rs:744-746
Timestamp: 2024-12-14T21:30:27.243Z
Learning: In the Rust file `crates/core/src/node.rs` of the ast-grep project, the methods `start_pos()` and `end_pos()` retrieve positions from tree-sitter. When updating terminology from `row` to `line`, references to `pos.row()` within these methods should not be modified, as they rely on tree-sitter's API.
Applied to files:
crates/cli/src/config.rs
📚 Learning: ruleoverwrite implements `default` via the `#[derive(default)]` macro....
Learnt from: HerringtonDarkholme
PR: ast-grep/ast-grep#1546
File: crates/cli/src/lsp.rs:27-27
Timestamp: 2024-10-22T13:56:16.926Z
Learning: RuleOverwrite implements `Default` via the `#[derive(Default)]` macro.
Applied to files:
crates/cli/src/config.rs
🪛 GitHub Actions: coverage
crates/cli/src/config.rs
[error] 89-100: cargo fmt check failed due to formatting differences. Run 'cargo fmt' to fix code style issues.
⏰ 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). (1)
- GitHub Check: copilot
🔇 Additional comments (5)
crates/cli/src/lsp.rs (1)
16-23
: LGTM! Clean refactoring to use closure-based rule loadingThe changes properly implement the new pattern:
- Correctly clones
project_dir
for ownership- Uses the new
make_rule_finder()
method to create the closure- Defers rule loading and error handling to the Backend
This simplifies the initialization logic and enables dynamic rule reloading.
crates/lsp/tests/basic.rs (2)
59-84
: LGTM! Proper adaptation to closure-based initializationThe refactoring correctly implements the closure pattern:
- Creates a rule finder closure that builds rules dynamically
- Returns
Ok(rc)
matching the expectedResult
type- Properly passes the closure to
Backend::new
267-317
: Well-structured test for file watcher registrationThe test properly verifies:
- Workspace capability for dynamic file watcher registration
- Initialization sequence with
initialize
andinitialized
- Response contains expected registration or log messages
crates/lsp/src/lib.rs (2)
660-709
: LGTM! Well-implemented rule reloading with proper synchronizationThe implementation correctly:
- Uses the rule finder closure to reload rules
- Handles errors appropriately with atomic updates
- Clears the interner to handle rule ID changes (addressing past review comment)
- Republishes diagnostics for all open files
252-273
: LGTM! Clean constructor implementation with closure-based initializationThe constructor properly:
- Accepts a generic rule finder closure with appropriate trait bounds
- Handles initial rule loading errors gracefully
- Stores the closure for dynamic reloading
- Uses Arc<RwLock<>> for thread-safe state management
…mplify logic, reduce indentation, update file watchers, remove unused deps Co-authored-by: HerringtonDarkholme <2883231+HerringtonDarkholme@users.noreply.github.com>
All comments have been addressed. Applied cargo fmt and clippy before committing. All changes are working correctly with LSP tests passing. Commit: c8de808
All code review comments have been addressed. Applied cargo fmt and clippy before committing. Key changes: moved |
@coderabbitai review |
✅ Actions performedReview triggered.
|
This PR implements dynamic rule reloading for the LSP server while addressing code duplication by decoupling rule finding logic from the LSP crate and reusing the robust CLI implementation.
Problem
Previously, the LSP server had two major issues:
No dynamic rule reloading: Rules were loaded once during initialization and never updated. Any changes to
sgconfig.yml
or rule files (.yml
) required restarting the LSP server.Code duplication: The LSP had its own simplified rule finding logic that duplicated and diverged from the CLI's more robust implementation, missing features like util rules and proper error handling.
Solution
Decoupled Rule Finding Architecture
ProjectConfig::make_rule_finder<L>()
method that encapsulates CLI rule finding logic in a reusable closureload_rules_from_filesystem()
methodDynamic Rule Reloading
**/sgconfig.yml
and**/*.yml
patterns during LSP initializationdid_change_watched_files
handler to detect configuration file changes and trigger rule reloadingBenefits
Example Usage
The LSP server will automatically:
Testing
Fixes #2142.
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Chores