diff --git a/src/document.rs b/src/document.rs index 3dc6c9b..0f7dd54 100644 --- a/src/document.rs +++ b/src/document.rs @@ -94,14 +94,13 @@ impl PyDocument { match self.inner.query_exact(&r) { Ok(Some(feature)) => { let span = feature.location.byte_span; - // Note: span.0 <= span.1 is guaranteed by tree-sitter node - // ranges, so we only check bounds and UTF-8 alignment. + // Note: span.0 <= span.1 is guaranteed by tree-sitter node construction. if span.1 > source.len() || !source.is_char_boundary(span.0) || !source.is_char_boundary(span.1) { return Err(PyErr::new::( - "Feature span is not valid in source", + "Feature span is out of bounds or not aligned to UTF-8 character boundaries", )); } let raw = &source[span.0..span.1]; @@ -295,9 +294,11 @@ fn apply_insert_at( .ok_or_else(|| format!("insert_at: item at index {resolved} not found"))?; let item_start = item_feature.location.byte_span.0; - // Note: no reversed-span check needed; tree-sitter nodes guarantee start <= end. if item_start > source.len() || !source.is_char_boundary(item_start) { - return Err("Feature span is not valid in source".to_string()); + return Err( + "Feature span is out of bounds or not aligned to UTF-8 character boundaries" + .to_string(), + ); } let line_start = source[..item_start] .rfind('\n') @@ -358,11 +359,13 @@ fn apply_complex_replace( .map_err(|e| format!("Query failed: {e}"))?; let span = feature.location.byte_span; - // Note: span.0 <= span.1 is guaranteed by tree-sitter node ranges, - // so we only check bounds and UTF-8 alignment. + // Note: span.0 <= span.1 is guaranteed by tree-sitter node construction. if span.1 > source.len() || !source.is_char_boundary(span.0) || !source.is_char_boundary(span.1) { - return Err("Feature span is not valid in source".to_string()); + return Err( + "Feature span is out of bounds or not aligned to UTF-8 character boundaries" + .to_string(), + ); } let content_with_ws = doc.extract_with_leading_whitespace(&feature);