From 5d102bc838e2d67a891df1fa296de9d7f8df929e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 7 Aug 2023 16:13:15 +0200 Subject: [PATCH] napi: Fix access to diagnostics Invoking the diagnostics getter would throw an exception because the JsDiagnostic type has no constructor. There's however no constructor that would allow for the previous laziness, so instead this PR bites the bullet: - When diagnostics are requested, we convert them all in one go into proper JavaScript objects. - The vector returned by line_column is replaced with more idiomatic column and lineNumber properties --- api/napi/__test__/compiler.spec.ts | 17 +++++++++ api/napi/src/interpreter/diagnostic.rs | 51 +++++++++----------------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/api/napi/__test__/compiler.spec.ts b/api/napi/__test__/compiler.spec.ts index 65f2b7ae8..3128d8a08 100644 --- a/api/napi/__test__/compiler.spec.ts +++ b/api/napi/__test__/compiler.spec.ts @@ -196,3 +196,20 @@ test('globalCallbacks ComponentDefinition', (t) => { t.is(callbacks![0], "first-callback"); t.is(callbacks![1], "second-callback"); }) + +test('compiler diagnostics', (t) => { + let compiler = new ComponentCompiler; + t.is(compiler.buildFromSource(`export component App { + garbage + }`, "testsource.slint"), null); + + const diags = compiler.diagnostics; + t.is(diags.length, 1); + t.deepEqual(diags[0], { + level: 0, + message: 'Parse error', + lineNumber: 2, + column: 12, + sourceFile: 'testsource.slint' + }); +}) diff --git a/api/napi/src/interpreter/diagnostic.rs b/api/napi/src/interpreter/diagnostic.rs index dbfcbbfd9..e4bbe7f76 100644 --- a/api/napi/src/interpreter/diagnostic.rs +++ b/api/napi/src/interpreter/diagnostic.rs @@ -19,42 +19,27 @@ impl From for JsDiagnosticLevel { } } -#[napi(js_name = "Diagnostic")] +#[napi(object, js_name = "Diagnostic")] pub struct JsDiagnostic { - internal: Diagnostic, -} - -#[napi] -impl JsDiagnostic { - #[napi] - pub fn level(&self) -> JsDiagnosticLevel { - self.internal.level().into() - } - - #[napi] - pub fn message(&self) -> String { - self.internal.message().into() - } - - #[napi] - pub fn line_column(&self) -> Vec { - let (start, column) = self.internal.line_column(); - vec![start as i32, column as i32] - } - - #[napi] - pub fn source_file(&self) -> Option { - if let Some(source_file) = self.internal.source_file() { - if let Some(source_file) = source_file.to_str() { - return Some(source_file.into()); - } - } - None - } + pub level: JsDiagnosticLevel, + pub message: String, + pub line_number: u32, + pub column: u32, + pub source_file: Option, } impl From for JsDiagnostic { - fn from(diagnostic: Diagnostic) -> Self { - Self { internal: diagnostic } + fn from(internal_diagnostic: Diagnostic) -> Self { + let (line_number, column) = internal_diagnostic.line_column(); + Self { + level: internal_diagnostic.level().into(), + message: internal_diagnostic.message().into(), + line_number: line_number as u32, + column: column as u32, + source_file: internal_diagnostic + .source_file() + .and_then(|path| path.to_str()) + .map(|str| str.into()), + } } }