diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 029aad5..d060705 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -36,6 +36,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} + allowed_bots: Copilot,app/copilot,dependabot,github-actions trigger_phrase: '@claude' mode: agent assignee_trigger: claude @@ -105,6 +106,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} + allowed_bots: Copilot,app/copilot,dependabot,github-actions trigger_phrase: '@claude' assignee_trigger: claude mode: agent @@ -128,6 +130,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} + allowed_bots: Copilot,app/copilot,dependabot,github-actions trigger_phrase: '@claude' assignee_trigger: claude label_trigger: claude @@ -151,6 +154,7 @@ jobs: with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }} + allowed_bots: Copilot,app/copilot,dependabot,github-actions trigger_phrase: '@claude' assignee_trigger: claude mode: agent diff --git a/crates/ast-engine/src/tree_sitter/mod.rs b/crates/ast-engine/src/tree_sitter/mod.rs index ad21149..caa22e8 100644 --- a/crates/ast-engine/src/tree_sitter/mod.rs +++ b/crates/ast-engine/src/tree_sitter/mod.rs @@ -145,7 +145,6 @@ fn parse_lang( /// /// ```rust,no_run /// # use thread_ast_engine::tree_sitter::StrDoc; -/// # use thread_ast_engine::Doc; /// # #[derive(Clone, Debug)] /// # struct JavaScript; /// # impl thread_ast_engine::Language for JavaScript { @@ -404,7 +403,7 @@ pub fn perform_edit(tree: &mut Tree, input: &mut S, edit: &Edit bool { pos >= self.start && pos <= self.end } - /// Check if this range overlaps with another range + /// Check if this range overlaps with another range. + /// + /// Uses **inclusive** (closed-interval) semantics: two ranges that touch + /// at a single boundary point (i.e. one ends exactly where the other + /// starts) are considered overlapping. pub fn overlaps(&self, other: &Range) -> bool { self.start <= other.end && other.start <= self.end } } + +#[cfg(test)] +mod range_tests { + use super::*; + + // Helper to create positions + #[cfg(feature = "ast-grep-backend")] + fn pos(line: usize, byte_column: usize, byte_offset: usize) -> Position { + Position::new(line, byte_column, byte_offset) + } + + #[cfg(not(feature = "ast-grep-backend"))] + fn pos(row: usize, column: usize, index: usize) -> Position { + Position::new(row, column, index) + } + + #[test] + fn test_range_contains() { + let start = pos(1, 5, 15); + let end = pos(3, 10, 45); + let range = Range::new(start, end); + + // Before range + assert!(!range.contains(pos(1, 4, 14))); + assert!(!range.contains(pos(0, 5, 5))); + + // Exactly at start + assert!(range.contains(pos(1, 5, 15))); + + // Inside range + assert!(range.contains(pos(2, 0, 25))); + + // Exactly at end + assert!(range.contains(pos(3, 10, 45))); + + // After range + assert!(!range.contains(pos(3, 11, 46))); + assert!(!range.contains(pos(4, 0, 50))); + } + + #[test] + fn test_range_overlaps() { + let base_start = pos(2, 5, 25); + let base_end = pos(4, 10, 55); + let base = Range::new(base_start, base_end); + + // 1. Completely before (no overlap) + let before = Range::new(pos(1, 0, 10), pos(2, 4, 24)); + assert!(!base.overlaps(&before)); + assert!(!before.overlaps(&base)); + + // 2. Touching at start boundary (inclusive: counts as overlap) + let abut_before = Range::new(pos(1, 0, 10), pos(2, 5, 25)); + assert!(base.overlaps(&abut_before)); + assert!(abut_before.overlaps(&base)); + + // 3. Overlapping start + let overlap_start = Range::new(pos(1, 0, 10), pos(3, 0, 35)); + assert!(base.overlaps(&overlap_start)); + assert!(overlap_start.overlaps(&base)); + + // 4. Completely inside + let inside = Range::new(pos(3, 0, 35), pos(3, 5, 40)); + assert!(base.overlaps(&inside)); + assert!(inside.overlaps(&base)); + + // 5. Overlapping end + let overlap_end = Range::new(pos(3, 0, 35), pos(5, 0, 65)); + assert!(base.overlaps(&overlap_end)); + assert!(overlap_end.overlaps(&base)); + + // 6. Touching at end boundary (inclusive: counts as overlap) + let abut_after = Range::new(pos(4, 10, 55), pos(5, 0, 65)); + assert!(base.overlaps(&abut_after)); + assert!(abut_after.overlaps(&base)); + + // 7. Completely after (no overlap) + let after = Range::new(pos(4, 11, 56), pos(5, 0, 65)); + assert!(!base.overlaps(&after)); + assert!(!after.overlaps(&base)); + } +}