diff --git a/Cargo.lock b/Cargo.lock index 6f0b1514..b0ad29a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1428,6 +1428,7 @@ dependencies = [ "fs4", "home", "indexmap", + "line-index", "log", "petgraph", "schemars", diff --git a/crates/moon/src/cli/doc.rs b/crates/moon/src/cli/doc.rs index cbde9d8c..b140213b 100644 --- a/crates/moon/src/cli/doc.rs +++ b/crates/moon/src/cli/doc.rs @@ -84,7 +84,7 @@ pub fn run_doc(cli: UniversalFlags, cmd: DocSubcommand) -> anyhow::Result { let moonbuild_opt = MoonbuildOpt { source_dir: source_dir.clone(), target_dir, - sort_input: false, + sort_input: true, run_mode, ..Default::default() }; diff --git a/crates/moon/tests/test_cases/mod.rs b/crates/moon/tests/test_cases/mod.rs index 619bef43..507d011b 100644 --- a/crates/moon/tests/test_cases/mod.rs +++ b/crates/moon/tests/test_cases/mod.rs @@ -5348,8 +5348,8 @@ fn test_moon_check_json_output() { check( &get_stdout_with_args_and_replace_dir(&dir, ["check", "--output-json", "-q"]), expect![[r#" - {"$message_type":"diagnostic","level":"warning","loc":{"path":"$ROOT/main/main.mbt","start":{"line":3,"col":3,"offset":25},"end":{"line":3,"col":10,"offset":32}},"message":"Warning (Alert alert_2): alert_2","error_code":2000} - "#]], + {"$message_type":"diagnostic","level":"warning","loc":{"path":"$ROOT/main/main.mbt","start":{"line":3,"col":3},"end":{"line":3,"col":10}},"message":"Warning (Alert alert_2): alert_2","error_code":2000} + "#]], ); check( &get_stderr_on_success_with_args_and_replace_dir( @@ -5372,7 +5372,7 @@ fn test_moon_check_json_output() { check( &get_stdout_with_args_and_replace_dir(&dir, ["check", "--output-json", "-q"]), expect![[r#" - {"$message_type":"diagnostic","level":"warning","loc":{"path":"$ROOT/main/main.mbt","start":{"line":3,"col":3,"offset":27},"end":{"line":3,"col":10,"offset":34}},"message":"Warning (Alert alert_2): alert_2","error_code":2000} + {"$message_type":"diagnostic","level":"warning","loc":{"path":"$ROOT/main/main.mbt","start":{"line":3,"col":3},"end":{"line":3,"col":10}},"message":"Warning (Alert alert_2): alert_2","error_code":2000} "#]], ); check( @@ -5503,7 +5503,7 @@ fn test_specify_source_dir_001() { "#]], ); check( - &get_stderr_on_success_with_args_and_replace_dir(&dir, ["check"]), + &get_stderr_on_success_with_args_and_replace_dir(&dir, ["check", "--sort-input"]), expect![[r#" Finished. moon: ran 3 tasks, now up to date "#]], diff --git a/crates/moonbuild/src/expect.rs b/crates/moonbuild/src/expect.rs index 19e268f5..0e7a6271 100644 --- a/crates/moonbuild/src/expect.rs +++ b/crates/moonbuild/src/expect.rs @@ -18,6 +18,7 @@ use anyhow::Context; use colored::Colorize; +use moonutil::common::line_col_to_byte_idx; use std::collections::BTreeSet; use std::collections::HashMap; use std::path::PathBuf; @@ -217,14 +218,6 @@ impl Replace { } } -fn line_col_to_byte_idx(line_index: &line_index::LineIndex, line: u32, col: u32) -> Option { - let offset = line_index.offset(line_index.to_utf8( - line_index::WideEncoding::Utf32, - line_index::WideLineCol { line, col }, - )?)?; - Some(usize::from(offset)) -} - fn parse_expect_failed_message(msg: &str) -> anyhow::Result { let j: ExpectFailedRaw = serde_json_lenient::from_str(msg) .context(format!("parse expect test result failed: {}", msg))?; diff --git a/crates/moonutil/Cargo.toml b/crates/moonutil/Cargo.toml index ac6c9d4f..ac956855 100644 --- a/crates/moonutil/Cargo.toml +++ b/crates/moonutil/Cargo.toml @@ -44,6 +44,7 @@ env_logger.workspace = true log.workspace = true thiserror.workspace = true schemars.workspace = true +line-index.workspace = true [dev-dependencies] expect-test.workspace = true diff --git a/crates/moonutil/src/common.rs b/crates/moonutil/src/common.rs index 6f7aba9d..0006ec73 100644 --- a/crates/moonutil/src/common.rs +++ b/crates/moonutil/src/common.rs @@ -785,3 +785,15 @@ impl MooncGenTestInfo { result } } + +pub fn line_col_to_byte_idx( + line_index: &line_index::LineIndex, + line: u32, + col: u32, +) -> Option { + let offset = line_index.offset(line_index.to_utf8( + line_index::WideEncoding::Utf32, + line_index::WideLineCol { line, col }, + )?)?; + Some(usize::from(offset)) +} diff --git a/crates/moonutil/src/render.rs b/crates/moonutil/src/render.rs index abcf796c..a16af257 100644 --- a/crates/moonutil/src/render.rs +++ b/crates/moonutil/src/render.rs @@ -19,6 +19,8 @@ use ariadne::Fmt; use serde::{Deserialize, Serialize}; +use crate::common::line_col_to_byte_idx; + #[derive(Debug, Serialize, Deserialize)] pub struct MooncDiagnostic { pub level: String, @@ -39,7 +41,21 @@ pub struct Location { pub struct Position { pub line: usize, pub col: usize, - pub offset: isize, +} + +impl Position { + pub fn calculate_offset(&self, content: &str) -> usize { + let line_index = line_index::LineIndex::new(content); + let byte_based_index = + line_col_to_byte_idx(&line_index, self.line as u32 - 1, self.col as u32 - 1).unwrap(); + + content + .char_indices() + .enumerate() + .find(|(_, (byte_offset, _))| *byte_offset == byte_based_index) + .map(|(i, _)| i) + .unwrap_or(usize::from(line_index.len())) + } } impl MooncDiagnostic { @@ -74,21 +90,17 @@ impl MooncDiagnostic { } }; - let mut report_builder = ariadne::Report::build( - kind, - source_file_path, - diagnostic.location.start.offset as usize, - ) - .with_message(format!("[{}]", diagnostic.error_code).fg(color)) - .with_label( - ariadne::Label::new(( - source_file_path, - diagnostic.location.start.offset as usize - ..diagnostic.location.end.offset as usize, - )) - .with_message((&diagnostic.message).fg(color)) - .with_color(color), - ); + let start_offset = diagnostic.location.start.calculate_offset(&source_file); + let end_offset = diagnostic.location.end.calculate_offset(&source_file); + + let mut report_builder = + ariadne::Report::build(kind, source_file_path, start_offset) + .with_message(format!("[{}]", diagnostic.error_code).fg(color)) + .with_label( + ariadne::Label::new((source_file_path, start_offset..end_offset)) + .with_message((&diagnostic.message).fg(color)) + .with_color(color), + ); if !use_fancy { let config = ariadne::Config::default().with_color(false);