Preserve raw include diagnostic provenance and derive bands from the existing shaped editor. Retain deferred tooltip paragraphs through rendering. Include source, regression, failure and native-trial evidence; corrected native acceptance remains pending.
98 lines
6.3 KiB
Rust
98 lines
6.3 KiB
Rust
//! PRIVATE, UNRUN. Parent may install as a child of source_annotations for one
|
|
//! ignored manual test. No fixed machine-speed threshold and no native claim.
|
|
use super::*;
|
|
use iced::advanced::{graphics::text::Editor, text::{Editor as _, Highlighter as _, LineHeight, Wrapping, highlighter::{Format, PlainText}}};
|
|
use iced::{Font, Pixels};
|
|
use oa_core::{language::{Diagnostic, Span}, validation::Severity};
|
|
use std::{hint::black_box, time::Instant};
|
|
|
|
fn diagnostic(start: usize, end: usize) -> SourceDiagnostic {
|
|
SourceDiagnostic { path: "a".into(), diagnostic: Diagnostic {
|
|
severity: Severity::Warning, code: "perf".into(), message: "prepared geometry specimen".into(), object_id: None, field: None, line: 0, column: 0, span: Span { start, end },
|
|
}, related: Vec::new() }
|
|
}
|
|
fn shaped(source: &str) -> Editor {
|
|
let mut e = Editor::with_text(source);
|
|
let mut h = PlainText::new(&());
|
|
e.update(Size::new(640., 240.), Font::MONOSPACE, Pixels(16.), LineHeight::Absolute(Pixels(24.)), Wrapping::WordOrGlyph, &mut h);
|
|
e.highlight(Font::MONOSPACE, &mut h, |_| Format::default());
|
|
e
|
|
}
|
|
fn distribution<T>(label: &str, batch: usize, mut operation: impl FnMut() -> T) {
|
|
drop(black_box(operation())); // one excluded warmup
|
|
let mut samples = Vec::new();
|
|
for _ in 0..5 {
|
|
let mut elapsed = 0;
|
|
for _ in 0..batch {
|
|
let start = Instant::now();
|
|
let value = operation();
|
|
black_box(&value);
|
|
elapsed += start.elapsed().as_nanos();
|
|
drop(value); // allocation/destruction separated: operation includes allocation, excludes drop
|
|
}
|
|
samples.push(elapsed / batch as u128);
|
|
}
|
|
let mut sorted = samples.clone(); sorted.sort_unstable();
|
|
println!("TIMING {label} batch={batch} warmup=1 measured=5 ns_per_call={samples:?} min={} median={} max={} drop_excluded=true", sorted[0], sorted[2], sorted[4]);
|
|
}
|
|
fn run_view(label: &str, source: Arc<str>, editor: &Editor, dense: &[SourceDiagnostic]) {
|
|
let buffer = editor.buffer();
|
|
let runs: Vec<_> = buffer.layout_runs().collect();
|
|
assert!(!runs.is_empty());
|
|
let visible_glyphs: usize = runs.iter().map(|r| r.glyphs.len()).sum();
|
|
let first = runs.iter().find_map(|r| r.glyphs.iter().find(|g| g.w > 0.).map(|g| (r.line_i, g.start, g.end))).unwrap();
|
|
let line_starts: Vec<_> = cosmic_text::LineIter::new(&source).map(|(r,_)| r.start).collect();
|
|
let sparse = [diagnostic(line_starts[first.0] + first.1, line_starts[first.0] + first.2)];
|
|
let sparse_index = Index::new(source.clone(), "a", &sparse);
|
|
let dense_index = Index::new(source.clone(), "a", dense);
|
|
let empty_index = Index::new(source.clone(), "a", &[]);
|
|
let origin = Point::new(17., 29.);
|
|
let clip = Rectangle::new(origin, Size::new(640., 240.));
|
|
let sparse_bands = sparse_index.bands(buffer, origin, clip);
|
|
assert!(!sparse_bands.is_empty(), "positive visible glyph fixture");
|
|
assert!(empty_index.bands(buffer, origin, clip).is_empty());
|
|
let rejected = Rectangle::new(Point::new(-1000., -1000.), Size::new(1., 1.));
|
|
assert!(dense_index.bands(buffer, origin, rejected).is_empty(), "offscreen-output negative control");
|
|
let dense_count = dense_index.bands(buffer, origin, clip).len();
|
|
println!("CASE {label} bytes={} paragraphs={} diagnostics={} visible_runs={} visible_glyphs={visible_glyphs} dense_bands={dense_count} scroll={:?}", source.len(), buffer.lines.len(), dense.len(), runs.len(), buffer.scroll());
|
|
distribution(&format!("{label}/index-build-dense"), 1, || Index::new(black_box(source.clone()), "a", black_box(dense)));
|
|
distribution(&format!("{label}/layout-runs-only"), 8, || black_box(buffer).layout_runs().map(|r| r.glyphs.len()).sum::<usize>());
|
|
distribution(&format!("{label}/bands-no-diagnostics"), 8, || empty_index.bands(black_box(buffer), origin, clip));
|
|
distribution(&format!("{label}/bands-one-visible"), 8, || sparse_index.bands(black_box(buffer), origin, clip));
|
|
distribution(&format!("{label}/bands-dense"), 8, || dense_index.bands(black_box(buffer), origin, clip));
|
|
distribution(&format!("{label}/bands-dense-rejected-clip"), 8, || dense_index.bands(black_box(buffer), origin, rejected));
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "manual diagnostic projection distributions; no fixed machine threshold"]
|
|
fn annotation_projection_cost_distributions() {
|
|
// Ordinary file: many logical paragraphs; deep scroll can skip by paragraph.
|
|
let line = "alpha beta gamma delta epsilon\n";
|
|
let ordinary: Arc<str> = Arc::from(line.repeat(4000));
|
|
let ordinary_diagnostics: Vec<_> = (0..4000).map(|i| diagnostic(i * line.len(), i * line.len() + 5)).collect();
|
|
let mut ordinary_editor = shaped(&ordinary);
|
|
run_view("ordinary/top", ordinary.clone(), &ordinary_editor, &ordinary_diagnostics);
|
|
ordinary_editor.perform(iced::widget::text_editor::Action::Scroll { lines: 2000 });
|
|
assert!(ordinary_editor.buffer().scroll().line > 1000, "must really reach a deep logical paragraph");
|
|
run_view("ordinary/deep", ordinary, &ordinary_editor, &ordinary_diagnostics);
|
|
|
|
// Single paragraph: diagnostics near beginning remain indexed on the same
|
|
// logical line even when the visible runs are far below all of them.
|
|
let token = "alpha beta gamma delta ";
|
|
let single: Arc<str> = Arc::from(token.repeat(6000));
|
|
let dense: Vec<_> = (0..1500).map(|i| diagnostic(i * token.len(), i * token.len() + 5)).collect();
|
|
let mut single_editor = shaped(&single);
|
|
let wrap_count = single_editor.buffer().lines[0].layout_opt().unwrap().len();
|
|
assert!(wrap_count > 1000, "fixture must shape thousands of wraps");
|
|
run_view("single/top", single.clone(), &single_editor, &dense);
|
|
single_editor.perform(iced::widget::text_editor::Action::Scroll { lines: (wrap_count / 2) as i32 });
|
|
let buffer = single_editor.buffer();
|
|
assert_eq!(buffer.scroll().line, 0);
|
|
assert!(buffer.scroll().vertical > 1000., "must really scroll within same paragraph");
|
|
let first_visible = buffer.layout_runs().next().unwrap();
|
|
assert!(first_visible.glyphs.iter().map(|g| g.start).min().unwrap() > dense.last().unwrap().diagnostic.span.end,
|
|
"dense diagnostics must all be above the deep viewport");
|
|
run_view("single/deep-offscreen-diagnostics", single, &single_editor, &dense);
|
|
println!("DONE manual cost distributions; compare controls and top/deep ratios, not a platform-independent latency PASS");
|
|
}
|