From cf83584abb130574059064ad5f0dd806c22e45d5 Mon Sep 17 00:00:00 2001 From: Brent Westbrook <36778786+ntBre@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:28:37 -0500 Subject: [PATCH] Show version-related syntax errors in the playground (#16419) ## Summary Fixes part of https://github.com/astral-sh/ruff/issues/16417 by converting `unsupported_syntax_errors` into playground diagnostics. ## Test Plan A new `ruff_wasm` test, plus trying out the playground locally: Default settings: ![image](https://github.com/user-attachments/assets/94377ab5-4d4c-44d3-ae63-fe328a53e083) `target-version = "py310"`: ![image](https://github.com/user-attachments/assets/51c312ce-70e7-43d3-b6ba-098f2750cb28) --- crates/ruff_wasm/src/lib.rs | 26 +++++++++++++++++++++----- crates/ruff_wasm/tests/api.rs | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) 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"]}"#, []);