diff --git a/crates/ruff_wasm/src/lib.rs b/crates/ruff_wasm/src/lib.rs index 0006abf7fa..9949914ac0 100644 --- a/crates/ruff_wasm/src/lib.rs +++ b/crates/ruff_wasm/src/lib.rs @@ -18,9 +18,7 @@ use ruff_python_ast::{Mod, PySourceType}; use ruff_python_codegen::Stylist; use ruff_python_formatter::{format_module_ast, pretty_comments, PyFormatContext, QuoteStyle}; use ruff_python_index::Indexer; -use ruff_python_parser::{ - parse, parse_unchecked, parse_unchecked_source, Mode, ParseOptions, Parsed, -}; +use ruff_python_parser::{parse, parse_unchecked, Mode, ParseOptions, Parsed}; use ruff_python_trivia::CommentRanges; use ruff_source_file::SourceLocation; use ruff_text_size::Ranged; @@ -163,8 +161,14 @@ impl Workspace { // TODO(dhruvmanila): Support Jupyter Notebooks let source_kind = SourceKind::Python(contents.to_string()); + // Use the unresolved version because we don't have a file path. + let target_version = self.settings.linter.unresolved_target_version; + // Parse once. - let parsed = parse_unchecked_source(source_kind.source_code(), source_type); + let options = ParseOptions::from(source_type).with_target_version(target_version); + let parsed = parse_unchecked(source_kind.source_code(), options) + .try_into_module() + .expect("`PySourceType` always parses to a `ModModule`."); // Map row and column locations to byte slices (lazily). let locator = Locator::new(contents); @@ -196,7 +200,7 @@ impl Workspace { &source_kind, source_type, &parsed, - self.settings.linter.unresolved_target_version, + target_version, ); let source_code = locator.to_source_code(); @@ -238,6 +242,18 @@ impl Workspace { fix: None, } })) + .chain(parsed.unsupported_syntax_errors().iter().map(|error| { + let start_location = source_code.source_location(error.range.start()); + let end_location = source_code.source_location(error.range.end()); + + ExpandedMessage { + code: None, + message: format!("SyntaxError: {error}"), + location: start_location, + end_location, + fix: None, + } + })) .collect(); serde_wasm_bindgen::to_value(&messages).map_err(into_error) diff --git a/crates/ruff_wasm/tests/api.rs b/crates/ruff_wasm/tests/api.rs index 50811299fc..650791540f 100644 --- a/crates/ruff_wasm/tests/api.rs +++ b/crates/ruff_wasm/tests/api.rs @@ -61,6 +61,27 @@ fn syntax_error() { ); } +#[wasm_bindgen_test] +fn unsupported_syntax_error() { + check!( + "match 2:\n case 1: ...", + r#"{}"#, + [ExpandedMessage { + code: None, + message: "SyntaxError: Cannot use `match` statement on Python 3.9 (syntax was added in Python 3.10)".to_string(), + location: SourceLocation { + row: OneIndexed::from_zero_indexed(0), + column: OneIndexed::from_zero_indexed(0) + }, + end_location: SourceLocation { + row: OneIndexed::from_zero_indexed(0), + column: OneIndexed::from_zero_indexed(5) + }, + fix: None, + }] + ); +} + #[wasm_bindgen_test] fn partial_config() { check!("if (1, 2):\n pass", r#"{"ignore": ["F"]}"#, []);