first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
+41 -29
View File
@@ -1,38 +1,34 @@
mod queries;
use languages::Language;
pub use queries::highlight_query::{ColorMap, TextSlice};
use std::{
cell::{Ref, RefCell},
collections::{HashMap, HashSet},
sync::Arc,
};
use parking_lot::Mutex;
use std::cell::{Ref, RefCell};
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use arborium::tree_sitter::{InputEdit, Parser, Tree};
use futures::stream::AbortHandle;
use galaxyui::{color::ColorU, AppContext, Entity, ModelContext, WeakModelHandle};
use queries::{
highlight_query::HighlightQuery,
indent_query::{indentation_delta, IndentDelta},
};
use languages::Language;
use parking_lot::Mutex;
use queries::highlight_query::HighlightQuery;
pub use queries::highlight_query::{ColorMap, TextSlice};
use queries::indent_query::{indentation_delta, IndentDelta};
use rangemap::{RangeMap, RangeSet};
use string_offset::{ByteOffset, CharOffset};
use galaxy_editor::{
content::{
buffer::{Buffer, BufferSnapshot},
edit::PreciseDelta,
text::IndentUnit,
version::BufferVersion,
},
decoration::DecorationLayer,
};
use galaxyui::text::point::Point;
use galaxy_editor::content::buffer::{Buffer, BufferSnapshot};
use galaxy_editor::content::edit::PreciseDelta;
use galaxy_editor::content::text::IndentUnit;
use galaxy_editor::content::version::BufferVersion;
use galaxy_editor::decoration::DecorationLayer;
use galaxyui_core::color::ColorU;
use galaxyui_core::text::point::Point;
use galaxyui_core::{AppContext, Entity, ModelContext, WeakModelHandle};
const MAX_SYNTAX_TREES: usize = 3;
/// Maximum buffer size in bytes for which we attempt to parse a syntax tree.
/// Files larger than this are skipped to avoid tree-sitter's super-linear
/// memory growth on large inputs. See this tree-sitter issue:
/// https://github.com/tree-sitter/tree-sitter/issues/222#issuecomment-435987441
const MAX_PARSE_BYTES: usize = 2 * 1024 * 1024; // 2 MB
thread_local! {
static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
}
@@ -225,12 +221,17 @@ impl SyntaxTreeState {
}
/// Re-parse the tree based on the updated tree and source content.
///
/// Returns `None` if the buffer exceeds [`MAX_PARSE_BYTES`].
async fn parse_text(
content: BufferSnapshot,
old_tree: Option<Tree>,
language: &Language,
) -> Tree {
PARSER.with(|parser| {
) -> Option<Tree> {
if content.byte_len() > MAX_PARSE_BYTES {
return None;
}
Some(PARSER.with(|parser| {
let mut parser = parser.borrow_mut();
parser
.set_language(&language.grammar)
@@ -244,7 +245,7 @@ impl SyntaxTreeState {
parser
.parse_with_options(&mut callback, old_tree.as_ref(), None)
.expect("Should succeed")
})
}))
}
/// Translate an incoming edit delta into an InputEdit for incrementally updating the syntax
@@ -355,6 +356,17 @@ impl DecorationLayer for SyntaxTreeState {
new_tree
},
move |model, new_tree, ctx| {
let Some(new_tree) = new_tree else {
// Buffer exceeded MAX_PARSE_BYTES; skip updating the syntax tree, but
// still emit DecorationUpdated so any delayed rendering is flushed
let mut syntax_tree_lock = model.syntax_tree.lock();
syntax_tree_lock.remove(&version);
drop(syntax_tree_lock);
model.invalidate_highlight_cache_for_version(version);
// (the editor delays showing content until this event fires).
ctx.emit(DecorationStateEvent::DecorationUpdated { version });
return;
};
let mut syntax_tree_lock = model.syntax_tree.lock();
model.invalidate_highlight_cache_for_version(version);
if let Some(old_tree) = syntax_tree_lock.get_mut(&version) {
@@ -1,14 +1,13 @@
use std::{iter, ops::Range};
use std::iter;
use std::ops::Range;
use arborium::tree_sitter::{Node, Query, QueryCursor, TextProvider, Tree};
use galaxy_editor::content::{
buffer::{Buffer, ToBufferByteOffset, ToBufferCharOffset},
text::Bytes,
};
use galaxyui::color::ColorU;
use rangemap::RangeMap;
use streaming_iterator::StreamingIterator;
use string_offset::{ByteOffset, CharOffset};
use galaxy_editor::content::buffer::{Buffer, ToBufferByteOffset, ToBufferCharOffset};
use galaxy_editor::content::text::Bytes;
use galaxyui_core::color::ColorU;
/// Color mapping from parsed syntax token name to its corresponding highlighting color.
#[derive(Clone, Copy)]
@@ -1,9 +1,11 @@
use std::{collections::HashMap, ops::Range};
use std::collections::HashMap;
use std::ops::Range;
use arborium::tree_sitter::{Node, Query, QueryCursor, Tree};
use galaxy_editor::content::buffer::Buffer;
use galaxyui::text::point::Point;
use streaming_iterator::StreamingIterator;
use galaxyui_core::text::point::Point;
use super::highlight_query::TextBuffer;
@@ -6,28 +6,34 @@ use galaxy_editor::content::selection_model::BufferSelectionModel;
use galaxy_editor::content::text::IndentBehavior;
use galaxyui::App;
use languages::{language_by_filename, Language};
use crate::SyntaxTreeState;
use galaxy_util::standardized_path::StandardizedPath;
use galaxyui_core::App;
use super::*;
use crate::SyntaxTreeState;
// Simple stub function to allow compilation - can be improved later
fn mock_buffer_and_tree(text_content: &str, language: Arc<Language>) -> (Buffer, Tree) {
// Create a tree by parsing the text
let snapshot = BufferSnapshot::from_plain_text(text_content);
let tree = galaxyui::r#async::block_on(async {
let tree = galaxyui_core::r#async::block_on(async {
SyntaxTreeState::parse_text(snapshot, None, &language).await
});
})
.expect("test buffer is small and should parse");
// Create a minimal buffer
let buffer = Buffer::new(Box::new(|_, _| IndentBehavior::Ignore));
(buffer, tree)
}
fn test_path(filename: &str) -> StandardizedPath {
StandardizedPath::try_new(&format!("/{filename}")).expect("test path should be absolute")
}
#[test]
fn test_indent_query() {
App::test((), |mut app| async move {
let language = language_by_filename(std::path::Path::new("test.rs"))
let language = language_by_filename(&test_path("test.rs"))
.expect("Should contain language rule for rust");
let text_content = r#"impl Test {
fn first_func() {
@@ -55,9 +61,10 @@ fn test_indent_query() {
});
let buffer_snapshot = buffer_handle.read(&app, |buffer, _| buffer.buffer_snapshot());
let tree = galaxyui::r#async::block_on(async {
let tree = galaxyui_core::r#async::block_on(async {
SyntaxTreeState::parse_text(buffer_snapshot, None, &language).await
});
})
.expect("test buffer is small and should parse");
let query = language.as_ref().indents_query.as_ref().unwrap();
@@ -116,7 +123,7 @@ fn test_indent_query() {
#[test]
fn test_indent_query_on_go() {
App::test((), |mut app| async move {
let language = language_by_filename(std::path::Path::new("test.go"))
let language = language_by_filename(&test_path("test.go"))
.expect("Should contain language rule for go");
let text_content = r#"package logic
import (
@@ -151,9 +158,10 @@ fn test_indent_query_on_go() {
});
let buffer_snapshot = buffer_handle.read(&app, |buffer, _| buffer.buffer_snapshot());
let tree = galaxyui::r#async::block_on(async {
let tree = galaxyui_core::r#async::block_on(async {
SyntaxTreeState::parse_text(buffer_snapshot, None, &language).await
});
})
.expect("test buffer is small and should parse");
let query = &language.as_ref().indents_query.as_ref().unwrap();
@@ -210,8 +218,8 @@ fn test_indent_query_on_go() {
#[test]
fn test_indent_query_on_go_bracket_expansion() {
let language = language_by_filename(std::path::Path::new("test.go"))
.expect("Should contain language rule for go");
let language =
language_by_filename(&test_path("test.go")).expect("Should contain language rule for go");
let (buffer, tree) = mock_buffer_and_tree(
r#"func test(){}
func test() {
@@ -250,7 +258,7 @@ fn test_indent_query_on_go_bracket_expansion() {
// source: https://peps.python.org/pep-0008/#indentation
#[test]
fn test_indent_query_on_python() {
let language = language_by_filename(std::path::Path::new("test.py"))
let language = language_by_filename(&test_path("test.py"))
.expect("Should contain language rule for python");
let (buffer, tree) = mock_buffer_and_tree(
r#"# Aligned with opening delimiter.
@@ -300,7 +308,7 @@ fn test_indent_query_on_python() {
#[test]
fn test_indent_query_on_python_colon() {
let language = language_by_filename(std::path::Path::new("test.py"))
let language = language_by_filename(&test_path("test.py"))
.expect("Should contain language rule for python");
let (if_buffer, if_tree) = mock_buffer_and_tree(r#"if x:"#, language.clone());
let query = &language.as_ref().indents_query.as_ref().unwrap();
@@ -601,7 +609,7 @@ def foo():
#[test]
fn test_indent_query_on_javascript() {
let language = language_by_filename(std::path::Path::new("test.js"))
let language = language_by_filename(&test_path("test.js"))
.expect("Should contain language rule for javascript");
let (buffer, tree) = mock_buffer_and_tree(
r#"// Import the 'fs' module, commonly used for file operations
@@ -661,7 +669,7 @@ fn test_indent_query_on_javascript() {
#[test]
fn test_indent_query_on_typescript() {
let language = language_by_filename(std::path::Path::new("test.ts"))
let language = language_by_filename(&test_path("test.ts"))
.expect("Should contain language rule for typescript");
let (buffer, tree) = mock_buffer_and_tree(
r#"import { User } from './types';