mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Pass ParserOptions
to the parser (#16220)
## Summary This is part of the preparation for detecting syntax errors in the parser from https://github.com/astral-sh/ruff/pull/16090/. As suggested in [this comment](https://github.com/astral-sh/ruff/pull/16090/#discussion_r1953084509), I started working on a `ParseOptions` struct that could be stored in the parser. For this initial refactor, I only made it hold the existing `Mode` option, but for syntax errors, we will also need it to have a `PythonVersion`. For that use case, I'm picturing something like a `ParseOptions::with_python_version` method, so you can extend the current calls to something like ```rust ParseOptions::from(mode).with_python_version(settings.target_version) ``` But I thought it was worth adding `ParseOptions` alone without changing any other behavior first. Most of the diff is just updating call sites taking `Mode` to take `ParseOptions::from(Mode)` or those taking `PySourceType`s to take `ParseOptions::from(PySourceType)`. The interesting changes are in the new `parser/options.rs` file and smaller parts of `parser/mod.rs` and `ruff_python_parser/src/lib.rs`. ## Test Plan Existing tests, this should not change any behavior.
This commit is contained in:
parent
cfc6941d5c
commit
97d0659ce3
25 changed files with 148 additions and 93 deletions
|
@ -8,7 +8,7 @@ use ruff_benchmark::{
|
||||||
TestCase, LARGE_DATASET, NUMPY_CTYPESLIB, NUMPY_GLOBALS, PYDANTIC_TYPES, UNICODE_PYPINYIN,
|
TestCase, LARGE_DATASET, NUMPY_CTYPESLIB, NUMPY_GLOBALS, PYDANTIC_TYPES, UNICODE_PYPINYIN,
|
||||||
};
|
};
|
||||||
use ruff_python_formatter::{format_module_ast, PreviewMode, PyFormatOptions};
|
use ruff_python_formatter::{format_module_ast, PreviewMode, PyFormatOptions};
|
||||||
use ruff_python_parser::{parse, Mode};
|
use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -48,8 +48,8 @@ fn benchmark_formatter(criterion: &mut Criterion) {
|
||||||
&case,
|
&case,
|
||||||
|b, case| {
|
|b, case| {
|
||||||
// Parse the source.
|
// Parse the source.
|
||||||
let parsed =
|
let parsed = parse(case.code(), ParseOptions::from(Mode::Module))
|
||||||
parse(case.code(), Mode::Module).expect("Input should be a valid Python code");
|
.expect("Input should be a valid Python code");
|
||||||
|
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use anyhow::Result;
|
||||||
|
|
||||||
use ruff_linter::source_kind::SourceKind;
|
use ruff_linter::source_kind::SourceKind;
|
||||||
use ruff_python_ast::PySourceType;
|
use ruff_python_ast::PySourceType;
|
||||||
use ruff_python_parser::{parse, AsMode};
|
use ruff_python_parser::{parse, ParseOptions};
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
pub(crate) struct Args {
|
pub(crate) struct Args {
|
||||||
|
@ -24,7 +24,8 @@ pub(crate) fn main(args: &Args) -> Result<()> {
|
||||||
args.file.display()
|
args.file.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let python_ast = parse(source_kind.source_code(), source_type.as_mode())?.into_syntax();
|
let python_ast =
|
||||||
|
parse(source_kind.source_code(), ParseOptions::from(source_type))?.into_syntax();
|
||||||
println!("{python_ast:#?}");
|
println!("{python_ast:#?}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
||||||
|
|
||||||
use ruff_db::system::{SystemPath, SystemPathBuf};
|
use ruff_db::system::{SystemPath, SystemPathBuf};
|
||||||
use ruff_python_ast::helpers::to_module_path;
|
use ruff_python_ast::helpers::to_module_path;
|
||||||
use ruff_python_parser::{parse, Mode};
|
use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
|
|
||||||
use crate::collector::Collector;
|
use crate::collector::Collector;
|
||||||
pub use crate::db::ModuleDb;
|
pub use crate::db::ModuleDb;
|
||||||
|
@ -30,7 +30,7 @@ impl ModuleImports {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
// Read and parse the source code.
|
// Read and parse the source code.
|
||||||
let source = std::fs::read_to_string(path)?;
|
let source = std::fs::read_to_string(path)?;
|
||||||
let parsed = parse(&source, Mode::Module)?;
|
let parsed = parse(&source, ParseOptions::from(Mode::Module))?;
|
||||||
|
|
||||||
let module_path =
|
let module_path =
|
||||||
package.and_then(|package| to_module_path(package.as_std_path(), path.as_std_path()));
|
package.and_then(|package| to_module_path(package.as_std_path(), path.as_std_path()));
|
||||||
|
|
|
@ -309,7 +309,7 @@ mod tests {
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Edit, Fix};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Edit, Fix};
|
||||||
use ruff_notebook::NotebookIndex;
|
use ruff_notebook::NotebookIndex;
|
||||||
use ruff_python_parser::{parse_unchecked, Mode};
|
use ruff_python_parser::{parse_unchecked, Mode, ParseOptions};
|
||||||
use ruff_source_file::{OneIndexed, SourceFileBuilder};
|
use ruff_source_file::{OneIndexed, SourceFileBuilder};
|
||||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ if call(foo
|
||||||
";
|
";
|
||||||
let locator = Locator::new(source);
|
let locator = Locator::new(source);
|
||||||
let source_file = SourceFileBuilder::new("syntax_errors.py", source).finish();
|
let source_file = SourceFileBuilder::new("syntax_errors.py", source).finish();
|
||||||
parse_unchecked(source, Mode::Module)
|
parse_unchecked(source, ParseOptions::from(Mode::Module))
|
||||||
.errors()
|
.errors()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|parse_error| {
|
.map(|parse_error| {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use insta::assert_snapshot;
|
||||||
|
|
||||||
use ruff_python_ast::visitor::source_order::{SourceOrderVisitor, TraversalSignal};
|
use ruff_python_ast::visitor::source_order::{SourceOrderVisitor, TraversalSignal};
|
||||||
use ruff_python_ast::{AnyNodeRef, BoolOp, CmpOp, Operator, Singleton, UnaryOp};
|
use ruff_python_ast::{AnyNodeRef, BoolOp, CmpOp, Operator, Singleton, UnaryOp};
|
||||||
use ruff_python_parser::{parse, Mode};
|
use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_arguments() {
|
fn function_arguments() {
|
||||||
|
@ -147,7 +147,7 @@ fn f_strings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_source_order_visitation(source: &str) -> String {
|
fn trace_source_order_visitation(source: &str) -> String {
|
||||||
let parsed = parse(source, Mode::Module).unwrap();
|
let parsed = parse(source, ParseOptions::from(Mode::Module)).unwrap();
|
||||||
|
|
||||||
let mut visitor = RecordVisitor::default();
|
let mut visitor = RecordVisitor::default();
|
||||||
visitor.visit_mod(parsed.syntax());
|
visitor.visit_mod(parsed.syntax());
|
||||||
|
|
|
@ -13,7 +13,7 @@ use ruff_python_ast::{
|
||||||
Expr, FString, FStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern,
|
Expr, FString, FStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern,
|
||||||
Stmt, StringLiteral, TypeParam, UnaryOp, WithItem,
|
Stmt, StringLiteral, TypeParam, UnaryOp, WithItem,
|
||||||
};
|
};
|
||||||
use ruff_python_parser::{parse, Mode};
|
use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_arguments() {
|
fn function_arguments() {
|
||||||
|
@ -156,7 +156,7 @@ fn f_strings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_visitation(source: &str) -> String {
|
fn trace_visitation(source: &str) -> String {
|
||||||
let parsed = parse(source, Mode::Module).unwrap();
|
let parsed = parse(source, ParseOptions::from(Mode::Module)).unwrap();
|
||||||
|
|
||||||
let mut visitor = RecordVisitor::default();
|
let mut visitor = RecordVisitor::default();
|
||||||
walk_module(&mut visitor, parsed.syntax());
|
walk_module(&mut visitor, parsed.syntax());
|
||||||
|
|
|
@ -1435,7 +1435,7 @@ impl<'a> Generator<'a> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ruff_python_ast::{Mod, ModModule};
|
use ruff_python_ast::{Mod, ModModule};
|
||||||
use ruff_python_parser::{self, parse_module, Mode};
|
use ruff_python_parser::{self, parse_module, Mode, ParseOptions};
|
||||||
use ruff_source_file::LineEnding;
|
use ruff_source_file::LineEnding;
|
||||||
|
|
||||||
use crate::stylist::Indentation;
|
use crate::stylist::Indentation;
|
||||||
|
@ -1467,7 +1467,8 @@ mod tests {
|
||||||
fn jupyter_round_trip(contents: &str) -> String {
|
fn jupyter_round_trip(contents: &str) -> String {
|
||||||
let indentation = Indentation::default();
|
let indentation = Indentation::default();
|
||||||
let line_ending = LineEnding::default();
|
let line_ending = LineEnding::default();
|
||||||
let parsed = ruff_python_parser::parse(contents, Mode::Ipython).unwrap();
|
let parsed =
|
||||||
|
ruff_python_parser::parse(contents, ParseOptions::from(Mode::Ipython)).unwrap();
|
||||||
let Mod::Module(ModModule { body, .. }) = parsed.into_syntax() else {
|
let Mod::Module(ModModule { body, .. }) = parsed.into_syntax() else {
|
||||||
panic!("Source code didn't return ModModule")
|
panic!("Source code didn't return ModModule")
|
||||||
};
|
};
|
||||||
|
|
|
@ -148,7 +148,7 @@ impl Deref for Indentation {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ruff_python_parser::{parse_module, parse_unchecked, Mode};
|
use ruff_python_parser::{parse_module, parse_unchecked, Mode, ParseOptions};
|
||||||
use ruff_source_file::{find_newline, LineEnding};
|
use ruff_source_file::{find_newline, LineEnding};
|
||||||
|
|
||||||
use super::{Indentation, Quote, Stylist};
|
use super::{Indentation, Quote, Stylist};
|
||||||
|
@ -215,7 +215,7 @@ x = (
|
||||||
3,
|
3,
|
||||||
)
|
)
|
||||||
";
|
";
|
||||||
let parsed = parse_unchecked(contents, Mode::Module);
|
let parsed = parse_unchecked(contents, ParseOptions::from(Mode::Module));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Stylist::from_tokens(parsed.tokens(), contents).indentation(),
|
Stylist::from_tokens(parsed.tokens(), contents).indentation(),
|
||||||
&Indentation(" ".to_string())
|
&Indentation(" ".to_string())
|
||||||
|
|
|
@ -7,7 +7,7 @@ use clap::{command, Parser, ValueEnum};
|
||||||
|
|
||||||
use ruff_formatter::SourceCode;
|
use ruff_formatter::SourceCode;
|
||||||
use ruff_python_ast::PySourceType;
|
use ruff_python_ast::PySourceType;
|
||||||
use ruff_python_parser::{parse, AsMode};
|
use ruff_python_parser::{parse, ParseOptions};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ pub fn format_and_debug_print(source: &str, cli: &Cli, source_path: &Path) -> Re
|
||||||
let source_type = PySourceType::from(source_path);
|
let source_type = PySourceType::from(source_path);
|
||||||
|
|
||||||
// Parse the AST.
|
// Parse the AST.
|
||||||
let parsed = parse(source, source_type.as_mode()).context("Syntax error in input")?;
|
let parsed = parse(source, ParseOptions::from(source_type)).context("Syntax error in input")?;
|
||||||
|
|
||||||
let options = PyFormatOptions::from_extension(source_path)
|
let options = PyFormatOptions::from_extension(source_path)
|
||||||
.with_preview(if cli.preview {
|
.with_preview(if cli.preview {
|
||||||
|
|
|
@ -514,7 +514,7 @@ mod tests {
|
||||||
|
|
||||||
use ruff_formatter::SourceCode;
|
use ruff_formatter::SourceCode;
|
||||||
use ruff_python_ast::{Mod, PySourceType};
|
use ruff_python_ast::{Mod, PySourceType};
|
||||||
use ruff_python_parser::{parse, AsMode, Parsed};
|
use ruff_python_parser::{parse, ParseOptions, Parsed};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
|
|
||||||
use crate::comments::Comments;
|
use crate::comments::Comments;
|
||||||
|
@ -529,8 +529,8 @@ mod tests {
|
||||||
fn from_code(source: &'a str) -> Self {
|
fn from_code(source: &'a str) -> Self {
|
||||||
let source_code = SourceCode::new(source);
|
let source_code = SourceCode::new(source);
|
||||||
let source_type = PySourceType::Python;
|
let source_type = PySourceType::Python;
|
||||||
let parsed =
|
let parsed = parse(source, ParseOptions::from(source_type))
|
||||||
parse(source, source_type.as_mode()).expect("Expect source to be valid Python");
|
.expect("Expect source to be valid Python");
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
CommentsTestCase {
|
CommentsTestCase {
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub use range::format_range;
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{format, write, FormatError, Formatted, PrintError, Printed, SourceCode};
|
use ruff_formatter::{format, write, FormatError, Formatted, PrintError, Printed, SourceCode};
|
||||||
use ruff_python_ast::{AnyNodeRef, Mod};
|
use ruff_python_ast::{AnyNodeRef, Mod};
|
||||||
use ruff_python_parser::{parse, AsMode, ParseError, Parsed};
|
use ruff_python_parser::{parse, ParseError, ParseOptions, Parsed};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ pub fn format_module_source(
|
||||||
options: PyFormatOptions,
|
options: PyFormatOptions,
|
||||||
) -> Result<Printed, FormatModuleError> {
|
) -> Result<Printed, FormatModuleError> {
|
||||||
let source_type = options.source_type();
|
let source_type = options.source_type();
|
||||||
let parsed = parse(source, source_type.as_mode())?;
|
let parsed = parse(source, ParseOptions::from(source_type))?;
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
let formatted = format_module_ast(&parsed, &comment_ranges, source, options)?;
|
let formatted = format_module_ast(&parsed, &comment_ranges, source, options)?;
|
||||||
Ok(formatted.print()?)
|
Ok(formatted.print()?)
|
||||||
|
@ -154,7 +154,7 @@ mod tests {
|
||||||
use insta::assert_snapshot;
|
use insta::assert_snapshot;
|
||||||
|
|
||||||
use ruff_python_ast::PySourceType;
|
use ruff_python_ast::PySourceType;
|
||||||
use ruff_python_parser::{parse, AsMode};
|
use ruff_python_parser::{parse, ParseOptions};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::{TextRange, TextSize};
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ def main() -> None:
|
||||||
|
|
||||||
// Parse the AST.
|
// Parse the AST.
|
||||||
let source_path = "code_inline.py";
|
let source_path = "code_inline.py";
|
||||||
let parsed = parse(source, source_type.as_mode()).unwrap();
|
let parsed = parse(source, ParseOptions::from(source_type)).unwrap();
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
let options = PyFormatOptions::from_extension(Path::new(source_path));
|
let options = PyFormatOptions::from_extension(Path::new(source_path));
|
||||||
let formatted = format_module_ast(&parsed, &comment_ranges, source, options).unwrap();
|
let formatted = format_module_ast(&parsed, &comment_ranges, source, options).unwrap();
|
||||||
|
|
|
@ -6,7 +6,7 @@ use ruff_formatter::{
|
||||||
};
|
};
|
||||||
use ruff_python_ast::visitor::source_order::{walk_body, SourceOrderVisitor, TraversalSignal};
|
use ruff_python_ast::visitor::source_order::{walk_body, SourceOrderVisitor, TraversalSignal};
|
||||||
use ruff_python_ast::{AnyNodeRef, Stmt, StmtMatch, StmtTry};
|
use ruff_python_ast::{AnyNodeRef, Stmt, StmtMatch, StmtTry};
|
||||||
use ruff_python_parser::{parse, AsMode};
|
use ruff_python_parser::{parse, ParseOptions};
|
||||||
use ruff_python_trivia::{
|
use ruff_python_trivia::{
|
||||||
indentation_at_offset, BackwardsTokenizer, CommentRanges, SimpleToken, SimpleTokenKind,
|
indentation_at_offset, BackwardsTokenizer, CommentRanges, SimpleToken, SimpleTokenKind,
|
||||||
};
|
};
|
||||||
|
@ -73,7 +73,7 @@ pub fn format_range(
|
||||||
|
|
||||||
assert_valid_char_boundaries(range, source);
|
assert_valid_char_boundaries(range, source);
|
||||||
|
|
||||||
let parsed = parse(source, options.source_type().as_mode())?;
|
let parsed = parse(source, ParseOptions::from(options.source_type()))?;
|
||||||
let source_code = SourceCode::new(source);
|
let source_code = SourceCode::new(source);
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
let comments = Comments::from_ast(parsed.syntax(), source_code, &comment_ranges);
|
let comments = Comments::from_ast(parsed.syntax(), source_code, &comment_ranges);
|
||||||
|
|
|
@ -11,6 +11,7 @@ use regex::Regex;
|
||||||
|
|
||||||
use ruff_formatter::printer::SourceMapGeneration;
|
use ruff_formatter::printer::SourceMapGeneration;
|
||||||
use ruff_python_ast::{str::Quote, AnyStringFlags, StringFlags};
|
use ruff_python_ast::{str::Quote, AnyStringFlags, StringFlags};
|
||||||
|
use ruff_python_parser::ParseOptions;
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use {
|
use {
|
||||||
ruff_formatter::{write, FormatOptions, IndentStyle, LineWidth, Printed},
|
ruff_formatter::{write, FormatOptions, IndentStyle, LineWidth, Printed},
|
||||||
|
@ -492,8 +493,6 @@ impl<'src> DocstringLinePrinter<'_, '_, '_, 'src> {
|
||||||
&mut self,
|
&mut self,
|
||||||
kind: &mut CodeExampleKind<'_>,
|
kind: &mut CodeExampleKind<'_>,
|
||||||
) -> FormatResult<Option<Vec<OutputDocstringLine<'static>>>> {
|
) -> FormatResult<Option<Vec<OutputDocstringLine<'static>>>> {
|
||||||
use ruff_python_parser::AsMode;
|
|
||||||
|
|
||||||
let line_width = match self.f.options().docstring_code_line_width() {
|
let line_width = match self.f.options().docstring_code_line_width() {
|
||||||
DocstringCodeLineWidth::Fixed(width) => width,
|
DocstringCodeLineWidth::Fixed(width) => width,
|
||||||
DocstringCodeLineWidth::Dynamic => {
|
DocstringCodeLineWidth::Dynamic => {
|
||||||
|
@ -570,7 +569,8 @@ impl<'src> DocstringLinePrinter<'_, '_, '_, 'src> {
|
||||||
std::format!(r#""""{}""""#, printed.as_code())
|
std::format!(r#""""{}""""#, printed.as_code())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let result = ruff_python_parser::parse(&wrapped, self.f.options().source_type().as_mode());
|
let result =
|
||||||
|
ruff_python_parser::parse(&wrapped, ParseOptions::from(self.f.options().source_type()));
|
||||||
// If the resulting code is not valid, then reset and pass through
|
// If the resulting code is not valid, then reset and pass through
|
||||||
// the docstring lines as-is.
|
// the docstring lines as-is.
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
|
@ -1580,10 +1580,8 @@ fn docstring_format_source(
|
||||||
docstring_quote_style: Quote,
|
docstring_quote_style: Quote,
|
||||||
source: &str,
|
source: &str,
|
||||||
) -> Result<Printed, FormatModuleError> {
|
) -> Result<Printed, FormatModuleError> {
|
||||||
use ruff_python_parser::AsMode;
|
|
||||||
|
|
||||||
let source_type = options.source_type();
|
let source_type = options.source_type();
|
||||||
let parsed = ruff_python_parser::parse(source, source_type.as_mode())?;
|
let parsed = ruff_python_parser::parse(source, ParseOptions::from(source_type))?;
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
let source_code = ruff_formatter::SourceCode::new(source);
|
let source_code = ruff_formatter::SourceCode::new(source);
|
||||||
let comments = crate::Comments::from_ast(parsed.syntax(), source_code, &comment_ranges);
|
let comments = crate::Comments::from_ast(parsed.syntax(), source_code, &comment_ranges);
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::normalizer::Normalizer;
|
||||||
use ruff_formatter::FormatOptions;
|
use ruff_formatter::FormatOptions;
|
||||||
use ruff_python_ast::comparable::ComparableMod;
|
use ruff_python_ast::comparable::ComparableMod;
|
||||||
use ruff_python_formatter::{format_module_source, format_range, PreviewMode, PyFormatOptions};
|
use ruff_python_formatter::{format_module_source, format_range, PreviewMode, PyFormatOptions};
|
||||||
use ruff_python_parser::{parse, AsMode};
|
use ruff_python_parser::{parse, ParseOptions};
|
||||||
use ruff_source_file::{LineIndex, OneIndexed};
|
use ruff_source_file::{LineIndex, OneIndexed};
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::{TextRange, TextSize};
|
||||||
|
|
||||||
|
@ -393,14 +393,14 @@ fn ensure_unchanged_ast(
|
||||||
let source_type = options.source_type();
|
let source_type = options.source_type();
|
||||||
|
|
||||||
// Parse the unformatted code.
|
// Parse the unformatted code.
|
||||||
let mut unformatted_ast = parse(unformatted_code, source_type.as_mode())
|
let mut unformatted_ast = parse(unformatted_code, ParseOptions::from(source_type))
|
||||||
.expect("Unformatted code to be valid syntax")
|
.expect("Unformatted code to be valid syntax")
|
||||||
.into_syntax();
|
.into_syntax();
|
||||||
Normalizer.visit_module(&mut unformatted_ast);
|
Normalizer.visit_module(&mut unformatted_ast);
|
||||||
let unformatted_ast = ComparableMod::from(&unformatted_ast);
|
let unformatted_ast = ComparableMod::from(&unformatted_ast);
|
||||||
|
|
||||||
// Parse the formatted code.
|
// Parse the formatted code.
|
||||||
let mut formatted_ast = parse(formatted_code, source_type.as_mode())
|
let mut formatted_ast = parse(formatted_code, ParseOptions::from(source_type))
|
||||||
.expect("Formatted code to be valid syntax")
|
.expect("Formatted code to be valid syntax")
|
||||||
.into_syntax();
|
.into_syntax();
|
||||||
Normalizer.visit_module(&mut formatted_ast);
|
Normalizer.visit_module(&mut formatted_ast);
|
||||||
|
|
|
@ -68,6 +68,7 @@ use std::iter::FusedIterator;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub use crate::error::{FStringErrorType, LexicalErrorType, ParseError, ParseErrorType};
|
pub use crate::error::{FStringErrorType, LexicalErrorType, ParseError, ParseErrorType};
|
||||||
|
pub use crate::parser::ParseOptions;
|
||||||
pub use crate::token::{Token, TokenKind};
|
pub use crate::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
|
@ -110,7 +111,7 @@ pub mod typing;
|
||||||
/// assert!(module.is_ok());
|
/// assert!(module.is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn parse_module(source: &str) -> Result<Parsed<ModModule>, ParseError> {
|
pub fn parse_module(source: &str) -> Result<Parsed<ModModule>, ParseError> {
|
||||||
Parser::new(source, Mode::Module)
|
Parser::new(source, ParseOptions::from(Mode::Module))
|
||||||
.parse()
|
.parse()
|
||||||
.try_into_module()
|
.try_into_module()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -133,7 +134,7 @@ pub fn parse_module(source: &str) -> Result<Parsed<ModModule>, ParseError> {
|
||||||
/// assert!(expr.is_ok());
|
/// assert!(expr.is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn parse_expression(source: &str) -> Result<Parsed<ModExpression>, ParseError> {
|
pub fn parse_expression(source: &str) -> Result<Parsed<ModExpression>, ParseError> {
|
||||||
Parser::new(source, Mode::Expression)
|
Parser::new(source, ParseOptions::from(Mode::Expression))
|
||||||
.parse()
|
.parse()
|
||||||
.try_into_expression()
|
.try_into_expression()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -161,7 +162,7 @@ pub fn parse_expression_range(
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
) -> Result<Parsed<ModExpression>, ParseError> {
|
) -> Result<Parsed<ModExpression>, ParseError> {
|
||||||
let source = &source[..range.end().to_usize()];
|
let source = &source[..range.end().to_usize()];
|
||||||
Parser::new_starts_at(source, Mode::Expression, range.start())
|
Parser::new_starts_at(source, range.start(), ParseOptions::from(Mode::Expression))
|
||||||
.parse()
|
.parse()
|
||||||
.try_into_expression()
|
.try_into_expression()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -187,8 +188,12 @@ pub fn parse_parenthesized_expression_range(
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
) -> Result<Parsed<ModExpression>, ParseError> {
|
) -> Result<Parsed<ModExpression>, ParseError> {
|
||||||
let source = &source[..range.end().to_usize()];
|
let source = &source[..range.end().to_usize()];
|
||||||
let parsed =
|
let parsed = Parser::new_starts_at(
|
||||||
Parser::new_starts_at(source, Mode::ParenthesizedExpression, range.start()).parse();
|
source,
|
||||||
|
range.start(),
|
||||||
|
ParseOptions::from(Mode::ParenthesizedExpression),
|
||||||
|
)
|
||||||
|
.parse();
|
||||||
parsed.try_into_expression().unwrap().into_result()
|
parsed.try_into_expression().unwrap().into_result()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,11 +232,11 @@ pub fn parse_string_annotation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the given Python source code using the specified [`Mode`].
|
/// Parse the given Python source code using the specified [`ParseOptions`].
|
||||||
///
|
///
|
||||||
/// This function is the most general function to parse Python code. Based on the [`Mode`] supplied,
|
/// This function is the most general function to parse Python code. Based on the [`Mode`] supplied
|
||||||
/// it can be used to parse a single expression, a full Python program, an interactive expression
|
/// via the [`ParseOptions`], it can be used to parse a single expression, a full Python program,
|
||||||
/// or a Python program containing IPython escape commands.
|
/// an interactive expression or a Python program containing IPython escape commands.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -239,16 +244,16 @@ pub fn parse_string_annotation(
|
||||||
/// parsing:
|
/// parsing:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use ruff_python_parser::{Mode, parse};
|
/// use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
///
|
///
|
||||||
/// let parsed = parse("1 + 2", Mode::Expression);
|
/// let parsed = parse("1 + 2", ParseOptions::from(Mode::Expression));
|
||||||
/// assert!(parsed.is_ok());
|
/// assert!(parsed.is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Alternatively, we can parse a full Python program consisting of multiple lines:
|
/// Alternatively, we can parse a full Python program consisting of multiple lines:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use ruff_python_parser::{Mode, parse};
|
/// use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
///
|
///
|
||||||
/// let source = r#"
|
/// let source = r#"
|
||||||
/// class Greeter:
|
/// class Greeter:
|
||||||
|
@ -256,39 +261,39 @@ pub fn parse_string_annotation(
|
||||||
/// def greet(self):
|
/// def greet(self):
|
||||||
/// print("Hello, world!")
|
/// print("Hello, world!")
|
||||||
/// "#;
|
/// "#;
|
||||||
/// let parsed = parse(source, Mode::Module);
|
/// let parsed = parse(source, ParseOptions::from(Mode::Module));
|
||||||
/// assert!(parsed.is_ok());
|
/// assert!(parsed.is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Additionally, we can parse a Python program containing IPython escapes:
|
/// Additionally, we can parse a Python program containing IPython escapes:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use ruff_python_parser::{Mode, parse};
|
/// use ruff_python_parser::{parse, Mode, ParseOptions};
|
||||||
///
|
///
|
||||||
/// let source = r#"
|
/// let source = r#"
|
||||||
/// %timeit 1 + 2
|
/// %timeit 1 + 2
|
||||||
/// ?str.replace
|
/// ?str.replace
|
||||||
/// !ls
|
/// !ls
|
||||||
/// "#;
|
/// "#;
|
||||||
/// let parsed = parse(source, Mode::Ipython);
|
/// let parsed = parse(source, ParseOptions::from(Mode::Ipython));
|
||||||
/// assert!(parsed.is_ok());
|
/// assert!(parsed.is_ok());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn parse(source: &str, mode: Mode) -> Result<Parsed<Mod>, ParseError> {
|
pub fn parse(source: &str, options: ParseOptions) -> Result<Parsed<Mod>, ParseError> {
|
||||||
parse_unchecked(source, mode).into_result()
|
parse_unchecked(source, options).into_result()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the given Python source code using the specified [`Mode`].
|
/// Parse the given Python source code using the specified [`ParseOptions`].
|
||||||
///
|
///
|
||||||
/// This is same as the [`parse`] function except that it doesn't check for any [`ParseError`]
|
/// This is same as the [`parse`] function except that it doesn't check for any [`ParseError`]
|
||||||
/// and returns the [`Parsed`] as is.
|
/// and returns the [`Parsed`] as is.
|
||||||
pub fn parse_unchecked(source: &str, mode: Mode) -> Parsed<Mod> {
|
pub fn parse_unchecked(source: &str, options: ParseOptions) -> Parsed<Mod> {
|
||||||
Parser::new(source, mode).parse()
|
Parser::new(source, options).parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the given Python source code using the specified [`PySourceType`].
|
/// Parse the given Python source code using the specified [`PySourceType`].
|
||||||
pub fn parse_unchecked_source(source: &str, source_type: PySourceType) -> Parsed<ModModule> {
|
pub fn parse_unchecked_source(source: &str, source_type: PySourceType) -> Parsed<ModModule> {
|
||||||
// SAFETY: Safe because `PySourceType` always parses to a `ModModule`
|
// SAFETY: Safe because `PySourceType` always parses to a `ModModule`
|
||||||
Parser::new(source, source_type.as_mode())
|
Parser::new(source, ParseOptions::from(source_type))
|
||||||
.parse()
|
.parse()
|
||||||
.try_into_module()
|
.try_into_module()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -2265,7 +2265,7 @@ impl<'src> Parser<'src> {
|
||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.mode != Mode::Ipython {
|
if self.options.mode != Mode::Ipython {
|
||||||
self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, &command);
|
self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, &command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,11 @@ use crate::token_source::{TokenSource, TokenSourceCheckpoint};
|
||||||
use crate::{Mode, ParseError, ParseErrorType, TokenKind};
|
use crate::{Mode, ParseError, ParseErrorType, TokenKind};
|
||||||
use crate::{Parsed, Tokens};
|
use crate::{Parsed, Tokens};
|
||||||
|
|
||||||
|
pub use crate::parser::options::ParseOptions;
|
||||||
|
|
||||||
mod expression;
|
mod expression;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
mod options;
|
||||||
mod pattern;
|
mod pattern;
|
||||||
mod progress;
|
mod progress;
|
||||||
mod recovery;
|
mod recovery;
|
||||||
|
@ -32,8 +35,8 @@ pub(crate) struct Parser<'src> {
|
||||||
/// Stores all the syntax errors found during the parsing.
|
/// Stores all the syntax errors found during the parsing.
|
||||||
errors: Vec<ParseError>,
|
errors: Vec<ParseError>,
|
||||||
|
|
||||||
/// Specify the mode in which the code will be parsed.
|
/// Options for how the code will be parsed.
|
||||||
mode: Mode,
|
options: ParseOptions,
|
||||||
|
|
||||||
/// The ID of the current token. This is used to track the progress of the parser
|
/// The ID of the current token. This is used to track the progress of the parser
|
||||||
/// to avoid infinite loops when the parser is stuck.
|
/// to avoid infinite loops when the parser is stuck.
|
||||||
|
@ -51,16 +54,20 @@ pub(crate) struct Parser<'src> {
|
||||||
|
|
||||||
impl<'src> Parser<'src> {
|
impl<'src> Parser<'src> {
|
||||||
/// Create a new parser for the given source code.
|
/// Create a new parser for the given source code.
|
||||||
pub(crate) fn new(source: &'src str, mode: Mode) -> Self {
|
pub(crate) fn new(source: &'src str, options: ParseOptions) -> Self {
|
||||||
Parser::new_starts_at(source, mode, TextSize::new(0))
|
Parser::new_starts_at(source, TextSize::new(0), options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new parser for the given source code which starts parsing at the given offset.
|
/// Create a new parser for the given source code which starts parsing at the given offset.
|
||||||
pub(crate) fn new_starts_at(source: &'src str, mode: Mode, start_offset: TextSize) -> Self {
|
pub(crate) fn new_starts_at(
|
||||||
let tokens = TokenSource::from_source(source, mode, start_offset);
|
source: &'src str,
|
||||||
|
start_offset: TextSize,
|
||||||
|
options: ParseOptions,
|
||||||
|
) -> Self {
|
||||||
|
let tokens = TokenSource::from_source(source, options.mode, start_offset);
|
||||||
|
|
||||||
Parser {
|
Parser {
|
||||||
mode,
|
options,
|
||||||
source,
|
source,
|
||||||
errors: Vec::new(),
|
errors: Vec::new(),
|
||||||
tokens,
|
tokens,
|
||||||
|
@ -73,7 +80,7 @@ impl<'src> Parser<'src> {
|
||||||
|
|
||||||
/// Consumes the [`Parser`] and returns the parsed [`Parsed`].
|
/// Consumes the [`Parser`] and returns the parsed [`Parsed`].
|
||||||
pub(crate) fn parse(mut self) -> Parsed<Mod> {
|
pub(crate) fn parse(mut self) -> Parsed<Mod> {
|
||||||
let syntax = match self.mode {
|
let syntax = match self.options.mode {
|
||||||
Mode::Expression | Mode::ParenthesizedExpression => {
|
Mode::Expression | Mode::ParenthesizedExpression => {
|
||||||
Mod::Expression(self.parse_single_expression())
|
Mod::Expression(self.parse_single_expression())
|
||||||
}
|
}
|
||||||
|
|
41
crates/ruff_python_parser/src/parser/options.rs
Normal file
41
crates/ruff_python_parser/src/parser/options.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use ruff_python_ast::PySourceType;
|
||||||
|
|
||||||
|
use crate::{AsMode, Mode};
|
||||||
|
|
||||||
|
/// Options for controlling how a source file is parsed.
|
||||||
|
///
|
||||||
|
/// You can construct a [`ParseOptions`] directly from a [`Mode`]:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ruff_python_parser::{Mode, ParseOptions};
|
||||||
|
///
|
||||||
|
/// let options = ParseOptions::from(Mode::Module);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// or from a [`PySourceType`]
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ruff_python_ast::PySourceType;
|
||||||
|
/// use ruff_python_parser::ParseOptions;
|
||||||
|
///
|
||||||
|
/// let options = ParseOptions::from(PySourceType::Python);
|
||||||
|
/// ```
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ParseOptions {
|
||||||
|
/// Specify the mode in which the code will be parsed.
|
||||||
|
pub(crate) mode: Mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Mode> for ParseOptions {
|
||||||
|
fn from(mode: Mode) -> Self {
|
||||||
|
Self { mode }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PySourceType> for ParseOptions {
|
||||||
|
fn from(source_type: PySourceType) -> Self {
|
||||||
|
Self {
|
||||||
|
mode: source_type.as_mode(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -304,7 +304,7 @@ impl<'src> Parser<'src> {
|
||||||
op,
|
op,
|
||||||
start,
|
start,
|
||||||
))
|
))
|
||||||
} else if self.mode == Mode::Ipython && self.at(TokenKind::Question) {
|
} else if self.options.mode == Mode::Ipython && self.at(TokenKind::Question) {
|
||||||
Stmt::IpyEscapeCommand(
|
Stmt::IpyEscapeCommand(
|
||||||
self.parse_ipython_help_end_escape_command_statement(&parsed_expr),
|
self.parse_ipython_help_end_escape_command_statement(&parsed_expr),
|
||||||
)
|
)
|
||||||
|
@ -932,7 +932,7 @@ impl<'src> Parser<'src> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let range = self.node_range(start);
|
let range = self.node_range(start);
|
||||||
if self.mode != Mode::Ipython {
|
if self.options.mode != Mode::Ipython {
|
||||||
self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, range);
|
self.add_error(ParseErrorType::UnexpectedIpythonEscapeCommand, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::{parse, parse_expression, parse_module, Mode};
|
use crate::{parse, parse_expression, parse_module, Mode, ParseOptions};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_modes() {
|
fn test_modes() {
|
||||||
let source = "a[0][1][2][3][4]";
|
let source = "a[0][1][2][3][4]";
|
||||||
|
|
||||||
assert!(parse(source, Mode::Expression).is_ok());
|
assert!(parse(source, ParseOptions::from(Mode::Expression)).is_ok());
|
||||||
assert!(parse(source, Mode::Module).is_ok());
|
assert!(parse(source, ParseOptions::from(Mode::Module)).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -129,7 +129,7 @@ foo.bar[0].baz[1]??
|
||||||
foo.bar[0].baz[2].egg??
|
foo.bar[0].baz[2].egg??
|
||||||
"
|
"
|
||||||
.trim(),
|
.trim(),
|
||||||
Mode::Ipython,
|
ParseOptions::from(Mode::Ipython),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
insta::assert_debug_snapshot!(parsed.syntax());
|
insta::assert_debug_snapshot!(parsed.syntax());
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::path::Path;
|
||||||
use ruff_annotate_snippets::{Level, Renderer, Snippet};
|
use ruff_annotate_snippets::{Level, Renderer, Snippet};
|
||||||
use ruff_python_ast::visitor::source_order::{walk_module, SourceOrderVisitor, TraversalSignal};
|
use ruff_python_ast::visitor::source_order::{walk_module, SourceOrderVisitor, TraversalSignal};
|
||||||
use ruff_python_ast::{AnyNodeRef, Mod};
|
use ruff_python_ast::{AnyNodeRef, Mod};
|
||||||
use ruff_python_parser::{parse_unchecked, Mode, ParseErrorType, Token};
|
use ruff_python_parser::{parse_unchecked, Mode, ParseErrorType, ParseOptions, Token};
|
||||||
use ruff_source_file::{LineIndex, OneIndexed, SourceCode};
|
use ruff_source_file::{LineIndex, OneIndexed, SourceCode};
|
||||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ fn inline_err() {
|
||||||
/// Snapshots the AST.
|
/// Snapshots the AST.
|
||||||
fn test_valid_syntax(input_path: &Path) {
|
fn test_valid_syntax(input_path: &Path) {
|
||||||
let source = fs::read_to_string(input_path).expect("Expected test file to exist");
|
let source = fs::read_to_string(input_path).expect("Expected test file to exist");
|
||||||
let parsed = parse_unchecked(&source, Mode::Module);
|
let parsed = parse_unchecked(&source, ParseOptions::from(Mode::Module));
|
||||||
|
|
||||||
if !parsed.is_valid() {
|
if !parsed.is_valid() {
|
||||||
let line_index = LineIndex::from_source_text(&source);
|
let line_index = LineIndex::from_source_text(&source);
|
||||||
|
@ -78,7 +78,7 @@ fn test_valid_syntax(input_path: &Path) {
|
||||||
/// Snapshots the AST and the error messages.
|
/// Snapshots the AST and the error messages.
|
||||||
fn test_invalid_syntax(input_path: &Path) {
|
fn test_invalid_syntax(input_path: &Path) {
|
||||||
let source = fs::read_to_string(input_path).expect("Expected test file to exist");
|
let source = fs::read_to_string(input_path).expect("Expected test file to exist");
|
||||||
let parsed = parse_unchecked(&source, Mode::Module);
|
let parsed = parse_unchecked(&source, ParseOptions::from(Mode::Module));
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!parsed.is_valid(),
|
!parsed.is_valid(),
|
||||||
|
@ -130,7 +130,7 @@ f'{'
|
||||||
f'{foo!r'
|
f'{foo!r'
|
||||||
";
|
";
|
||||||
|
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
|
|
||||||
println!("AST:\n----\n{:#?}", parsed.syntax());
|
println!("AST:\n----\n{:#?}", parsed.syntax());
|
||||||
println!("Tokens:\n-------\n{:#?}", parsed.tokens());
|
println!("Tokens:\n-------\n{:#?}", parsed.tokens());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_python_parser::{parse_unchecked, Mode};
|
use ruff_python_parser::{parse_unchecked, Mode, ParseOptions};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextSize;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use ruff_text_size::TextSize;
|
||||||
fn block_comments_two_line_block_at_start() {
|
fn block_comments_two_line_block_at_start() {
|
||||||
// arrange
|
// arrange
|
||||||
let source = "# line 1\n# line 2\n";
|
let source = "# line 1\n# line 2\n";
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -20,7 +20,7 @@ fn block_comments_two_line_block_at_start() {
|
||||||
fn block_comments_indented_block() {
|
fn block_comments_indented_block() {
|
||||||
// arrange
|
// arrange
|
||||||
let source = " # line 1\n # line 2\n";
|
let source = " # line 1\n # line 2\n";
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -34,7 +34,7 @@ fn block_comments_indented_block() {
|
||||||
fn block_comments_single_line_is_not_a_block() {
|
fn block_comments_single_line_is_not_a_block() {
|
||||||
// arrange
|
// arrange
|
||||||
let source = "\n";
|
let source = "\n";
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -48,7 +48,7 @@ fn block_comments_single_line_is_not_a_block() {
|
||||||
fn block_comments_lines_with_code_not_a_block() {
|
fn block_comments_lines_with_code_not_a_block() {
|
||||||
// arrange
|
// arrange
|
||||||
let source = "x = 1 # line 1\ny = 2 # line 2\n";
|
let source = "x = 1 # line 1\ny = 2 # line 2\n";
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -62,7 +62,7 @@ fn block_comments_lines_with_code_not_a_block() {
|
||||||
fn block_comments_sequential_lines_not_in_block() {
|
fn block_comments_sequential_lines_not_in_block() {
|
||||||
// arrange
|
// arrange
|
||||||
let source = " # line 1\n # line 2\n";
|
let source = " # line 1\n # line 2\n";
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -81,7 +81,7 @@ fn block_comments_lines_in_triple_quotes_not_a_block() {
|
||||||
# line 2
|
# line 2
|
||||||
"""
|
"""
|
||||||
"#;
|
"#;
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -117,7 +117,7 @@ y = 2 # do not form a block comment
|
||||||
# therefore do not form a block comment
|
# therefore do not form a block comment
|
||||||
"""
|
"""
|
||||||
"#;
|
"#;
|
||||||
let parsed = parse_unchecked(source, Mode::Module);
|
let parsed = parse_unchecked(source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use insta::assert_debug_snapshot;
|
use insta::assert_debug_snapshot;
|
||||||
|
|
||||||
use ruff_python_parser::{parse_unchecked, Mode};
|
use ruff_python_parser::{parse_unchecked, Mode, ParseOptions};
|
||||||
use ruff_python_trivia::{lines_after, lines_before, CommentRanges, SimpleToken, SimpleTokenizer};
|
use ruff_python_trivia::{lines_after, lines_before, CommentRanges, SimpleToken, SimpleTokenizer};
|
||||||
use ruff_python_trivia::{BackwardsTokenizer, SimpleTokenKind};
|
use ruff_python_trivia::{BackwardsTokenizer, SimpleTokenKind};
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
|
@ -22,7 +22,7 @@ impl TokenizationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tokenize_reverse(&self) -> Vec<SimpleToken> {
|
fn tokenize_reverse(&self) -> Vec<SimpleToken> {
|
||||||
let parsed = parse_unchecked(self.source, Mode::Module);
|
let parsed = parse_unchecked(self.source, ParseOptions::from(Mode::Module));
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
BackwardsTokenizer::new(self.source, self.range, &comment_ranges).collect()
|
BackwardsTokenizer::new(self.source, self.range, &comment_ranges).collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ use ruff_python_ast::{Mod, PySourceType};
|
||||||
use ruff_python_codegen::Stylist;
|
use ruff_python_codegen::Stylist;
|
||||||
use ruff_python_formatter::{format_module_ast, pretty_comments, PyFormatContext, QuoteStyle};
|
use ruff_python_formatter::{format_module_ast, pretty_comments, PyFormatContext, QuoteStyle};
|
||||||
use ruff_python_index::Indexer;
|
use ruff_python_index::Indexer;
|
||||||
use ruff_python_parser::{parse, parse_unchecked, parse_unchecked_source, Mode, Parsed};
|
use ruff_python_parser::{
|
||||||
|
parse, parse_unchecked, parse_unchecked_source, Mode, ParseOptions, Parsed,
|
||||||
|
};
|
||||||
use ruff_python_trivia::CommentRanges;
|
use ruff_python_trivia::CommentRanges;
|
||||||
use ruff_source_file::SourceLocation;
|
use ruff_source_file::SourceLocation;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
@ -264,13 +266,13 @@ impl Workspace {
|
||||||
|
|
||||||
/// Parses the content and returns its AST
|
/// Parses the content and returns its AST
|
||||||
pub fn parse(&self, contents: &str) -> Result<String, Error> {
|
pub fn parse(&self, contents: &str) -> Result<String, Error> {
|
||||||
let parsed = parse_unchecked(contents, Mode::Module);
|
let parsed = parse_unchecked(contents, ParseOptions::from(Mode::Module));
|
||||||
|
|
||||||
Ok(format!("{:#?}", parsed.into_syntax()))
|
Ok(format!("{:#?}", parsed.into_syntax()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tokens(&self, contents: &str) -> Result<String, Error> {
|
pub fn tokens(&self, contents: &str) -> Result<String, Error> {
|
||||||
let parsed = parse_unchecked(contents, Mode::Module);
|
let parsed = parse_unchecked(contents, ParseOptions::from(Mode::Module));
|
||||||
|
|
||||||
Ok(format!("{:#?}", parsed.tokens().as_ref()))
|
Ok(format!("{:#?}", parsed.tokens().as_ref()))
|
||||||
}
|
}
|
||||||
|
@ -288,7 +290,7 @@ struct ParsedModule<'a> {
|
||||||
|
|
||||||
impl<'a> ParsedModule<'a> {
|
impl<'a> ParsedModule<'a> {
|
||||||
fn from_source(source_code: &'a str) -> Result<Self, Error> {
|
fn from_source(source_code: &'a str) -> Result<Self, Error> {
|
||||||
let parsed = parse(source_code, Mode::Module).map_err(into_error)?;
|
let parsed = parse(source_code, ParseOptions::from(Mode::Module)).map_err(into_error)?;
|
||||||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
source_code,
|
source_code,
|
||||||
|
|
|
@ -18,7 +18,7 @@ use ruff_db::system::{DbWithTestSystem, System, SystemPathBuf, TestSystem};
|
||||||
use ruff_db::vendored::VendoredFileSystem;
|
use ruff_db::vendored::VendoredFileSystem;
|
||||||
use ruff_db::{Db as SourceDb, Upcast};
|
use ruff_db::{Db as SourceDb, Upcast};
|
||||||
use ruff_python_ast::PythonVersion;
|
use ruff_python_ast::PythonVersion;
|
||||||
use ruff_python_parser::{parse_unchecked, Mode};
|
use ruff_python_parser::{parse_unchecked, Mode, ParseOptions};
|
||||||
|
|
||||||
/// Database that can be used for testing.
|
/// Database that can be used for testing.
|
||||||
///
|
///
|
||||||
|
@ -134,7 +134,7 @@ fn do_fuzz(case: &[u8]) -> Corpus {
|
||||||
return Corpus::Reject;
|
return Corpus::Reject;
|
||||||
};
|
};
|
||||||
|
|
||||||
let parsed = parse_unchecked(code, Mode::Module);
|
let parsed = parse_unchecked(code, ParseOptions::from(Mode::Module));
|
||||||
if parsed.is_valid() {
|
if parsed.is_valid() {
|
||||||
return Corpus::Reject;
|
return Corpus::Reject;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue