KCL tests: take fancier snapshots of KCL errors (#4574)
Right now our KCL tests output a debug representation of the KCLError value. This works OK, but it's difficult to read an error like "runtime error: SourceRange([44, 48])" because I don't fucking know what the 44th character in my KCL program is. In the modeling app, source ranges are turned into nice red squiggly underlines in the editor. I want nice squiggly underline when I run the Rust unit tests too, damnit. The JS world should NEVER have fancy toys that I, a Rust programmer, cannot access. I deserve this. I need this. So anyway instead of snapshotting debug repr, snapshot a fancy error via the miette library.
This commit is contained in:
		
							
								
								
									
										107
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										107
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -228,6 +228,15 @@ dependencies = [
 | 
			
		||||
 "windows-targets 0.52.6",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "backtrace-ext"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "backtrace",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "base64"
 | 
			
		||||
version = "0.13.1"
 | 
			
		||||
@ -1625,6 +1634,12 @@ dependencies = [
 | 
			
		||||
 "windows-sys 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "is_ci"
 | 
			
		||||
version = "1.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "is_terminal_polyfill"
 | 
			
		||||
version = "1.70.1"
 | 
			
		||||
@ -1708,6 +1723,7 @@ dependencies = [
 | 
			
		||||
 "kittycad-modeling-cmds",
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "measurements",
 | 
			
		||||
 "miette",
 | 
			
		||||
 "mime_guess",
 | 
			
		||||
 "parse-display 0.9.1",
 | 
			
		||||
 "pretty_assertions",
 | 
			
		||||
@ -1971,6 +1987,37 @@ dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "miette"
 | 
			
		||||
version = "7.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "backtrace",
 | 
			
		||||
 "backtrace-ext",
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "miette-derive",
 | 
			
		||||
 "owo-colors",
 | 
			
		||||
 "supports-color",
 | 
			
		||||
 "supports-hyperlinks",
 | 
			
		||||
 "supports-unicode",
 | 
			
		||||
 "terminal_size",
 | 
			
		||||
 "textwrap",
 | 
			
		||||
 "thiserror 1.0.68",
 | 
			
		||||
 "unicode-width 0.1.14",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "miette-derive"
 | 
			
		||||
version = "7.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 2.0.87",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "mime"
 | 
			
		||||
version = "0.3.17"
 | 
			
		||||
@ -2163,6 +2210,12 @@ dependencies = [
 | 
			
		||||
 "thiserror 1.0.68",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "owo-colors"
 | 
			
		||||
version = "4.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "papergrid"
 | 
			
		||||
version = "0.11.0"
 | 
			
		||||
@ -3311,6 +3364,12 @@ version = "1.13.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "smawk"
 | 
			
		||||
version = "0.3.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "socket2"
 | 
			
		||||
version = "0.5.7"
 | 
			
		||||
@ -3396,6 +3455,27 @@ version = "2.6.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "supports-color"
 | 
			
		||||
version = "3.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "is_ci",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "supports-hyperlinks"
 | 
			
		||||
version = "3.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "supports-unicode"
 | 
			
		||||
version = "3.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "1.0.109"
 | 
			
		||||
@ -3496,6 +3576,27 @@ dependencies = [
 | 
			
		||||
 "winapi-util",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "terminal_size"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "rustix",
 | 
			
		||||
 "windows-sys 0.48.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "textwrap"
 | 
			
		||||
version = "0.16.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "smawk",
 | 
			
		||||
 "unicode-linebreak",
 | 
			
		||||
 "unicode-width 0.1.14",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "thiserror"
 | 
			
		||||
version = "1.0.68"
 | 
			
		||||
@ -3955,6 +4056,12 @@ version = "1.0.13"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-linebreak"
 | 
			
		||||
version = "0.1.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-segmentation"
 | 
			
		||||
version = "1.12.0"
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,7 @@ kittycad = { workspace = true }
 | 
			
		||||
kittycad-modeling-cmds = { workspace = true }
 | 
			
		||||
lazy_static = "1.5.0"
 | 
			
		||||
measurements = "0.11.0"
 | 
			
		||||
miette = "7.2.0"
 | 
			
		||||
mime_guess = "2.0.5"
 | 
			
		||||
parse-display = "0.9.1"
 | 
			
		||||
pyo3 = { version = "0.22.6", optional = true }
 | 
			
		||||
@ -89,6 +90,7 @@ iai = "0.1"
 | 
			
		||||
image = { version = "0.25.5", default-features = false, features = ["png"] }
 | 
			
		||||
insta = { version = "1.41.1", features = ["json", "filters", "redactions"] }
 | 
			
		||||
itertools = "0.13.0"
 | 
			
		||||
miette = { version = "7.2.0", features = ["fancy"] }
 | 
			
		||||
pretty_assertions = "1.4.1"
 | 
			
		||||
tokio = { version = "1.40.0", features = ["rt-multi-thread", "macros", "time"] }
 | 
			
		||||
twenty-twenty = "0.8.0"
 | 
			
		||||
 | 
			
		||||
@ -54,10 +54,56 @@ pub enum KclError {
 | 
			
		||||
    Internal(KclErrorDetails),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone, PartialEq, Eq)]
 | 
			
		||||
#[derive(thiserror::Error, Debug)]
 | 
			
		||||
#[error("{}", self.error.get_message())]
 | 
			
		||||
pub struct Report {
 | 
			
		||||
    pub error: KclError,
 | 
			
		||||
    pub kcl_source: String,
 | 
			
		||||
    pub filename: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl miette::Diagnostic for Report {
 | 
			
		||||
    fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
 | 
			
		||||
        let family = match self.error {
 | 
			
		||||
            KclError::Lexical(_) => "Lexical",
 | 
			
		||||
            KclError::Syntax(_) => "Syntax",
 | 
			
		||||
            KclError::Semantic(_) => "Semantic",
 | 
			
		||||
            KclError::ImportCycle(_) => "ImportCycle",
 | 
			
		||||
            KclError::Type(_) => "Type",
 | 
			
		||||
            KclError::Unimplemented(_) => "Unimplemented",
 | 
			
		||||
            KclError::Unexpected(_) => "Unexpected",
 | 
			
		||||
            KclError::ValueAlreadyDefined(_) => "ValueAlreadyDefined",
 | 
			
		||||
            KclError::UndefinedValue(_) => "UndefinedValue",
 | 
			
		||||
            KclError::InvalidExpression(_) => "InvalidExpression",
 | 
			
		||||
            KclError::Engine(_) => "Engine",
 | 
			
		||||
            KclError::Internal(_) => "Internal",
 | 
			
		||||
        };
 | 
			
		||||
        let error_string = format!("KCL {family} error");
 | 
			
		||||
        Some(Box::new(error_string))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn source_code(&self) -> Option<&dyn miette::SourceCode> {
 | 
			
		||||
        Some(&self.kcl_source)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
 | 
			
		||||
        let iter = self
 | 
			
		||||
            .error
 | 
			
		||||
            .source_ranges()
 | 
			
		||||
            .clone()
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(miette::SourceSpan::from)
 | 
			
		||||
            .map(|span| miette::LabeledSpan::new_with_span(None, span));
 | 
			
		||||
        Some(Box::new(iter))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Serialize, Deserialize, ts_rs::TS, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic)]
 | 
			
		||||
#[error("{message}")]
 | 
			
		||||
#[ts(export)]
 | 
			
		||||
pub struct KclErrorDetails {
 | 
			
		||||
    #[serde(rename = "sourceRanges")]
 | 
			
		||||
    #[label(collection, "Errors")]
 | 
			
		||||
    pub source_ranges: Vec<SourceRange>,
 | 
			
		||||
    #[serde(rename = "msg")]
 | 
			
		||||
    pub message: String,
 | 
			
		||||
 | 
			
		||||
@ -1020,6 +1020,20 @@ impl From<[usize; 3]> for SourceRange {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&SourceRange> for miette::SourceSpan {
 | 
			
		||||
    fn from(source_range: &SourceRange) -> Self {
 | 
			
		||||
        let length = source_range.end() - source_range.start();
 | 
			
		||||
        let start = miette::SourceOffset::from(source_range.start());
 | 
			
		||||
        Self::new(start, length)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<SourceRange> for miette::SourceSpan {
 | 
			
		||||
    fn from(source_range: SourceRange) -> Self {
 | 
			
		||||
        Self::from(&source_range)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SourceRange {
 | 
			
		||||
    /// Create a new source range.
 | 
			
		||||
    pub fn new(start: usize, end: usize, module_id: ModuleId) -> Self {
 | 
			
		||||
 | 
			
		||||
@ -99,9 +99,30 @@ async fn execute(test_name: &str, render_to_png: bool) {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            assert_snapshot(test_name, "Error from executing", || {
 | 
			
		||||
                insta::assert_snapshot!("execution_error", e);
 | 
			
		||||
            });
 | 
			
		||||
            match e {
 | 
			
		||||
                crate::errors::ExecError::Kcl(error) => {
 | 
			
		||||
                    // Snapshot the KCL error with a fancy graphical report.
 | 
			
		||||
                    // This looks like a Cargo compile error, with arrows pointing
 | 
			
		||||
                    // to source code, underlines, etc.
 | 
			
		||||
                    let report = crate::errors::Report {
 | 
			
		||||
                        error,
 | 
			
		||||
                        filename: format!("{test_name}.kcl"),
 | 
			
		||||
                        kcl_source: read("input.kcl", test_name),
 | 
			
		||||
                    };
 | 
			
		||||
                    let report = miette::Report::new(report);
 | 
			
		||||
                    let report = format!("{:?}", report);
 | 
			
		||||
 | 
			
		||||
                    assert_snapshot(test_name, "Error from executing", || {
 | 
			
		||||
                        insta::assert_snapshot!("execution_error", report);
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
                e => {
 | 
			
		||||
                    // These kinds of errors aren't expected to occur. We don't
 | 
			
		||||
                    // snapshot them because they indicate there's something wrong
 | 
			
		||||
                    // with the Rust test, not with the KCL code being tested.
 | 
			
		||||
                    panic!("{e}")
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,13 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing argument_error.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
type: KclErrorDetails { source_ranges: [SourceRange([34, 35, 0])], message: "Expected an array but found Function" }
 | 
			
		||||
KCL Type error
 | 
			
		||||
 | 
			
		||||
  × type: Expected an array but found Function
 | 
			
		||||
   ╭─[5:5]
 | 
			
		||||
 4 │ 
 | 
			
		||||
 5 │ map(f, [0, 1])
 | 
			
		||||
   ·     ─
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing array_elem_push_fail.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
undefined value: KclErrorDetails { source_ranges: [SourceRange([48, 54, 0])], message: "The array doesn't have any item at index 3" }
 | 
			
		||||
KCL UndefinedValue error
 | 
			
		||||
 | 
			
		||||
  × undefined value: The array doesn't have any item at index 3
 | 
			
		||||
   ╭─[3:8]
 | 
			
		||||
 2 │ pushedArr = push(arr, 4)
 | 
			
		||||
 3 │ fail = arr[3]
 | 
			
		||||
   ·        ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing array_index_oob.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
undefined value: KclErrorDetails { source_ranges: [SourceRange([13, 19, 0])], message: "The array doesn't have any item at index 0" }
 | 
			
		||||
KCL UndefinedValue error
 | 
			
		||||
 | 
			
		||||
  × undefined value: The array doesn't have any item at index 0
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ arr = []
 | 
			
		||||
 2 │ x = arr[0]
 | 
			
		||||
   ·     ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,10 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing comparisons_multiple.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([7, 13, 0])], message: "Expected a number, but found a boolean (true/false value)" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: Expected a number, but found a boolean (true/false value)
 | 
			
		||||
   ╭────
 | 
			
		||||
 1 │ assert(3 == 3 == 3, "this should not compile")
 | 
			
		||||
   ·        ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing import_constant.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
engine: KclErrorDetails { source_ranges: [SourceRange([0, 39, 0])], message: "Failed to read file `export_constant.kcl`: No such file or directory (os error 2)" }
 | 
			
		||||
KCL Engine error
 | 
			
		||||
 | 
			
		||||
  × engine: Failed to read file `export_constant.kcl`: No such file or
 | 
			
		||||
  │ directory (os error 2)
 | 
			
		||||
   ╭────
 | 
			
		||||
 1 │ import three from "export_constant.kcl"
 | 
			
		||||
   · ───────────────────────────────────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,12 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing import_cycle1.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
engine: KclErrorDetails { source_ranges: [SourceRange([0, 35, 0])], message: "Failed to read file `import_cycle2.kcl`: No such file or directory (os error 2)" }
 | 
			
		||||
KCL Engine error
 | 
			
		||||
 | 
			
		||||
  × engine: Failed to read file `import_cycle2.kcl`: No such file or directory
 | 
			
		||||
  │ (os error 2)
 | 
			
		||||
   ╭─[1:1]
 | 
			
		||||
 1 │ import two from "import_cycle2.kcl"
 | 
			
		||||
   · ───────────────────────────────────
 | 
			
		||||
 2 │ 
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing import_side_effect.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
engine: KclErrorDetails { source_ranges: [SourceRange([0, 40, 0])], message: "Failed to read file `export_side_effect.kcl`: No such file or directory (os error 2)" }
 | 
			
		||||
KCL Engine error
 | 
			
		||||
 | 
			
		||||
  × engine: Failed to read file `export_side_effect.kcl`: No such file or
 | 
			
		||||
  │ directory (os error 2)
 | 
			
		||||
   ╭────
 | 
			
		||||
 1 │ import foo from "export_side_effect.kcl"
 | 
			
		||||
   · ────────────────────────────────────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,13 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/simulation_tests.rs
 | 
			
		||||
assertion_line: 103
 | 
			
		||||
description: Error from executing invalid_index_fractional.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([20, 28, 0])], message: "1.2 is not a valid index, indices must be whole numbers >= 0" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: 1.2 is not a valid index, indices must be whole numbers >= 0
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ arr = [1, 2, 3]
 | 
			
		||||
 2 │ x = arr[1.2]
 | 
			
		||||
   ·     ────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing invalid_index_negative.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([27, 33, 0])], message: "'-1' is negative, so you can't index an array with it" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: '-1' is negative, so you can't index an array with it
 | 
			
		||||
   ╭─[3:5]
 | 
			
		||||
 2 │ i = -1
 | 
			
		||||
 3 │ x = arr[i]
 | 
			
		||||
   ·     ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,12 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing invalid_index_str.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([20, 28, 0])], message: "Only integers >= 0 can be used as the index of an array, but you're using a string" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: Only integers >= 0 can be used as the index of an array, but
 | 
			
		||||
  │ you're using a string
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ arr = [1, 2, 3]
 | 
			
		||||
 2 │ x = arr["s"]
 | 
			
		||||
   ·     ────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,14 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/simulation_tests.rs
 | 
			
		||||
assertion_line: 103
 | 
			
		||||
description: Error from executing invalid_member_object.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([14, 20, 0])], message: "Only arrays and objects can be indexed, but you're trying to index a number" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: Only arrays and objects can be indexed, but you're trying to
 | 
			
		||||
  │ index a number
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ num = 999
 | 
			
		||||
 2 │ x = num[3]
 | 
			
		||||
   ·     ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,12 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing invalid_member_object_prop.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([13, 26, 0])], message: "Only arrays and objects can be indexed, but you're trying to index a boolean (true/false value)" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: Only arrays and objects can be indexed, but you're trying to
 | 
			
		||||
  │ index a boolean (true/false value)
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ b = true
 | 
			
		||||
 2 │ x = b["property"]
 | 
			
		||||
   ·     ─────────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,14 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl/src/simulation_tests.rs
 | 
			
		||||
assertion_line: 116
 | 
			
		||||
description: Error from executing non_string_key_of_object.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([26, 32, 0])], message: "Only strings can be used as the property of an object, but you're using a number" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: Only strings can be used as the property of an object, but
 | 
			
		||||
  │ you're using a number
 | 
			
		||||
   ╭─[2:7]
 | 
			
		||||
 1 │ obj = { key = 123 }
 | 
			
		||||
 2 │ num = obj[3]
 | 
			
		||||
   ·       ──────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,11 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing object_prop_not_found.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
undefined value: KclErrorDetails { source_ranges: [SourceRange([15, 25, 0])], message: "Property 'age' not found in object" }
 | 
			
		||||
KCL UndefinedValue error
 | 
			
		||||
 | 
			
		||||
  × undefined value: Property 'age' not found in object
 | 
			
		||||
   ╭─[2:5]
 | 
			
		||||
 1 │ obj = {  }
 | 
			
		||||
 2 │ k = obj["age"]
 | 
			
		||||
   ·     ──────────
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,12 @@ source: kcl/src/simulation_tests.rs
 | 
			
		||||
description: Error from executing pipe_substitution_inside_function_called_from_pipeline.kcl
 | 
			
		||||
snapshot_kind: text
 | 
			
		||||
---
 | 
			
		||||
semantic: KclErrorDetails { source_ranges: [SourceRange([106, 107, 0])], message: "cannot use % outside a pipe expression" }
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: cannot use % outside a pipe expression
 | 
			
		||||
   ╭─[6:10]
 | 
			
		||||
 5 │ 
 | 
			
		||||
 6 │ answer = %
 | 
			
		||||
   ·          ─
 | 
			
		||||
 7 │   |> f(%)
 | 
			
		||||
   ╰────
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user