Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format doctests in docstrings #8811

Merged
merged 11 commits into from
Nov 27, 2023
Prev Previous commit
Next Next commit
ruff_python_formatter: add docstring state to context
This augments the Python's formatter context to include
state about a docstring's quote style. Namely, the quote
style refers to the kind of quotes used for a docstring
that contains a code example that is currently being
formatted. This state will allow us to choose the correct
quote style to use while reformatting code snippets and
will avoid writing invalid Python (in most cases).
BurntSushi committed Nov 27, 2023
commit ba835057e78dfe237f1c78f53e9026286fc46696
33 changes: 32 additions & 1 deletion crates/ruff_python_formatter/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::comments::Comments;
use crate::PyFormatOptions;
use crate::{PyFormatOptions, QuoteStyle};
use ruff_formatter::{Buffer, FormatContext, GroupId, SourceCode};
use ruff_source_file::Locator;
use std::fmt::{Debug, Formatter};
@@ -11,6 +11,15 @@ pub struct PyFormatContext<'a> {
contents: &'a str,
comments: Comments<'a>,
node_level: NodeLevel,
/// Set to a non-None value when the formatter is running on a code
/// snippet within a docstring. The value should be the quote style of the
/// docstring containing the code snippet.
///
/// Various parts of the formatter may inspect this state to change how it
/// works. For example, multi-line strings will always be written with a
/// quote style that is inverted from the one here in order to ensure that
/// the formatted Python code will be valid.
docstring: Option<QuoteStyle>,
}

impl<'a> PyFormatContext<'a> {
@@ -20,6 +29,7 @@ impl<'a> PyFormatContext<'a> {
contents,
comments,
node_level: NodeLevel::TopLevel(TopLevelStatementPosition::Other),
docstring: None,
}
}

@@ -43,6 +53,27 @@ impl<'a> PyFormatContext<'a> {
pub(crate) fn comments(&self) -> &Comments<'a> {
&self.comments
}

/// Returns a non-None value only if the formatter is running on a code
/// snippet within a docstring.
///
/// The quote style returned corresponds to the quoting used for the
/// docstring containing the code snippet currently being formatted.
pub(crate) fn docstring(&self) -> Option<QuoteStyle> {
self.docstring
}

/// Return a new context suitable for formatting code snippets within a
/// docstring.
///
/// The quote style given should correspond to the style of quoting used
/// for the docstring containing the code snippets.
pub(crate) fn in_docstring(self, style: QuoteStyle) -> PyFormatContext<'a> {
PyFormatContext {
docstring: Some(style),
..self
}
}
}

impl FormatContext for PyFormatContext<'_> {