BREAKING CHANGES: - Relationship syntax now requires blocks for all participants - Removed self/other perspective blocks from relationships - Replaced 'guard' keyword with 'if' for behavior tree decorators Language Features: - Add tree-sitter grammar with improved if/condition disambiguation - Add comprehensive tutorial and reference documentation - Add SBIR v0.2.0 binary format specification - Add resource linking system for behaviors and schedules - Add year-long schedule patterns (day, season, recurrence) - Add behavior tree enhancements (named nodes, decorators) Documentation: - Complete tutorial series (9 chapters) with baker family examples - Complete reference documentation for all language features - SBIR v0.2.0 specification with binary format details - Added locations and institutions documentation Examples: - Convert all examples to baker family scenario - Add comprehensive working examples Tooling: - Zed extension with LSP integration - Tree-sitter grammar for syntax highlighting - Build scripts and development tools Version Updates: - Main package: 0.1.0 → 0.2.0 - Tree-sitter grammar: 0.1.0 → 0.2.0 - Zed extension: 0.1.0 → 0.2.0 - Storybook editor: 0.1.0 → 0.2.0
168 lines
4.3 KiB
Rust
168 lines
4.3 KiB
Rust
//! Tests for LSP document formatting functionality
|
|
//!
|
|
//! This module tests auto-formatting for:
|
|
//! - Spacing normalization around colons
|
|
//! - Indentation preservation
|
|
//! - Prose block preservation
|
|
//! - Edge cases (empty documents, already formatted)
|
|
|
|
use tower_lsp::lsp_types::FormattingOptions;
|
|
|
|
use super::{
|
|
document::Document,
|
|
formatting::{
|
|
format_document,
|
|
format_text,
|
|
},
|
|
};
|
|
|
|
#[test]
|
|
fn test_format_adds_space_after_colon() {
|
|
let input = "character Alice{age:7}";
|
|
let formatted = format_text(input);
|
|
|
|
// Main formatting: adds space after colon
|
|
assert!(formatted.contains("age: 7"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_normalizes_colon_spacing() {
|
|
let input = "character Alice{age : 7}";
|
|
let formatted = format_text(input);
|
|
|
|
// Should normalize to single space after colon
|
|
assert!(formatted.contains("age: 7"));
|
|
assert!(!formatted.contains("age :"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_multiple_fields() {
|
|
let input = "character Alice{age:7\nname:\"Alice\"}";
|
|
let formatted = format_text(input);
|
|
|
|
assert!(formatted.contains("age: 7"));
|
|
assert!(formatted.contains("name: \"Alice\""));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_preserves_module_paths() {
|
|
let input = "use characters::Alice;";
|
|
let formatted = format_text(input);
|
|
|
|
// Should NOT add space in :: paths
|
|
assert!(formatted.contains("characters::Alice"));
|
|
assert!(!formatted.contains("characters: :Alice"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_preserves_prose_blocks() {
|
|
let input = r#"character Alice{
|
|
---backstory
|
|
Some irregular spacing here
|
|
---
|
|
age:7}"#;
|
|
let formatted = format_text(input);
|
|
|
|
// Prose content preserved exactly
|
|
assert!(formatted.contains("Some irregular spacing here"));
|
|
// But other fields still formatted
|
|
assert!(formatted.contains("age: 7"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_indentation_with_braces() {
|
|
let input = "character Alice{\nage:7\n}";
|
|
let formatted = format_text(input);
|
|
|
|
// Check indentation (4 spaces)
|
|
assert!(formatted.contains("character Alice{"));
|
|
assert!(formatted.contains(" age: 7"));
|
|
assert!(formatted.contains("}"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_nested_indentation() {
|
|
let input = "template Person{\nnested:{\nvalue:123\n}\n}";
|
|
let formatted = format_text(input);
|
|
|
|
assert!(formatted.contains(" nested: {"));
|
|
assert!(formatted.contains(" value: 123"));
|
|
assert!(formatted.contains(" }"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_empty_document() {
|
|
let input = "";
|
|
let formatted = format_text(input);
|
|
|
|
assert_eq!(formatted, "");
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_whitespace_only() {
|
|
let input = " \n \n ";
|
|
let formatted = format_text(input);
|
|
|
|
// Should collapse to single newline or empty
|
|
assert!(formatted.len() <= 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_already_formatted() {
|
|
let input = "character Alice{\n age: 7\n}";
|
|
let formatted = format_text(input);
|
|
|
|
// Should remain essentially the same
|
|
assert!(formatted.contains("age: 7"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_removes_multiple_blank_lines() {
|
|
let input = "character Alice{age:7}\n\n\n\ncharacter Bob{age:10}";
|
|
let formatted = format_text(input);
|
|
|
|
// Should consolidate multiple blank lines
|
|
let double_newlines = formatted.matches("\n\n\n").count();
|
|
assert_eq!(double_newlines, 0, "Should not have triple newlines");
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_comments_unchanged() {
|
|
let input = "// Comment\ncharacter Alice{age:7}";
|
|
let formatted = format_text(input);
|
|
|
|
assert!(formatted.contains("// Comment"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_document_returns_text_edit() {
|
|
let input = "character Alice{age:7}";
|
|
let doc = Document::new(input.to_string());
|
|
|
|
let result = format_document(&doc, &FormattingOptions::default());
|
|
|
|
if doc.ast.is_some() {
|
|
assert!(
|
|
result.is_some(),
|
|
"Should return TextEdit for valid document"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_format_document_no_changes_returns_none() {
|
|
let input = "character Alice{\n age: 7\n}\n";
|
|
let doc = Document::new(input.to_string());
|
|
|
|
let result = format_document(&doc, &FormattingOptions::default());
|
|
|
|
// If document is already formatted, may return None
|
|
// (depends on exact formatting match)
|
|
if result.is_none() {
|
|
assert!(
|
|
doc.ast.is_some(),
|
|
"Should only return None if formatting matches"
|
|
);
|
|
}
|
|
}
|