mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:16 +00:00
Fix non‑BMP code point handling in quick‑fixes and markers (#20526)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
09f570af92
commit
3e1e02e9b6
4 changed files with 70 additions and 33 deletions
|
@ -19,7 +19,7 @@ There are multiple versions for the different wasm-pack targets. See [here](http
|
|||
This example uses the wasm-pack web target and is known to work with Vite.
|
||||
|
||||
```ts
|
||||
import init, { Workspace, type Diagnostic } from '@astral-sh/ruff-wasm-web';
|
||||
import init, { Workspace, type Diagnostic, PositionEncoding } from '@astral-sh/ruff-wasm-web';
|
||||
|
||||
const exampleDocument = `print('hello'); print("world")`
|
||||
|
||||
|
@ -42,7 +42,7 @@ const workspace = new Workspace({
|
|||
'F'
|
||||
],
|
||||
},
|
||||
});
|
||||
}, PositionEncoding.UTF16);
|
||||
|
||||
// Will contain 1 diagnostic code for E702: Multiple statements on one line
|
||||
const diagnostics: Diagnostic[] = workspace.check(exampleDocument);
|
||||
|
|
|
@ -19,7 +19,7 @@ use ruff_python_formatter::{PyFormatContext, QuoteStyle, format_module_ast, pret
|
|||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::{Mode, ParseOptions, Parsed, parse, parse_unchecked};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::{LineColumn, OneIndexed};
|
||||
use ruff_source_file::{OneIndexed, PositionEncoding as SourcePositionEncoding, SourceLocation};
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_workspace::Settings;
|
||||
use ruff_workspace::configuration::Configuration;
|
||||
|
@ -117,6 +117,7 @@ pub fn run() {
|
|||
#[wasm_bindgen]
|
||||
pub struct Workspace {
|
||||
settings: Settings,
|
||||
position_encoding: SourcePositionEncoding,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -126,7 +127,7 @@ impl Workspace {
|
|||
}
|
||||
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(options: JsValue) -> Result<Workspace, Error> {
|
||||
pub fn new(options: JsValue, position_encoding: PositionEncoding) -> Result<Workspace, Error> {
|
||||
let options: Options = serde_wasm_bindgen::from_value(options).map_err(into_error)?;
|
||||
let configuration =
|
||||
Configuration::from_options(options, Some(Path::new(".")), Path::new("."))
|
||||
|
@ -135,7 +136,10 @@ impl Workspace {
|
|||
.into_settings(Path::new("."))
|
||||
.map_err(into_error)?;
|
||||
|
||||
Ok(Workspace { settings })
|
||||
Ok(Workspace {
|
||||
settings,
|
||||
position_encoding: position_encoding.into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = defaultSettings)]
|
||||
|
@ -228,14 +232,16 @@ impl Workspace {
|
|||
|
||||
let messages: Vec<ExpandedMessage> = diagnostics
|
||||
.into_iter()
|
||||
.map(|msg| ExpandedMessage {
|
||||
.map(|msg| {
|
||||
let range = msg.range().unwrap_or_default();
|
||||
ExpandedMessage {
|
||||
code: msg.secondary_code_or_id().to_string(),
|
||||
message: msg.body().to_string(),
|
||||
start_location: source_code
|
||||
.line_column(msg.range().unwrap_or_default().start())
|
||||
.source_location(range.start(), self.position_encoding)
|
||||
.into(),
|
||||
end_location: source_code
|
||||
.line_column(msg.range().unwrap_or_default().end())
|
||||
.source_location(range.end(), self.position_encoding)
|
||||
.into(),
|
||||
fix: msg.fix().map(|fix| ExpandedFix {
|
||||
message: msg.first_help_text().map(ToString::to_string),
|
||||
|
@ -243,12 +249,17 @@ impl Workspace {
|
|||
.edits()
|
||||
.iter()
|
||||
.map(|edit| ExpandedEdit {
|
||||
location: source_code.line_column(edit.start()).into(),
|
||||
end_location: source_code.line_column(edit.end()).into(),
|
||||
location: source_code
|
||||
.source_location(edit.start(), self.position_encoding)
|
||||
.into(),
|
||||
end_location: source_code
|
||||
.source_location(edit.end(), self.position_encoding)
|
||||
.into(),
|
||||
content: edit.content().map(ToString::to_string),
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -331,14 +342,37 @@ impl<'a> ParsedModule<'a> {
|
|||
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
|
||||
pub struct Location {
|
||||
pub row: OneIndexed,
|
||||
/// The character offset from the start of the line.
|
||||
///
|
||||
/// The semantic of the offset depends on the [`PositionEncoding`] used when creating
|
||||
/// the [`Workspace`].
|
||||
pub column: OneIndexed,
|
||||
}
|
||||
|
||||
impl From<LineColumn> for Location {
|
||||
fn from(value: LineColumn) -> Self {
|
||||
impl From<SourceLocation> for Location {
|
||||
fn from(value: SourceLocation) -> Self {
|
||||
Self {
|
||||
row: value.line,
|
||||
column: value.column,
|
||||
column: value.character_offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[wasm_bindgen]
|
||||
pub enum PositionEncoding {
|
||||
#[default]
|
||||
Utf8,
|
||||
Utf16,
|
||||
Utf32,
|
||||
}
|
||||
|
||||
impl From<PositionEncoding> for SourcePositionEncoding {
|
||||
fn from(value: PositionEncoding) -> Self {
|
||||
match value {
|
||||
PositionEncoding::Utf8 => Self::Utf8,
|
||||
PositionEncoding::Utf16 => Self::Utf16,
|
||||
PositionEncoding::Utf32 => Self::Utf32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,15 @@ use wasm_bindgen_test::wasm_bindgen_test;
|
|||
|
||||
use ruff_linter::registry::Rule;
|
||||
use ruff_source_file::OneIndexed;
|
||||
use ruff_wasm::{ExpandedMessage, Location, Workspace};
|
||||
use ruff_wasm::{ExpandedMessage, Location, PositionEncoding, Workspace};
|
||||
|
||||
macro_rules! check {
|
||||
($source:expr, $config:expr, $expected:expr) => {{
|
||||
let config = js_sys::JSON::parse($config).unwrap();
|
||||
match Workspace::new(config).unwrap().check($source) {
|
||||
match Workspace::new(config, PositionEncoding::Utf8)
|
||||
.unwrap()
|
||||
.check($source)
|
||||
{
|
||||
Ok(output) => {
|
||||
let result: Vec<ExpandedMessage> = serde_wasm_bindgen::from_value(output).unwrap();
|
||||
assert_eq!(result, $expected);
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
useState,
|
||||
} from "react";
|
||||
import { Panel, PanelGroup } from "react-resizable-panels";
|
||||
import { Diagnostic, Workspace } from "ruff_wasm";
|
||||
import { Diagnostic, Workspace, PositionEncoding } from "ruff_wasm";
|
||||
import {
|
||||
ErrorMessage,
|
||||
Theme,
|
||||
|
@ -173,7 +173,7 @@ export default function Editor({
|
|||
|
||||
try {
|
||||
const config = JSON.parse(settingsSource);
|
||||
const workspace = new Workspace(config);
|
||||
const workspace = new Workspace(config, PositionEncoding.Utf16);
|
||||
const diagnostics = workspace.check(pythonSource);
|
||||
|
||||
let secondary: SecondaryPanelResult = null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue