Skip to content

Commit

Permalink
Remove LintSource
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Oct 2, 2023
1 parent 0a16d70 commit d97d454
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 170 deletions.
6 changes: 3 additions & 3 deletions crates/ruff_cli/src/commands/add_noqa.rs
Expand Up @@ -7,12 +7,12 @@ use log::{debug, error};
use rayon::prelude::*;

use ruff_linter::linter::add_noqa_to_path;
use ruff_linter::source_kind::SourceKind;
use ruff_linter::warn_user_once;
use ruff_python_ast::{PySourceType, SourceType};
use ruff_workspace::resolver::{python_files_in_path, PyprojectConfig};

use crate::args::CliOverrides;
use crate::diagnostics::LintSource;

/// Add `noqa` directives to a collection of files.
pub(crate) fn add_noqa(
Expand Down Expand Up @@ -57,8 +57,8 @@ pub(crate) fn add_noqa(
.and_then(|parent| package_roots.get(parent))
.and_then(|package| *package);
let settings = resolver.resolve(path, pyproject_config);
let LintSource(source_kind) = match LintSource::try_from_path(path, source_type) {
Ok(Some(source)) => source,
let source_kind = match SourceKind::from_path(path, source_type) {
Ok(Some(source_kind)) => source_kind,
Ok(None) => return None,
Err(e) => {
error!("Failed to extract source from {}: {e}", path.display());
Expand Down
103 changes: 73 additions & 30 deletions crates/ruff_cli/src/commands/format.rs
Expand Up @@ -15,7 +15,7 @@ use tracing::debug;
use ruff_diagnostics::SourceMap;
use ruff_linter::fs;
use ruff_linter::logging::LogLevel;
use ruff_linter::source_kind::{SourceKind, SourceReadError, SourceWriteError};
use ruff_linter::source_kind::{SourceError, SourceKind};
use ruff_linter::warn_user_once;
use ruff_python_ast::{PySourceType, SourceType};
use ruff_python_formatter::{format_module_source, FormatModuleError};
Expand Down Expand Up @@ -147,64 +147,99 @@ fn format_path(
mode: FormatMode,
) -> Result<FormatCommandResult, FormatCommandError> {
// Extract the sources from the file.
let source_kind = SourceKind::from_path(path, source_type)
.map_err(|err| FormatCommandError::Read(Some(path.to_path_buf()), err))?;
let source_kind = match SourceKind::from_path(path, source_type) {
Ok(Some(source_kind)) => source_kind,
Ok(None) => return Ok(FormatCommandResult::Unchanged),
Err(err) => {
return Err(FormatCommandError::Read(Some(path.to_path_buf()), err));
}
};

// Format the source.
if let Some(source_kind) = format_source(&source_kind, source_type, Some(path), settings)? {
if mode.is_write() {
let mut writer = File::create(path)
.map_err(|err| FormatCommandError::Write(Some(path.to_path_buf()), err.into()))?;
source_kind
.write(&mut writer)
.map_err(|err| FormatCommandError::Write(Some(path.to_path_buf()), err))?;
match format_source(source_kind, source_type, Some(path), settings)? {
FormattedSource::Formatted(formatted) => {
if mode.is_write() {
let mut writer = File::create(path).map_err(|err| {
FormatCommandError::Write(Some(path.to_path_buf()), err.into())
})?;
formatted
.write(&mut writer)
.map_err(|err| FormatCommandError::Write(Some(path.to_path_buf()), err))?;
}
Ok(FormatCommandResult::Formatted)
}
FormattedSource::Unchanged(_) => Ok(FormatCommandResult::Unchanged),
}
}

#[derive(Debug)]
pub(crate) enum FormattedSource {
/// The source was formatted, and the [`SourceKind`] contains the transformed source code.
Formatted(SourceKind),
/// The source was unchanged, and the [`SourceKind`] contains the original source code.
Unchanged(SourceKind),
}

impl From<FormattedSource> for FormatCommandResult {
fn from(value: FormattedSource) -> Self {
match value {
FormattedSource::Formatted(_) => FormatCommandResult::Formatted,
FormattedSource::Unchanged(_) => FormatCommandResult::Unchanged,
}
}
}

impl FormattedSource {
pub(crate) fn source_kind(&self) -> &SourceKind {
match self {
FormattedSource::Formatted(source_kind) => source_kind,
FormattedSource::Unchanged(source_kind) => source_kind,
}
Ok(FormatCommandResult::Formatted)
} else {
Ok(FormatCommandResult::Unchanged)
}
}

/// Format a [`SourceKind`], returning the transformed [`SourceKind`], or `None` if the source was
/// unchanged.
pub(crate) fn format_source(
source_kind: &SourceKind,
source_kind: SourceKind,
source_type: PySourceType,
path: Option<&Path>,
settings: &FormatterSettings,
) -> Result<Option<SourceKind>, FormatCommandError> {
) -> Result<FormattedSource, FormatCommandError> {
match source_kind {
SourceKind::Python(unformatted) => {
let options = settings.to_format_options(source_type, unformatted);
let options = settings.to_format_options(source_type, &unformatted);

let formatted = format_module_source(unformatted, options)
let formatted = format_module_source(&unformatted, options)
.map_err(|err| FormatCommandError::Format(path.map(Path::to_path_buf), err))?;

let formatted = formatted.into_code();
if formatted.len() == unformatted.len() && formatted == *unformatted {
Ok(None)
Ok(FormattedSource::Unchanged(SourceKind::Python(unformatted)))
} else {
Ok(Some(SourceKind::Python(formatted)))
Ok(FormattedSource::Formatted(SourceKind::Python(formatted)))
}
}
SourceKind::IpyNotebook(notebook) => {
if !notebook.is_python_notebook() {
return Ok(None);
return Ok(FormattedSource::Unchanged(SourceKind::IpyNotebook(
notebook,
)));
}

let mut output = String::with_capacity(notebook.source_code().len());
let mut source_map = SourceMap::default();
let options = settings.to_format_options(source_type, notebook.source_code());

let mut output: Option<String> = None;
let mut last: Option<TextSize> = None;
let mut source_map = SourceMap::default();

// Format each cell individually.
for (start, end) in notebook.cell_offsets().iter().tuple_windows::<(_, _)>() {
let range = TextRange::new(*start, *end);
let unformatted = &notebook.source_code()[range];

let options = settings.to_format_options(source_type, unformatted);

// Format the cell.
let formatted = format_module_source(unformatted, options)
let formatted = format_module_source(unformatted, options.clone())
.map_err(|err| FormatCommandError::Format(path.map(Path::to_path_buf), err))?;

// If the cell is unchanged, skip it.
Expand All @@ -213,6 +248,10 @@ pub(crate) fn format_source(
continue;
}

// If this is the first newly-formatted cell, initialize the output.
let output = output
.get_or_insert_with(|| String::with_capacity(notebook.source_code().len()));

// Add all contents from `last` to the current cell.
let slice = &notebook.source_code()
[TextRange::new(last.unwrap_or_default(), range.start())];
Expand All @@ -232,8 +271,10 @@ pub(crate) fn format_source(
}

// If the file was unchanged, return `None`.
let Some(last) = last else {
return Ok(None);
let (Some(mut output), Some(last)) = (output, last) else {
return Ok(FormattedSource::Unchanged(SourceKind::IpyNotebook(
notebook,
)));
};

// Add the remaining content.
Expand All @@ -244,7 +285,9 @@ pub(crate) fn format_source(
let mut notebook = notebook.clone();
notebook.update(&source_map, output);

Ok(Some(SourceKind::IpyNotebook(notebook)))
Ok(FormattedSource::Formatted(SourceKind::IpyNotebook(
notebook,
)))
}
}
}
Expand Down Expand Up @@ -328,9 +371,9 @@ impl Display for FormatResultSummary {
pub(crate) enum FormatCommandError {
Ignore(#[from] ignore::Error),
Panic(Option<PathBuf>, PanicError),
Read(Option<PathBuf>, SourceReadError),
Read(Option<PathBuf>, SourceError),
Format(Option<PathBuf>, FormatModuleError),
Write(Option<PathBuf>, SourceWriteError),
Write(Option<PathBuf>, SourceError),
}

impl Display for FormatCommandError {
Expand Down
37 changes: 18 additions & 19 deletions crates/ruff_cli/src/commands/format_stdin.rs
Expand Up @@ -74,28 +74,27 @@ fn format_source_code(
) -> Result<FormatCommandResult, FormatCommandError> {
// Read the source from stdin.
let source_code = read_from_stdin()
.map_err(|err| FormatCommandError::Read(path.map(Into::into), err.into()))?;
let source_kind = SourceKind::from_source_code(source_code, source_type)
.map_err(|err| FormatCommandError::Read(path.map(Into::into), err))?;
.map_err(|err| FormatCommandError::Read(path.map(Path::to_path_buf), err.into()))?;

// Format the source, and write to stdout regardless of the mode.
if let Some(formatted) = format_source(&source_kind, source_type, path, settings)? {
if mode.is_write() {
let mut writer = stdout().lock();
formatted
.write(&mut writer)
.map_err(|err| FormatCommandError::Write(path.map(Into::into), err))?;
let source_kind = match SourceKind::from_source_code(source_code, source_type) {
Ok(Some(source_kind)) => source_kind,
Ok(None) => return Ok(FormatCommandResult::Unchanged),
Err(err) => {
return Err(FormatCommandError::Read(path.map(Path::to_path_buf), err));
}
};

Ok(FormatCommandResult::Formatted)
} else {
if mode.is_write() {
let mut writer = stdout().lock();
source_kind
.write(&mut writer)
.map_err(|err| FormatCommandError::Write(path.map(Into::into), err))?;
}
// Format the source.
let formatted = format_source(source_kind, source_type, path, settings)?;

Ok(FormatCommandResult::Unchanged)
// Write to stdout regardless of whether the source was formatted.
if mode.is_write() {
let mut writer = stdout().lock();
formatted
.source_kind()
.write(&mut writer)
.map_err(|err| FormatCommandError::Write(path.map(Path::to_path_buf), err))?;
}

Ok(FormatCommandResult::from(formatted))
}

0 comments on commit d97d454

Please sign in to comment.