mirror of https://github.com/astral-sh/ruff
Merge dfd3c9a78d into b0bc990cbf
This commit is contained in:
commit
78da98fd22
|
|
@ -81,6 +81,7 @@ pub(crate) fn definitions(checker: &mut Checker) {
|
||||||
Rule::UndocumentedPublicPackage,
|
Rule::UndocumentedPublicPackage,
|
||||||
]);
|
]);
|
||||||
let enforce_pydoclint = checker.any_rule_enabled(&[
|
let enforce_pydoclint = checker.any_rule_enabled(&[
|
||||||
|
Rule::UndocumentedParam,
|
||||||
Rule::DocstringExtraneousParameter,
|
Rule::DocstringExtraneousParameter,
|
||||||
Rule::DocstringMissingReturns,
|
Rule::DocstringMissingReturns,
|
||||||
Rule::DocstringExtraneousReturns,
|
Rule::DocstringExtraneousReturns,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ mod tests {
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
use crate::rules::pydocstyle;
|
use crate::rules::pydocstyle;
|
||||||
use crate::rules::pydocstyle::settings::Convention;
|
use crate::rules::pydocstyle::settings::Convention;
|
||||||
|
use crate::settings::types::PreviewMode;
|
||||||
use crate::test::test_path;
|
use crate::test::test_path;
|
||||||
use crate::{assert_diagnostics, settings};
|
use crate::{assert_diagnostics, settings};
|
||||||
|
|
||||||
|
|
@ -99,4 +100,107 @@ mod tests {
|
||||||
assert_diagnostics!(snapshot, diagnostics);
|
assert_diagnostics!(snapshot, diagnostics);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case(Rule::UndocumentedParam, Path::new("canonical_google_examples.py"))]
|
||||||
|
#[test_case(Rule::UndocumentedParam, Path::new("canonical_numpy_examples.py"))]
|
||||||
|
#[test_case(Rule::UndocumentedParam, Path::new("sections.py"))]
|
||||||
|
fn undocumented_param(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle").join(path).as_path(),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
pydocstyle: pydocstyle::settings::Settings {
|
||||||
|
..pydocstyle::settings::Settings::default()
|
||||||
|
},
|
||||||
|
..settings::LinterSettings::for_rule(rule_code)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(snapshot, diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d417_unspecified() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle/D417.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
// When inferring the convention, we'll see a few false negatives.
|
||||||
|
// See: https://github.com/PyCQA/pydocstyle/issues/459.
|
||||||
|
pydocstyle: pydocstyle::settings::Settings::default(),
|
||||||
|
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d417_unspecified_ignore_var_parameters() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle/D417.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
pydocstyle: pydocstyle::settings::Settings::default(),
|
||||||
|
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d417_google() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle/D417.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
// With explicit Google convention, we should flag every function.
|
||||||
|
pydocstyle: pydocstyle::settings::Settings {
|
||||||
|
convention: Some(Convention::Google),
|
||||||
|
..pydocstyle::settings::Settings::default()
|
||||||
|
},
|
||||||
|
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d417_google_ignore_var_parameters() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle/D417.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
pydocstyle: pydocstyle::settings::Settings {
|
||||||
|
convention: Some(Convention::Google),
|
||||||
|
ignore_var_parameters: true,
|
||||||
|
..pydocstyle::settings::Settings::default()
|
||||||
|
},
|
||||||
|
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn d417_numpy() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pydocstyle/D417.py"),
|
||||||
|
&settings::LinterSettings {
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
// With explicit numpy convention, we shouldn't flag anything.
|
||||||
|
pydocstyle: pydocstyle::settings::Settings {
|
||||||
|
convention: Some(Convention::Numpy),
|
||||||
|
..pydocstyle::settings::Settings::default()
|
||||||
|
},
|
||||||
|
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
assert_diagnostics!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||||
use ruff_python_ast::helpers::{map_callable, map_subscript};
|
use ruff_python_ast::helpers::{map_callable, map_subscript};
|
||||||
|
use ruff_python_ast::identifier::Identifier;
|
||||||
use ruff_python_ast::name::QualifiedName;
|
use ruff_python_ast::name::QualifiedName;
|
||||||
use ruff_python_ast::visitor::Visitor;
|
use ruff_python_ast::visitor::Visitor;
|
||||||
use ruff_python_ast::{self as ast, Expr, Stmt, visitor};
|
use ruff_python_ast::{self as ast, Expr, Stmt, visitor};
|
||||||
|
use ruff_python_semantic::analyze::visibility::is_staticmethod;
|
||||||
use ruff_python_semantic::analyze::{function_type, visibility};
|
use ruff_python_semantic::analyze::{function_type, visibility};
|
||||||
use ruff_python_semantic::{Definition, SemanticModel};
|
use ruff_python_semantic::{Definition, SemanticModel};
|
||||||
use ruff_python_stdlib::identifiers::is_identifier;
|
use ruff_python_stdlib::identifiers::is_identifier;
|
||||||
|
|
@ -17,6 +19,7 @@ use crate::docstrings::Docstring;
|
||||||
use crate::docstrings::sections::{SectionContext, SectionContexts, SectionKind};
|
use crate::docstrings::sections::{SectionContext, SectionContexts, SectionKind};
|
||||||
use crate::docstrings::styles::SectionStyle;
|
use crate::docstrings::styles::SectionStyle;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
use crate::rules::pydocstyle::rules::UndocumentedParam;
|
||||||
use crate::rules::pydocstyle::settings::Convention;
|
use crate::rules::pydocstyle::settings::Convention;
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
|
|
@ -464,6 +467,7 @@ impl GenericSection {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct ParameterEntry<'a> {
|
struct ParameterEntry<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
|
has_definition: bool,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,6 +527,16 @@ impl<'a> ParametersSection<'a> {
|
||||||
range: section.section_name_range(),
|
range: section.section_name_range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extend_from_section(&mut self, section: &SectionContext<'a>, style: Option<SectionStyle>) {
|
||||||
|
let mut new_entries = parse_parameters(
|
||||||
|
section.following_lines_str(),
|
||||||
|
section.following_range().start(),
|
||||||
|
style,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.parameters.append(&mut new_entries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -538,10 +552,22 @@ impl<'a> DocstringSections<'a> {
|
||||||
let mut docstring_sections = Self::default();
|
let mut docstring_sections = Self::default();
|
||||||
for section in sections {
|
for section in sections {
|
||||||
match section.kind() {
|
match section.kind() {
|
||||||
SectionKind::Args | SectionKind::Arguments | SectionKind::Parameters => {
|
SectionKind::Args
|
||||||
|
| SectionKind::Arguments
|
||||||
|
| SectionKind::Parameters
|
||||||
|
| SectionKind::KeywordArgs
|
||||||
|
| SectionKind::KeywordArguments
|
||||||
|
| SectionKind::OtherArgs
|
||||||
|
| SectionKind::OtherArguments
|
||||||
|
| SectionKind::OtherParams
|
||||||
|
| SectionKind::OtherParameters => {
|
||||||
|
if let Some(ref mut parameters_section) = docstring_sections.parameters {
|
||||||
|
parameters_section.extend_from_section(§ion, style);
|
||||||
|
} else {
|
||||||
docstring_sections.parameters =
|
docstring_sections.parameters =
|
||||||
Some(ParametersSection::from_section(§ion, style));
|
Some(ParametersSection::from_section(§ion, style));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SectionKind::Raises => {
|
SectionKind::Raises => {
|
||||||
docstring_sections.raises = Some(RaisesSection::from_section(§ion, style));
|
docstring_sections.raises = Some(RaisesSection::from_section(§ion, style));
|
||||||
}
|
}
|
||||||
|
|
@ -569,11 +595,12 @@ fn parse_parameters(
|
||||||
) -> Vec<ParameterEntry<'_>> {
|
) -> Vec<ParameterEntry<'_>> {
|
||||||
match style {
|
match style {
|
||||||
Some(SectionStyle::Google) => parse_parameters_google(content, content_start),
|
Some(SectionStyle::Google) => parse_parameters_google(content, content_start),
|
||||||
|
|
||||||
Some(SectionStyle::Numpy) => parse_parameters_numpy(content, content_start),
|
Some(SectionStyle::Numpy) => parse_parameters_numpy(content, content_start),
|
||||||
None => {
|
None => {
|
||||||
let entries = parse_parameters_google(content, content_start);
|
let entries = parse_parameters_numpy(content, content_start);
|
||||||
if entries.is_empty() {
|
if entries.is_empty() {
|
||||||
parse_parameters_numpy(content, content_start)
|
parse_parameters_google(content, content_start)
|
||||||
} else {
|
} else {
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +618,11 @@ fn parse_parameters(
|
||||||
fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<ParameterEntry<'_>> {
|
fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<ParameterEntry<'_>> {
|
||||||
let mut entries: Vec<ParameterEntry> = Vec::new();
|
let mut entries: Vec<ParameterEntry> = Vec::new();
|
||||||
// Find first entry to determine indentation
|
// Find first entry to determine indentation
|
||||||
let Some(first_arg) = content.lines().next() else {
|
let Some((_, first_arg)) = content
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, line)| !line.trim().is_empty())
|
||||||
|
else {
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
let indentation = &first_arg[..first_arg.len() - first_arg.trim_start().len()];
|
let indentation = &first_arg[..first_arg.len() - first_arg.trim_start().len()];
|
||||||
|
|
@ -607,7 +638,7 @@ fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<Parame
|
||||||
.next()
|
.next()
|
||||||
.is_some_and(|first_char| !first_char.is_whitespace())
|
.is_some_and(|first_char| !first_char.is_whitespace())
|
||||||
{
|
{
|
||||||
let Some((before_colon, _)) = entry.split_once(':') else {
|
let Some((before_colon, after_colon)) = entry.split_once(':') else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(param) = before_colon.split_whitespace().next() {
|
if let Some(param) = before_colon.split_whitespace().next() {
|
||||||
|
|
@ -615,9 +646,11 @@ fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<Parame
|
||||||
if is_identifier(param_name) {
|
if is_identifier(param_name) {
|
||||||
let param_start = line_start + indentation.text_len();
|
let param_start = line_start + indentation.text_len();
|
||||||
let param_end = param_start + param.text_len();
|
let param_end = param_start + param.text_len();
|
||||||
|
let has_definition = !after_colon.trim().is_empty();
|
||||||
|
|
||||||
entries.push(ParameterEntry {
|
entries.push(ParameterEntry {
|
||||||
name: param_name,
|
name: param_name,
|
||||||
|
has_definition,
|
||||||
range: TextRange::new(
|
range: TextRange::new(
|
||||||
content_start + param_start,
|
content_start + param_start,
|
||||||
content_start + param_end,
|
content_start + param_end,
|
||||||
|
|
@ -625,6 +658,13 @@ fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<Parame
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// this is a follow up of the previous entry.
|
||||||
|
if !entry.trim().is_empty() {
|
||||||
|
if let Some(last) = entries.last_mut() {
|
||||||
|
last.has_definition = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -644,10 +684,14 @@ fn parse_parameters_google(content: &str, content_start: TextSize) -> Vec<Parame
|
||||||
fn parse_parameters_numpy(content: &str, content_start: TextSize) -> Vec<ParameterEntry<'_>> {
|
fn parse_parameters_numpy(content: &str, content_start: TextSize) -> Vec<ParameterEntry<'_>> {
|
||||||
let mut entries: Vec<ParameterEntry> = Vec::new();
|
let mut entries: Vec<ParameterEntry> = Vec::new();
|
||||||
let mut lines = content.lines();
|
let mut lines = content.lines();
|
||||||
let Some(dashes) = lines.next() else {
|
let Some(dashes_line) = lines.next() else {
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
let indentation = &dashes[..dashes.len() - dashes.trim_start().len()];
|
let dashes = dashes_line.trim_start();
|
||||||
|
if dashes.is_empty() || !dashes.chars().all(|c| c == '-') {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
let indentation = &dashes_line[..dashes_line.len() - dashes.len()];
|
||||||
|
|
||||||
let mut current_pos = content.full_line_end(dashes.text_len());
|
let mut current_pos = content.full_line_end(dashes.text_len());
|
||||||
for potential in lines {
|
for potential in lines {
|
||||||
|
|
@ -662,7 +706,6 @@ fn parse_parameters_numpy(content: &str, content_start: TextSize) -> Vec<Paramet
|
||||||
{
|
{
|
||||||
if let Some(before_colon) = entry.split(':').next() {
|
if let Some(before_colon) = entry.split(':').next() {
|
||||||
let param_line = before_colon.trim_end();
|
let param_line = before_colon.trim_end();
|
||||||
|
|
||||||
// Split on commas to handle comma-separated parameters
|
// Split on commas to handle comma-separated parameters
|
||||||
let mut current_offset = TextSize::from(0);
|
let mut current_offset = TextSize::from(0);
|
||||||
for param_part in param_line.split(',') {
|
for param_part in param_line.split(',') {
|
||||||
|
|
@ -678,6 +721,7 @@ fn parse_parameters_numpy(content: &str, content_start: TextSize) -> Vec<Paramet
|
||||||
|
|
||||||
entries.push(ParameterEntry {
|
entries.push(ParameterEntry {
|
||||||
name: param_name,
|
name: param_name,
|
||||||
|
has_definition: true,
|
||||||
range: TextRange::at(
|
range: TextRange::at(
|
||||||
content_start + param_start,
|
content_start + param_start,
|
||||||
param_part_trimmed.text_len(),
|
param_part_trimmed.text_len(),
|
||||||
|
|
@ -703,9 +747,9 @@ fn parse_raises(content: &str, style: Option<SectionStyle>) -> Vec<QualifiedName
|
||||||
Some(SectionStyle::Google) => parse_raises_google(content),
|
Some(SectionStyle::Google) => parse_raises_google(content),
|
||||||
Some(SectionStyle::Numpy) => parse_raises_numpy(content),
|
Some(SectionStyle::Numpy) => parse_raises_numpy(content),
|
||||||
None => {
|
None => {
|
||||||
let entries = parse_raises_google(content);
|
let entries = parse_raises_numpy(content);
|
||||||
if entries.is_empty() {
|
if entries.is_empty() {
|
||||||
parse_raises_numpy(content)
|
parse_raises_google(content)
|
||||||
} else {
|
} else {
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
|
|
@ -763,10 +807,14 @@ fn parse_raises_google(content: &str) -> Vec<QualifiedName<'_>> {
|
||||||
fn parse_raises_numpy(content: &str) -> Vec<QualifiedName<'_>> {
|
fn parse_raises_numpy(content: &str) -> Vec<QualifiedName<'_>> {
|
||||||
let mut entries: Vec<QualifiedName> = Vec::new();
|
let mut entries: Vec<QualifiedName> = Vec::new();
|
||||||
let mut lines = content.lines();
|
let mut lines = content.lines();
|
||||||
let Some(dashes) = lines.next() else {
|
let Some(dashes_line) = lines.next() else {
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
let indentation = &dashes[..dashes.len() - dashes.trim_start().len()];
|
let dashes = dashes_line.trim_start();
|
||||||
|
if dashes.is_empty() || !dashes.chars().all(|c| c == '-') {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
let indentation = &dashes_line[..dashes_line.len() - dashes.len()];
|
||||||
for potential in lines {
|
for potential in lines {
|
||||||
if let Some(entry) = potential.strip_prefix(indentation) {
|
if let Some(entry) = potential.strip_prefix(indentation) {
|
||||||
// Check for Sphinx directives (lines starting with ..) - these indicate the end of the
|
// Check for Sphinx directives (lines starting with ..) - these indicate the end of the
|
||||||
|
|
@ -1166,14 +1214,41 @@ fn is_generator_function_annotated_as_returning_none(
|
||||||
.is_some_and(GeneratorOrIteratorArguments::indicates_none_returned)
|
.is_some_and(GeneratorOrIteratorArguments::indicates_none_returned)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parameters_from_signature<'a>(docstring: &'a Docstring) -> Vec<&'a str> {
|
#[derive(Debug)]
|
||||||
|
struct SignatureParameter<'a> {
|
||||||
|
name: &'a str,
|
||||||
|
is_vararg: bool,
|
||||||
|
is_kwarg: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parameters_from_signature<'a>(docstring: &'a Docstring) -> Vec<SignatureParameter<'a>> {
|
||||||
let mut parameters = Vec::new();
|
let mut parameters = Vec::new();
|
||||||
let Some(function) = docstring.definition.as_function_def() else {
|
let Some(function) = docstring.definition.as_function_def() else {
|
||||||
return parameters;
|
return parameters;
|
||||||
};
|
};
|
||||||
for param in &function.parameters {
|
for param in function.parameters.iter_non_variadic_params() {
|
||||||
parameters.push(param.name());
|
parameters.push(SignatureParameter {
|
||||||
|
name: param.name(),
|
||||||
|
is_vararg: false,
|
||||||
|
is_kwarg: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(param) = function.parameters.vararg.as_ref() {
|
||||||
|
parameters.push(SignatureParameter {
|
||||||
|
name: param.name(),
|
||||||
|
is_vararg: true,
|
||||||
|
is_kwarg: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(param) = function.parameters.kwarg.as_ref() {
|
||||||
|
parameters.push(SignatureParameter {
|
||||||
|
name: param.name(),
|
||||||
|
is_vararg: false,
|
||||||
|
is_kwarg: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
parameters
|
parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1209,10 +1284,6 @@ pub(crate) fn check_docstring(
|
||||||
|
|
||||||
let semantic = checker.semantic();
|
let semantic = checker.semantic();
|
||||||
|
|
||||||
if function_type::is_stub(function_def, semantic) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prioritize the specified convention over the determined style.
|
// Prioritize the specified convention over the determined style.
|
||||||
let docstring_sections = match convention {
|
let docstring_sections = match convention {
|
||||||
Some(Convention::Google) => {
|
Some(Convention::Google) => {
|
||||||
|
|
@ -1232,6 +1303,57 @@ pub(crate) fn check_docstring(
|
||||||
|
|
||||||
let signature_parameters = parameters_from_signature(docstring);
|
let signature_parameters = parameters_from_signature(docstring);
|
||||||
|
|
||||||
|
// DOC101
|
||||||
|
if checker.settings().preview.is_enabled() {
|
||||||
|
if checker.is_rule_enabled(Rule::UndocumentedParam) {
|
||||||
|
if let Some(parameters_section) = docstring_sections.parameters.as_ref() {
|
||||||
|
let mut missing_parameters = Vec::new();
|
||||||
|
|
||||||
|
// Here we check if the function is a method (and not a staticmethod)
|
||||||
|
// in which case we skip the first argument which should be `self` or
|
||||||
|
// `cls`, and does not need to be documented.
|
||||||
|
for signature_param in signature_parameters.iter().skip(usize::from(
|
||||||
|
docstring.definition.is_method()
|
||||||
|
&& !is_staticmethod(&function_def.decorator_list, semantic),
|
||||||
|
)) {
|
||||||
|
if !(checker.settings().pydocstyle.ignore_var_parameters()
|
||||||
|
&& (signature_param.is_vararg || signature_param.is_kwarg)
|
||||||
|
|| signature_param.name.starts_with('_')
|
||||||
|
|| parameters_section.parameters.iter().any(|param| {
|
||||||
|
param.name == signature_param.name && param.has_definition
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
let name = signature_param.name;
|
||||||
|
if signature_param.is_vararg {
|
||||||
|
missing_parameters.push(format!("*{name}"));
|
||||||
|
} else if signature_param.is_kwarg {
|
||||||
|
missing_parameters.push(format!("**{name}"));
|
||||||
|
} else {
|
||||||
|
missing_parameters.push(name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !missing_parameters.is_empty() {
|
||||||
|
if let Some(definition) = docstring.definition.name() {
|
||||||
|
let names = missing_parameters.into_iter().sorted().collect();
|
||||||
|
checker.report_diagnostic(
|
||||||
|
UndocumentedParam {
|
||||||
|
definition: definition.to_string(),
|
||||||
|
names,
|
||||||
|
},
|
||||||
|
function_def.identifier(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if function_type::is_stub(function_def, semantic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// DOC201
|
// DOC201
|
||||||
if checker.is_rule_enabled(Rule::DocstringMissingReturns) {
|
if checker.is_rule_enabled(Rule::DocstringMissingReturns) {
|
||||||
if should_document_returns(function_def)
|
if should_document_returns(function_def)
|
||||||
|
|
@ -1326,7 +1448,10 @@ pub(crate) fn check_docstring(
|
||||||
if function_def.parameters.vararg.is_none() && function_def.parameters.kwarg.is_none() {
|
if function_def.parameters.vararg.is_none() && function_def.parameters.kwarg.is_none() {
|
||||||
if let Some(docstring_params) = docstring_sections.parameters {
|
if let Some(docstring_params) = docstring_sections.parameters {
|
||||||
for docstring_param in &docstring_params.parameters {
|
for docstring_param in &docstring_params.parameters {
|
||||||
if !signature_parameters.contains(&docstring_param.name) {
|
if !signature_parameters
|
||||||
|
.iter()
|
||||||
|
.any(|param| param.name == docstring_param.name)
|
||||||
|
{
|
||||||
checker.report_diagnostic(
|
checker.report_diagnostic(
|
||||||
DocstringExtraneousParameter {
|
DocstringExtraneousParameter {
|
||||||
id: docstring_param.name.to_string(),
|
id: docstring_param.name.to_string(),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
D417 Missing argument description in the docstring for `bar`: `y`
|
||||||
|
--> sections.py:292:9
|
||||||
|
|
|
||||||
|
290 | x = 1
|
||||||
|
291 |
|
||||||
|
292 | def bar(y=2): # noqa: D207, D213, D406, D407
|
||||||
|
| ^^^
|
||||||
|
293 | """Nested function test for docstrings.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `test_missing_google_args`: `y`
|
||||||
|
--> sections.py:309:5
|
||||||
|
|
|
||||||
|
307 | "(argument(s) y are missing descriptions in "
|
||||||
|
308 | "'test_missing_google_args' docstring)")
|
||||||
|
309 | def test_missing_google_args(x=1, y=2, _private=3): # noqa: D406, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
310 | """Toggle the gizmo.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z`
|
||||||
|
--> sections.py:333:9
|
||||||
|
|
|
||||||
|
331 | "(argument(s) test, y, z are missing descriptions in "
|
||||||
|
332 | "'test_missing_args' docstring)", arg_count=5)
|
||||||
|
333 | def test_missing_args(self, test, x, y, z=3, _private_arg=3): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
334 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_args_class_method`: `test`, `y`, `z`
|
||||||
|
--> sections.py:345:9
|
||||||
|
|
|
||||||
|
343 | "(argument(s) test, y, z are missing descriptions in "
|
||||||
|
344 | "'test_missing_args_class_method' docstring)", arg_count=5)
|
||||||
|
345 | def test_missing_args_class_method(cls, test, x, y, _, z=3): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
346 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `y`, `z`
|
||||||
|
--> sections.py:358:9
|
||||||
|
|
|
||||||
|
356 | "(argument(s) a, y, z are missing descriptions in "
|
||||||
|
357 | "'test_missing_args_static_method' docstring)", arg_count=4)
|
||||||
|
358 | def test_missing_args_static_method(a, x, y, _test, z=3): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
359 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_docstring`: `a`, `b`
|
||||||
|
--> sections.py:370:9
|
||||||
|
|
|
||||||
|
368 | "(argument(s) a, b are missing descriptions in "
|
||||||
|
369 | "'test_missing_docstring' docstring)", arg_count=2)
|
||||||
|
370 | def test_missing_docstring(a, b): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
371 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `test_missing_numpy_args`: `y`
|
||||||
|
--> sections.py:398:5
|
||||||
|
|
|
||||||
|
396 | "(argument(s) y are missing descriptions in "
|
||||||
|
397 | "'test_missing_numpy_args' docstring)")
|
||||||
|
398 | def test_missing_numpy_args(_private_arg=0, x=1, y=2): # noqa: D406, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
399 | """Toggle the gizmo.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z`
|
||||||
|
--> sections.py:434:9
|
||||||
|
|
|
||||||
|
432 | "(argument(s) test, y, z are missing descriptions in "
|
||||||
|
433 | "'test_missing_args' docstring)", arg_count=5)
|
||||||
|
434 | def test_missing_args(self, test, x, y, z=3, t=1, _private=0): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
435 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `z`
|
||||||
|
--> sections.py:468:9
|
||||||
|
|
|
||||||
|
466 | "(argument(s) a, z are missing descriptions in "
|
||||||
|
467 | "'test_missing_args_static_method' docstring)", arg_count=3)
|
||||||
|
468 | def test_missing_args_static_method(a, x, y, z=3, t=1): # noqa: D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
469 | """Test a valid args section.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `test_incorrect_indent`: `y`
|
||||||
|
--> sections.py:498:9
|
||||||
|
|
|
||||||
|
496 | "(argument(s) y are missing descriptions in "
|
||||||
|
497 | "'test_incorrect_indent' docstring)", arg_count=3)
|
||||||
|
498 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
499 | """Reproducing issue #437.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:1:5
|
||||||
|
|
|
||||||
|
1 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
2 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:14:5
|
||||||
|
|
|
||||||
|
14 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
15 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:27:5
|
||||||
|
|
|
||||||
|
27 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
28 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:39:5
|
||||||
|
|
|
||||||
|
39 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
40 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:52:5
|
||||||
|
|
|
||||||
|
52 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
53 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:65:5
|
||||||
|
|
|
||||||
|
65 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
66 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:77:5
|
||||||
|
|
|
||||||
|
77 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
78 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:98:5
|
||||||
|
|
|
||||||
|
98 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
99 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `*args`
|
||||||
|
--> D417.py:108:5
|
||||||
|
|
|
||||||
|
108 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
109 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:131:5
|
||||||
|
|
|
||||||
|
129 | return x, y, z
|
||||||
|
130 |
|
||||||
|
131 | def f(x):
|
||||||
|
| ^
|
||||||
|
132 | """Do something with valid description.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||||
|
--> D417.py:155:5
|
||||||
|
|
|
||||||
|
155 | def select_data(
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
156 | query: str,
|
||||||
|
157 | args: tuple,
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||||
|
--> D417.py:172:5
|
||||||
|
|
|
||||||
|
170 | """
|
||||||
|
171 |
|
||||||
|
172 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
173 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `should_fail`: `Args`
|
||||||
|
--> D417.py:199:5
|
||||||
|
|
|
||||||
|
198 | # undocumented argument with the same name as a section
|
||||||
|
199 | def should_fail(payload, Args):
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
200 | """
|
||||||
|
201 | Send a message.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:1:5
|
||||||
|
|
|
||||||
|
1 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
2 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:14:5
|
||||||
|
|
|
||||||
|
14 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
15 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:27:5
|
||||||
|
|
|
||||||
|
27 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
28 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:39:5
|
||||||
|
|
|
||||||
|
39 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
40 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:52:5
|
||||||
|
|
|
||||||
|
52 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
53 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:65:5
|
||||||
|
|
|
||||||
|
65 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
66 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:77:5
|
||||||
|
|
|
||||||
|
77 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
78 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:98:5
|
||||||
|
|
|
||||||
|
98 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
99 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:131:5
|
||||||
|
|
|
||||||
|
129 | return x, y, z
|
||||||
|
130 |
|
||||||
|
131 | def f(x):
|
||||||
|
| ^
|
||||||
|
132 | """Do something with valid description.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||||
|
--> D417.py:155:5
|
||||||
|
|
|
||||||
|
155 | def select_data(
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
156 | query: str,
|
||||||
|
157 | args: tuple,
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `should_fail`: `Args`
|
||||||
|
--> D417.py:199:5
|
||||||
|
|
|
||||||
|
198 | # undocumented argument with the same name as a section
|
||||||
|
199 | def should_fail(payload, Args):
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
200 | """
|
||||||
|
201 | Send a message.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:1:5
|
||||||
|
|
|
||||||
|
1 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
2 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:14:5
|
||||||
|
|
|
||||||
|
14 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
15 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:27:5
|
||||||
|
|
|
||||||
|
27 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
28 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:39:5
|
||||||
|
|
|
||||||
|
39 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
40 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:52:5
|
||||||
|
|
|
||||||
|
52 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
53 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:65:5
|
||||||
|
|
|
||||||
|
65 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
66 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:77:5
|
||||||
|
|
|
||||||
|
77 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
78 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:98:5
|
||||||
|
|
|
||||||
|
98 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
99 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `*args`
|
||||||
|
--> D417.py:108:5
|
||||||
|
|
|
||||||
|
108 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
109 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:131:5
|
||||||
|
|
|
||||||
|
129 | return x, y, z
|
||||||
|
130 |
|
||||||
|
131 | def f(x):
|
||||||
|
| ^
|
||||||
|
132 | """Do something with valid description.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||||
|
--> D417.py:155:5
|
||||||
|
|
|
||||||
|
155 | def select_data(
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
156 | query: str,
|
||||||
|
157 | args: tuple,
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||||
|
--> D417.py:172:5
|
||||||
|
|
|
||||||
|
170 | """
|
||||||
|
171 |
|
||||||
|
172 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
173 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `should_fail`: `Args`
|
||||||
|
--> D417.py:199:5
|
||||||
|
|
|
||||||
|
198 | # undocumented argument with the same name as a section
|
||||||
|
199 | def should_fail(payload, Args):
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
200 | """
|
||||||
|
201 | Send a message.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pydoclint/mod.rs
|
||||||
|
---
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:1:5
|
||||||
|
|
|
||||||
|
1 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
2 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:14:5
|
||||||
|
|
|
||||||
|
14 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
15 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:27:5
|
||||||
|
|
|
||||||
|
27 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
28 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||||
|
--> D417.py:39:5
|
||||||
|
|
|
||||||
|
39 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
40 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:52:5
|
||||||
|
|
|
||||||
|
52 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
53 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:65:5
|
||||||
|
|
|
||||||
|
65 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
66 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `y`
|
||||||
|
--> D417.py:77:5
|
||||||
|
|
|
||||||
|
77 | def f(x, y, z):
|
||||||
|
| ^
|
||||||
|
78 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:98:5
|
||||||
|
|
|
||||||
|
98 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
99 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `*args`
|
||||||
|
--> D417.py:108:5
|
||||||
|
|
|
||||||
|
108 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
109 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `x`
|
||||||
|
--> D417.py:131:5
|
||||||
|
|
|
||||||
|
129 | return x, y, z
|
||||||
|
130 |
|
||||||
|
131 | def f(x):
|
||||||
|
| ^
|
||||||
|
132 | """Do something with valid description.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||||
|
--> D417.py:155:5
|
||||||
|
|
|
||||||
|
155 | def select_data(
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
156 | query: str,
|
||||||
|
157 | args: tuple,
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||||
|
--> D417.py:172:5
|
||||||
|
|
|
||||||
|
170 | """
|
||||||
|
171 |
|
||||||
|
172 | def f(x, *args, **kwargs):
|
||||||
|
| ^
|
||||||
|
173 | """Do something.
|
||||||
|
|
|
||||||
|
|
||||||
|
D417 Missing argument description in the docstring for `should_fail`: `Args`
|
||||||
|
--> D417.py:199:5
|
||||||
|
|
|
||||||
|
198 | # undocumented argument with the same name as a section
|
||||||
|
199 | def should_fail(payload, Args):
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
200 | """
|
||||||
|
201 | Send a message.
|
||||||
|
|
|
||||||
|
|
@ -1243,9 +1243,9 @@ impl AlwaysFixableViolation for MissingSectionNameColon {
|
||||||
#[violation_metadata(stable_since = "v0.0.73")]
|
#[violation_metadata(stable_since = "v0.0.73")]
|
||||||
pub(crate) struct UndocumentedParam {
|
pub(crate) struct UndocumentedParam {
|
||||||
/// The name of the function being documented.
|
/// The name of the function being documented.
|
||||||
definition: String,
|
pub(crate) definition: String,
|
||||||
/// The names of the undocumented parameters.
|
/// The names of the undocumented parameters.
|
||||||
names: Vec<String>,
|
pub(crate) names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Violation for UndocumentedParam {
|
impl Violation for UndocumentedParam {
|
||||||
|
|
@ -1828,6 +1828,7 @@ fn missing_args(checker: &Checker, docstring: &Docstring, docstrings_args: &FxHa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if checker.settings().preview.is_disabled() {
|
||||||
if !missing_arg_names.is_empty() {
|
if !missing_arg_names.is_empty() {
|
||||||
if let Some(definition) = docstring.definition.name() {
|
if let Some(definition) = docstring.definition.name() {
|
||||||
let names = missing_arg_names.into_iter().sorted().collect();
|
let names = missing_arg_names.into_iter().sorted().collect();
|
||||||
|
|
@ -1841,6 +1842,7 @@ fn missing_args(checker: &Checker, docstring: &Docstring, docstrings_args: &FxHa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the parameter is annotated with `typing.Unpack`
|
/// Returns `true` if the parameter is annotated with `typing.Unpack`
|
||||||
fn has_unpack_annotation(checker: &Checker, parameter: &Parameter) -> bool {
|
fn has_unpack_annotation(checker: &Checker, parameter: &Parameter) -> bool {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue