new lint: `source_item_ordering`
This commit is contained in:
parent
15ad8245b2
commit
f7ab2c9908
|
@ -5331,6 +5331,7 @@ Released 2018-09-13
|
|||
[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
|
||||
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
|
||||
[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
|
||||
[`arbitrary_source_item_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering
|
||||
[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync
|
||||
[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
|
||||
[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
|
||||
|
@ -6208,12 +6209,14 @@ Released 2018-09-13
|
|||
[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
|
||||
[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
|
||||
[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items
|
||||
[`module-item-order-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-item-order-groupings
|
||||
[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv
|
||||
[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit
|
||||
[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior
|
||||
[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline
|
||||
[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline
|
||||
[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
|
||||
[`source-item-ordering`]: https://doc.rust-lang.org/clippy/lint_configuration.html#source-item-ordering
|
||||
[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold
|
||||
[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces
|
||||
[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold
|
||||
|
@ -6221,6 +6224,7 @@ Released 2018-09-13
|
|||
[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
|
||||
[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold
|
||||
[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold
|
||||
[`trait-assoc-item-kinds-order`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trait-assoc-item-kinds-order
|
||||
[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit
|
||||
[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold
|
||||
[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
|
||||
|
|
|
@ -666,6 +666,16 @@ crate. For example, `pub(crate)` items.
|
|||
* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
|
||||
|
||||
|
||||
## `module-item-order-groupings`
|
||||
The named groupings of different source item kinds within modules.
|
||||
|
||||
**Default Value:** `[["modules", ["extern_crate", "mod", "foreign_mod"]], ["use", ["use"]], ["macros", ["macro"]], ["global_asm", ["global_asm"]], ["UPPER_SNAKE_CASE", ["static", "const"]], ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], ["lower_snake_case", ["fn"]]]`
|
||||
|
||||
---
|
||||
**Affected lints:**
|
||||
* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
|
||||
|
||||
|
||||
## `msrv`
|
||||
The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
|
||||
|
||||
|
@ -784,6 +794,16 @@ The maximum number of single char bindings a scope may have
|
|||
* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
|
||||
|
||||
|
||||
## `source-item-ordering`
|
||||
Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`.
|
||||
|
||||
**Default Value:** `["enum", "impl", "module", "struct", "trait"]`
|
||||
|
||||
---
|
||||
**Affected lints:**
|
||||
* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
|
||||
|
||||
|
||||
## `stack-size-threshold`
|
||||
The maximum allowed stack size for functions in bytes
|
||||
|
||||
|
@ -863,6 +883,16 @@ The maximum number of lines a function or method can have
|
|||
* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
|
||||
|
||||
|
||||
## `trait-assoc-item-kinds-order`
|
||||
The order of associated items in traits.
|
||||
|
||||
**Default Value:** `["const", "type", "fn"]`
|
||||
|
||||
---
|
||||
**Affected lints:**
|
||||
* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
|
||||
|
||||
|
||||
## `trivial-copy-size-limit`
|
||||
The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
|
||||
reference. By default there is no limit
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use crate::ClippyConfiguration;
|
||||
use crate::msrvs::Msrv;
|
||||
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
|
||||
use crate::types::{
|
||||
DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering,
|
||||
SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind,
|
||||
SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edit_distance::edit_distance;
|
||||
|
@ -47,6 +51,29 @@ const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z
|
|||
const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"];
|
||||
const DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS: &[&str] =
|
||||
&["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"];
|
||||
const DEFAULT_MODULE_ITEM_ORDERING_GROUPS: &[(&str, &[SourceItemOrderingModuleItemKind])] = {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingModuleItemKind::*;
|
||||
&[
|
||||
("modules", &[ExternCrate, Mod, ForeignMod]),
|
||||
("use", &[Use]),
|
||||
("macros", &[Macro]),
|
||||
("global_asm", &[GlobalAsm]),
|
||||
("UPPER_SNAKE_CASE", &[Static, Const]),
|
||||
("PascalCase", &[TyAlias, Enum, Struct, Union, Trait, TraitAlias, Impl]),
|
||||
("lower_snake_case", &[Fn]),
|
||||
]
|
||||
};
|
||||
const DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER: &[SourceItemOrderingTraitAssocItemKind] = {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingTraitAssocItemKind::*;
|
||||
&[Const, Type, Fn]
|
||||
};
|
||||
const DEFAULT_SOURCE_ITEM_ORDERING: &[SourceItemOrderingCategory] = {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingCategory::*;
|
||||
&[Enum, Impl, Module, Struct, Trait]
|
||||
};
|
||||
|
||||
/// Conf with parse errors
|
||||
#[derive(Default)]
|
||||
|
@ -533,6 +560,9 @@ define_Conf! {
|
|||
/// crate. For example, `pub(crate)` items.
|
||||
#[lints(missing_docs_in_private_items)]
|
||||
missing_docs_in_crate_items: bool = false,
|
||||
/// The named groupings of different source item kinds within modules.
|
||||
#[lints(arbitrary_source_item_ordering)]
|
||||
module_item_order_groupings: SourceItemOrderingModuleItemGroupings = DEFAULT_MODULE_ITEM_ORDERING_GROUPS.into(),
|
||||
/// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
|
||||
#[default_text = "current version"]
|
||||
#[lints(
|
||||
|
@ -612,6 +642,9 @@ define_Conf! {
|
|||
/// The maximum number of single char bindings a scope may have
|
||||
#[lints(many_single_char_names)]
|
||||
single_char_binding_names_threshold: u64 = 4,
|
||||
/// Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`.
|
||||
#[lints(arbitrary_source_item_ordering)]
|
||||
source_item_ordering: SourceItemOrdering = DEFAULT_SOURCE_ITEM_ORDERING.into(),
|
||||
/// The maximum allowed stack size for functions in bytes
|
||||
#[lints(large_stack_frames)]
|
||||
stack_size_threshold: u64 = 512_000,
|
||||
|
@ -641,6 +674,9 @@ define_Conf! {
|
|||
/// The maximum number of lines a function or method can have
|
||||
#[lints(too_many_lines)]
|
||||
too_many_lines_threshold: u64 = 100,
|
||||
/// The order of associated items in traits.
|
||||
#[lints(arbitrary_source_item_ordering)]
|
||||
trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(),
|
||||
/// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
|
||||
/// reference. By default there is no limit
|
||||
#[default_text = "target_pointer_width * 2"]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use serde::de::{self, Deserializer, Visitor};
|
||||
use serde::{Deserialize, Serialize, ser};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
@ -102,6 +103,306 @@ impl<'de> Deserialize<'de> for MacroMatcher {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the item categories that can be ordered by the source ordering lint.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SourceItemOrderingCategory {
|
||||
Enum,
|
||||
Impl,
|
||||
Module,
|
||||
Struct,
|
||||
Trait,
|
||||
}
|
||||
|
||||
/// Represents which item categories are enabled for ordering.
|
||||
///
|
||||
/// The [`Deserialize`] implementation checks that there are no duplicates in
|
||||
/// the user configuration.
|
||||
pub struct SourceItemOrdering(Vec<SourceItemOrderingCategory>);
|
||||
|
||||
impl SourceItemOrdering {
|
||||
pub fn contains(&self, category: &SourceItemOrderingCategory) -> bool {
|
||||
self.0.contains(category)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for SourceItemOrdering
|
||||
where
|
||||
T: Into<Vec<SourceItemOrderingCategory>>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for SourceItemOrdering {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SourceItemOrdering {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let items = Vec::<SourceItemOrderingCategory>::deserialize(deserializer)?;
|
||||
let mut items_set = std::collections::HashSet::new();
|
||||
|
||||
for item in &items {
|
||||
if items_set.contains(item) {
|
||||
return Err(de::Error::custom(format!(
|
||||
"The category \"{item:?}\" was enabled more than once in the source ordering configuration."
|
||||
)));
|
||||
}
|
||||
items_set.insert(item);
|
||||
}
|
||||
|
||||
Ok(Self(items))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SourceItemOrdering {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the items that can occur within a module.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SourceItemOrderingModuleItemKind {
|
||||
ExternCrate,
|
||||
Mod,
|
||||
ForeignMod,
|
||||
Use,
|
||||
Macro,
|
||||
GlobalAsm,
|
||||
Static,
|
||||
Const,
|
||||
TyAlias,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Trait,
|
||||
TraitAlias,
|
||||
Impl,
|
||||
Fn,
|
||||
}
|
||||
|
||||
impl SourceItemOrderingModuleItemKind {
|
||||
pub fn all_variants() -> Vec<Self> {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingModuleItemKind::*;
|
||||
vec![
|
||||
ExternCrate,
|
||||
Mod,
|
||||
ForeignMod,
|
||||
Use,
|
||||
Macro,
|
||||
GlobalAsm,
|
||||
Static,
|
||||
Const,
|
||||
TyAlias,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Trait,
|
||||
TraitAlias,
|
||||
Impl,
|
||||
Fn,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the configured ordering of items within a module.
|
||||
///
|
||||
/// The [`Deserialize`] implementation checks that no item kinds have been
|
||||
/// omitted and that there are no duplicates in the user configuration.
|
||||
#[derive(Clone)]
|
||||
pub struct SourceItemOrderingModuleItemGroupings {
|
||||
groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)>,
|
||||
lut: HashMap<SourceItemOrderingModuleItemKind, usize>,
|
||||
}
|
||||
|
||||
impl SourceItemOrderingModuleItemGroupings {
|
||||
fn build_lut(
|
||||
groups: &[(String, Vec<SourceItemOrderingModuleItemKind>)],
|
||||
) -> HashMap<SourceItemOrderingModuleItemKind, usize> {
|
||||
let mut lut = HashMap::new();
|
||||
for (group_index, (_, items)) in groups.iter().enumerate() {
|
||||
for item in items {
|
||||
lut.insert(item.clone(), group_index);
|
||||
}
|
||||
}
|
||||
lut
|
||||
}
|
||||
|
||||
pub fn module_level_order_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<usize> {
|
||||
self.lut.get(item).copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrderingModuleItemGroupings {
|
||||
fn from(value: &[(&str, &[SourceItemOrderingModuleItemKind])]) -> Self {
|
||||
let groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)> =
|
||||
value.iter().map(|item| (item.0.to_string(), item.1.to_vec())).collect();
|
||||
let lut = Self::build_lut(&groups);
|
||||
Self { groups, lut }
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for SourceItemOrderingModuleItemGroupings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.groups.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let groups = Vec::<(String, Vec<SourceItemOrderingModuleItemKind>)>::deserialize(deserializer)?;
|
||||
let items_total: usize = groups.iter().map(|(_, v)| v.len()).sum();
|
||||
let lut = Self::build_lut(&groups);
|
||||
|
||||
let mut expected_items = SourceItemOrderingModuleItemKind::all_variants();
|
||||
for item in lut.keys() {
|
||||
expected_items.retain(|i| i != item);
|
||||
}
|
||||
|
||||
let all_items = SourceItemOrderingModuleItemKind::all_variants();
|
||||
if expected_items.is_empty() && items_total == all_items.len() {
|
||||
let Some(use_group_index) = lut.get(&SourceItemOrderingModuleItemKind::Use) else {
|
||||
return Err(de::Error::custom("Error in internal LUT."));
|
||||
};
|
||||
let Some((_, use_group_items)) = groups.get(*use_group_index) else {
|
||||
return Err(de::Error::custom("Error in internal LUT."));
|
||||
};
|
||||
if use_group_items.len() > 1 {
|
||||
return Err(de::Error::custom(
|
||||
"The group containing the \"use\" item kind may not contain any other item kinds. \
|
||||
The \"use\" items will (generally) be sorted by rustfmt already. \
|
||||
Therefore it makes no sense to implement linting rules that may conflict with rustfmt.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self { groups, lut })
|
||||
} else if items_total != all_items.len() {
|
||||
Err(de::Error::custom(format!(
|
||||
"Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \
|
||||
The module item kinds are: {all_items:?}"
|
||||
)))
|
||||
} else {
|
||||
Err(de::Error::custom(format!(
|
||||
"Not all module item kinds were part of the configured source ordering rule. \
|
||||
All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \
|
||||
The module item kinds are: {all_items:?}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SourceItemOrderingModuleItemGroupings {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
self.groups.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents all kinds of trait associated items.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SourceItemOrderingTraitAssocItemKind {
|
||||
Const,
|
||||
Fn,
|
||||
Type,
|
||||
}
|
||||
|
||||
impl SourceItemOrderingTraitAssocItemKind {
|
||||
pub fn all_variants() -> Vec<Self> {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingTraitAssocItemKind::*;
|
||||
vec![Const, Fn, Type]
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the order in which associated trait items should be ordered.
|
||||
///
|
||||
/// The reason to wrap a `Vec` in a newtype is to be able to implement
|
||||
/// [`Deserialize`]. Implementing `Deserialize` allows for implementing checks
|
||||
/// on configuration completeness at the time of loading the clippy config,
|
||||
/// letting the user know if there's any issues with the config (e.g. not
|
||||
/// listing all item kinds that should be sorted).
|
||||
#[derive(Clone)]
|
||||
pub struct SourceItemOrderingTraitAssocItemKinds(Vec<SourceItemOrderingTraitAssocItemKind>);
|
||||
|
||||
impl SourceItemOrderingTraitAssocItemKinds {
|
||||
pub fn index_of(&self, item: &SourceItemOrderingTraitAssocItemKind) -> Option<usize> {
|
||||
self.0.iter().position(|i| i == item)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for SourceItemOrderingTraitAssocItemKinds
|
||||
where
|
||||
T: Into<Vec<SourceItemOrderingTraitAssocItemKind>>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for SourceItemOrderingTraitAssocItemKinds {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SourceItemOrderingTraitAssocItemKinds {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let items = Vec::<SourceItemOrderingTraitAssocItemKind>::deserialize(deserializer)?;
|
||||
|
||||
let mut expected_items = SourceItemOrderingTraitAssocItemKind::all_variants();
|
||||
for item in &items {
|
||||
expected_items.retain(|i| i != item);
|
||||
}
|
||||
|
||||
let all_items = SourceItemOrderingTraitAssocItemKind::all_variants();
|
||||
if expected_items.is_empty() && items.len() == all_items.len() {
|
||||
Ok(Self(items))
|
||||
} else if items.len() != all_items.len() {
|
||||
Err(de::Error::custom(format!(
|
||||
"Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. \
|
||||
The trait associated item kinds are: {all_items:?}",
|
||||
)))
|
||||
} else {
|
||||
Err(de::Error::custom(format!(
|
||||
"Not all trait associated item kinds were part of the configured source ordering rule. \
|
||||
All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \
|
||||
The trait associated item kinds are: {all_items:?}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SourceItemOrderingTraitAssocItemKinds {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
// these impls are never actually called but are used by the various config options that default to
|
||||
// empty lists
|
||||
macro_rules! unimplemented_serialize {
|
||||
|
|
|
@ -0,0 +1,531 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_config::types::{
|
||||
SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind,
|
||||
SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds,
|
||||
};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use rustc_hir::{
|
||||
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind,
|
||||
Variant, VariantData,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
///
|
||||
/// Confirms that items are sorted in source files as per configuration.
|
||||
///
|
||||
/// ### Why restrict this?
|
||||
///
|
||||
/// Keeping a consistent ordering throughout the codebase helps with working
|
||||
/// as a team, and possibly improves maintainability of the codebase. The
|
||||
/// idea is that by defining a consistent and enforceable rule for how
|
||||
/// source files are structured, less time will be wasted during reviews on
|
||||
/// a topic that is (under most circumstances) not relevant to the logic
|
||||
/// implemented in the code. Sometimes this will be referred to as
|
||||
/// "bikeshedding".
|
||||
///
|
||||
/// ### Default Ordering and Configuration
|
||||
///
|
||||
/// As there is no generally applicable rule, and each project may have
|
||||
/// different requirements, the lint can be configured with high
|
||||
/// granularity. The configuration is split into two stages:
|
||||
///
|
||||
/// 1. Which item kinds that should have an internal order enforced.
|
||||
/// 2. Individual ordering rules per item kind.
|
||||
///
|
||||
/// The item kinds that can be linted are:
|
||||
/// - Module (with customized groupings, alphabetical within)
|
||||
/// - Trait (with customized order of associated items, alphabetical within)
|
||||
/// - Enum, Impl, Struct (purely alphabetical)
|
||||
///
|
||||
/// #### Module Item Order
|
||||
///
|
||||
/// Due to the large variation of items within modules, the ordering can be
|
||||
/// configured on a very granular level. Item kinds can be grouped together
|
||||
/// arbitrarily, items within groups will be ordered alphabetically. The
|
||||
/// following table shows the default groupings:
|
||||
///
|
||||
/// | Group | Item Kinds |
|
||||
/// |--------------------|----------------------|
|
||||
/// | `modules` | "mod", "foreign_mod" |
|
||||
/// | `use` | "use" |
|
||||
/// | `macros` | "macro" |
|
||||
/// | `global_asm` | "global_asm" |
|
||||
/// | `UPPER_SNAKE_CASE` | "static", "const" |
|
||||
/// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" |
|
||||
/// | `lower_snake_case` | "fn" |
|
||||
///
|
||||
/// All item kinds must be accounted for to create an enforceable linting
|
||||
/// rule set.
|
||||
///
|
||||
/// ### Known Problems
|
||||
///
|
||||
/// #### Performance Impact
|
||||
///
|
||||
/// Keep in mind, that ordering source code alphabetically can lead to
|
||||
/// reduced performance in cases where the most commonly used enum variant
|
||||
/// isn't the first entry anymore, and similar optimizations that can reduce
|
||||
/// branch misses, cache locality and such. Either don't use this lint if
|
||||
/// that's relevant, or disable the lint in modules or items specifically
|
||||
/// where it matters. Other solutions can be to use profile guided
|
||||
/// optimization (PGO), post-link optimization (e.g. using BOLT for LLVM),
|
||||
/// or other advanced optimization methods. A good starting point to dig
|
||||
/// into optimization is [cargo-pgo][cargo-pgo].
|
||||
///
|
||||
/// #### Lints on a Contains basis
|
||||
///
|
||||
/// The lint can be disabled only on a "contains" basis, but not per element
|
||||
/// within a "container", e.g. the lint works per-module, per-struct,
|
||||
/// per-enum, etc. but not for "don't order this particular enum variant".
|
||||
///
|
||||
/// #### Module documentation
|
||||
///
|
||||
/// Module level rustdoc comments are not part of the resulting syntax tree
|
||||
/// and as such cannot be linted from within `check_mod`. Instead, the
|
||||
/// `rustdoc::missing_documentation` lint may be used.
|
||||
///
|
||||
/// #### Module Tests
|
||||
///
|
||||
/// This lint does not implement detection of module tests (or other feature
|
||||
/// dependent elements for that matter). To lint the location of mod tests,
|
||||
/// the lint `items_after_test_module` can be used instead.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// trait TraitUnordered {
|
||||
/// const A: bool;
|
||||
/// const C: bool;
|
||||
/// const B: bool;
|
||||
///
|
||||
/// type SomeType;
|
||||
///
|
||||
/// fn a();
|
||||
/// fn c();
|
||||
/// fn b();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```no_run
|
||||
/// trait TraitOrdered {
|
||||
/// const A: bool;
|
||||
/// const B: bool;
|
||||
/// const C: bool;
|
||||
///
|
||||
/// type SomeType;
|
||||
///
|
||||
/// fn a();
|
||||
/// fn b();
|
||||
/// fn c();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [cargo-pgo]: https://github.com/Kobzol/cargo-pgo/blob/main/README.md
|
||||
///
|
||||
#[clippy::version = "1.82.0"]
|
||||
pub ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
restriction,
|
||||
"arbitrary source item ordering"
|
||||
}
|
||||
|
||||
impl_lint_pass!(ArbitrarySourceItemOrdering => [ARBITRARY_SOURCE_ITEM_ORDERING]);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::struct_excessive_bools)] // Bools are cached feature flags.
|
||||
pub struct ArbitrarySourceItemOrdering {
|
||||
assoc_types_order: SourceItemOrderingTraitAssocItemKinds,
|
||||
enable_ordering_for_enum: bool,
|
||||
enable_ordering_for_impl: bool,
|
||||
enable_ordering_for_module: bool,
|
||||
enable_ordering_for_struct: bool,
|
||||
enable_ordering_for_trait: bool,
|
||||
module_item_order_groupings: SourceItemOrderingModuleItemGroupings,
|
||||
}
|
||||
|
||||
impl ArbitrarySourceItemOrdering {
|
||||
pub fn new(conf: &'static Conf) -> Self {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingCategory::*;
|
||||
Self {
|
||||
assoc_types_order: conf.trait_assoc_item_kinds_order.clone(),
|
||||
enable_ordering_for_enum: conf.source_item_ordering.contains(&Enum),
|
||||
enable_ordering_for_impl: conf.source_item_ordering.contains(&Impl),
|
||||
enable_ordering_for_module: conf.source_item_ordering.contains(&Module),
|
||||
enable_ordering_for_struct: conf.source_item_ordering.contains(&Struct),
|
||||
enable_ordering_for_trait: conf.source_item_ordering.contains(&Trait),
|
||||
module_item_order_groupings: conf.module_item_order_groupings.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces a linting warning for incorrectly ordered impl items.
|
||||
fn lint_impl_item<T: LintContext>(&self, cx: &T, item: &ImplItemRef, before_item: &ImplItemRef) {
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
item.span,
|
||||
format!(
|
||||
"incorrect ordering of impl items (defined order: {:?})",
|
||||
self.assoc_types_order
|
||||
),
|
||||
Some(before_item.span),
|
||||
format!("should be placed before `{}`", before_item.ident.as_str(),),
|
||||
);
|
||||
}
|
||||
|
||||
/// Produces a linting warning for incorrectly ordered item members.
|
||||
fn lint_member_name<T: LintContext>(
|
||||
cx: &T,
|
||||
ident: &rustc_span::symbol::Ident,
|
||||
before_ident: &rustc_span::symbol::Ident,
|
||||
) {
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
ident.span,
|
||||
"incorrect ordering of items (must be alphabetically ordered)",
|
||||
Some(before_ident.span),
|
||||
format!("should be placed before `{}`", before_ident.as_str(),),
|
||||
);
|
||||
}
|
||||
|
||||
fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>) {
|
||||
let span = if item.ident.as_str().is_empty() {
|
||||
&item.span
|
||||
} else {
|
||||
&item.ident.span
|
||||
};
|
||||
|
||||
let (before_span, note) = if before_item.ident.as_str().is_empty() {
|
||||
(
|
||||
&before_item.span,
|
||||
"should be placed before the following item".to_owned(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
&before_item.ident.span,
|
||||
format!("should be placed before `{}`", before_item.ident.as_str(),),
|
||||
)
|
||||
};
|
||||
|
||||
// This catches false positives where generated code gets linted.
|
||||
if span == before_span {
|
||||
return;
|
||||
}
|
||||
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
*span,
|
||||
"incorrect ordering of items (must be alphabetically ordered)",
|
||||
Some(*before_span),
|
||||
note,
|
||||
);
|
||||
}
|
||||
|
||||
/// Produces a linting warning for incorrectly ordered trait items.
|
||||
fn lint_trait_item<T: LintContext>(&self, cx: &T, item: &TraitItemRef, before_item: &TraitItemRef) {
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
item.span,
|
||||
format!(
|
||||
"incorrect ordering of trait items (defined order: {:?})",
|
||||
self.assoc_types_order
|
||||
),
|
||||
Some(before_item.span),
|
||||
format!("should be placed before `{}`", before_item.ident.as_str(),),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
match &item.kind {
|
||||
ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => {
|
||||
let mut cur_v: Option<&Variant<'_>> = None;
|
||||
for variant in enum_def.variants {
|
||||
if in_external_macro(cx.sess(), variant.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(cur_v) = cur_v {
|
||||
if cur_v.ident.name.as_str() > variant.ident.name.as_str() && cur_v.span != variant.span {
|
||||
Self::lint_member_name(cx, &variant.ident, &cur_v.ident);
|
||||
}
|
||||
}
|
||||
cur_v = Some(variant);
|
||||
}
|
||||
},
|
||||
ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
|
||||
let mut cur_f: Option<&FieldDef<'_>> = None;
|
||||
for field in *fields {
|
||||
if in_external_macro(cx.sess(), field.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(cur_f) = cur_f {
|
||||
if cur_f.ident.name.as_str() > field.ident.name.as_str() && cur_f.span != field.span {
|
||||
Self::lint_member_name(cx, &field.ident, &cur_f.ident);
|
||||
}
|
||||
}
|
||||
cur_f = Some(field);
|
||||
}
|
||||
},
|
||||
ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref)
|
||||
if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
|
||||
{
|
||||
let mut cur_t: Option<&TraitItemRef> = None;
|
||||
|
||||
for item in *item_ref {
|
||||
if in_external_macro(cx.sess(), item.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(cur_t) = cur_t {
|
||||
let cur_t_kind = convert_assoc_item_kind(cur_t.kind);
|
||||
let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind);
|
||||
let item_kind = convert_assoc_item_kind(item.kind);
|
||||
let item_kind_index = self.assoc_types_order.index_of(&item_kind);
|
||||
|
||||
if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() {
|
||||
Self::lint_member_name(cx, &item.ident, &cur_t.ident);
|
||||
} else if cur_t_kind_index > item_kind_index {
|
||||
self.lint_trait_item(cx, item, cur_t);
|
||||
}
|
||||
}
|
||||
cur_t = Some(item);
|
||||
}
|
||||
},
|
||||
ItemKind::Impl(trait_impl) if self.enable_ordering_for_impl => {
|
||||
let mut cur_t: Option<&ImplItemRef> = None;
|
||||
|
||||
for item in trait_impl.items {
|
||||
if in_external_macro(cx.sess(), item.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(cur_t) = cur_t {
|
||||
let cur_t_kind = convert_assoc_item_kind(cur_t.kind);
|
||||
let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind);
|
||||
let item_kind = convert_assoc_item_kind(item.kind);
|
||||
let item_kind_index = self.assoc_types_order.index_of(&item_kind);
|
||||
|
||||
if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() {
|
||||
Self::lint_member_name(cx, &item.ident, &cur_t.ident);
|
||||
} else if cur_t_kind_index > item_kind_index {
|
||||
self.lint_impl_item(cx, item, cur_t);
|
||||
}
|
||||
}
|
||||
cur_t = Some(item);
|
||||
}
|
||||
},
|
||||
_ => {}, // Catch-all for `ItemKinds` that don't have fields.
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: HirId) {
|
||||
struct CurItem<'a> {
|
||||
item: &'a Item<'a>,
|
||||
order: usize,
|
||||
name: String,
|
||||
}
|
||||
let mut cur_t: Option<CurItem<'_>> = None;
|
||||
|
||||
if !self.enable_ordering_for_module {
|
||||
return;
|
||||
}
|
||||
|
||||
let items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id));
|
||||
|
||||
// Iterates over the items within a module.
|
||||
//
|
||||
// As of 2023-05-09, the Rust compiler will hold the entries in the same
|
||||
// order as they appear in the source code, which is convenient for us,
|
||||
// as no sorting by source map/line of code has to be applied.
|
||||
//
|
||||
for item in items {
|
||||
if in_external_macro(cx.sess(), item.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The following exceptions (skipping with `continue;`) may not be
|
||||
// complete, edge cases have not been explored further than what
|
||||
// appears in the existing code base.
|
||||
if item.ident.name == rustc_span::symbol::kw::Empty {
|
||||
if let ItemKind::Impl(_) = item.kind {
|
||||
// Sorting trait impls for unnamed types makes no sense.
|
||||
if get_item_name(item).is_empty() {
|
||||
continue;
|
||||
}
|
||||
} else if let ItemKind::ForeignMod { .. } = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::GlobalAsm(_) = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::Use(path, use_kind) = item.kind {
|
||||
if path.segments.is_empty() {
|
||||
// Use statements that contain braces get caught here.
|
||||
// They will still be linted internally.
|
||||
continue;
|
||||
} else if path.segments.len() >= 2
|
||||
&& (path.segments[0].ident.name == rustc_span::sym::std
|
||||
|| path.segments[0].ident.name == rustc_span::sym::core)
|
||||
&& path.segments[1].ident.name == rustc_span::sym::prelude
|
||||
{
|
||||
// Filters the autogenerated prelude use statement.
|
||||
// e.g. `use std::prelude::rustc_2021`
|
||||
} else if use_kind == UseKind::Glob {
|
||||
// Filters glob kinds of uses.
|
||||
// e.g. `use std::sync::*`
|
||||
} else {
|
||||
// This can be used for debugging.
|
||||
// println!("Unknown autogenerated use statement: {:?}", item);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if item.ident.name.as_str().starts_with('_') {
|
||||
// Filters out unnamed macro-like impls for various derives,
|
||||
// e.g. serde::Serialize or num_derive::FromPrimitive.
|
||||
continue;
|
||||
}
|
||||
|
||||
if item.ident.name == rustc_span::sym::std && item.span.is_dummy() {
|
||||
if let ItemKind::ExternCrate(None) = item.kind {
|
||||
// Filters the auto-included Rust standard library.
|
||||
continue;
|
||||
}
|
||||
println!("Unknown item: {item:?}");
|
||||
}
|
||||
|
||||
let item_kind = convert_module_item_kind(&item.kind);
|
||||
let module_level_order = self
|
||||
.module_item_order_groupings
|
||||
.module_level_order_of(&item_kind)
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(cur_t) = cur_t.as_ref() {
|
||||
use std::cmp::Ordering; // Better legibility.
|
||||
match module_level_order.cmp(&cur_t.order) {
|
||||
Ordering::Less => {
|
||||
Self::lint_member_item(cx, item, cur_t.item);
|
||||
},
|
||||
Ordering::Equal if item_kind == SourceItemOrderingModuleItemKind::Use => {
|
||||
// Skip ordering use statements, as these should be ordered by rustfmt.
|
||||
},
|
||||
Ordering::Equal if cur_t.name > get_item_name(item) => {
|
||||
Self::lint_member_item(cx, item, cur_t.item);
|
||||
},
|
||||
Ordering::Equal | Ordering::Greater => {
|
||||
// Nothing to do in this case, they're already in the right order.
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Makes a note of the current item for comparison with the next.
|
||||
cur_t = Some(CurItem {
|
||||
order: module_level_order,
|
||||
item,
|
||||
name: get_item_name(item),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a [`rustc_hir::AssocItemKind`] to a
|
||||
/// [`SourceItemOrderingTraitAssocItemKind`].
|
||||
///
|
||||
/// This is implemented here because `rustc_hir` is not a dependency of
|
||||
/// `clippy_config`.
|
||||
fn convert_assoc_item_kind(value: AssocItemKind) -> SourceItemOrderingTraitAssocItemKind {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingTraitAssocItemKind::*;
|
||||
match value {
|
||||
AssocItemKind::Const { .. } => Const,
|
||||
AssocItemKind::Type { .. } => Type,
|
||||
AssocItemKind::Fn { .. } => Fn,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a [`rustc_hir::ItemKind`] to a
|
||||
/// [`SourceItemOrderingModuleItemKind`].
|
||||
///
|
||||
/// This is implemented here because `rustc_hir` is not a dependency of
|
||||
/// `clippy_config`.
|
||||
fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleItemKind {
|
||||
#[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
|
||||
use SourceItemOrderingModuleItemKind::*;
|
||||
match value {
|
||||
ItemKind::ExternCrate(..) => ExternCrate,
|
||||
ItemKind::Use(..) => Use,
|
||||
ItemKind::Static(..) => Static,
|
||||
ItemKind::Const(..) => Const,
|
||||
ItemKind::Fn(..) => Fn,
|
||||
ItemKind::Macro(..) => Macro,
|
||||
ItemKind::Mod(..) => Mod,
|
||||
ItemKind::ForeignMod { .. } => ForeignMod,
|
||||
ItemKind::GlobalAsm(..) => GlobalAsm,
|
||||
ItemKind::TyAlias(..) => TyAlias,
|
||||
ItemKind::Enum(..) => Enum,
|
||||
ItemKind::Struct(..) => Struct,
|
||||
ItemKind::Union(..) => Union,
|
||||
ItemKind::Trait(..) => Trait,
|
||||
ItemKind::TraitAlias(..) => TraitAlias,
|
||||
ItemKind::Impl(..) => Impl,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the item name for sorting purposes, which in the general case is
|
||||
/// `item.ident.name`.
|
||||
///
|
||||
/// For trait impls, the name used for sorting will be the written path of
|
||||
/// `item.self_ty` plus the written path of `item.of_trait`, joined with
|
||||
/// exclamation marks. Exclamation marks are used because they are the first
|
||||
/// printable ASCII character.
|
||||
///
|
||||
/// Trait impls generated using a derive-macro will have their path rewritten,
|
||||
/// such that for example `Default` is `$crate::default::Default`, and
|
||||
/// `std::clone::Clone` is `$crate::clone::Clone`. This behaviour is described
|
||||
/// further in the [Rust Reference, Paths Chapter][rust_ref].
|
||||
///
|
||||
/// [rust_ref]: https://doc.rust-lang.org/reference/paths.html#crate-1
|
||||
fn get_item_name(item: &Item<'_>) -> String {
|
||||
match item.kind {
|
||||
ItemKind::Impl(im) => {
|
||||
if let TyKind::Path(path) = im.self_ty.kind {
|
||||
match path {
|
||||
QPath::Resolved(_, path) => {
|
||||
let segs = path.segments.iter();
|
||||
let mut segs: Vec<String> = segs.map(|s| s.ident.name.as_str().to_owned()).collect();
|
||||
|
||||
if let Some(of_trait) = im.of_trait {
|
||||
let mut trait_segs: Vec<String> = of_trait
|
||||
.path
|
||||
.segments
|
||||
.iter()
|
||||
.map(|s| s.ident.name.as_str().to_owned())
|
||||
.collect();
|
||||
segs.append(&mut trait_segs);
|
||||
}
|
||||
|
||||
segs.push(String::new());
|
||||
segs.join("!!")
|
||||
},
|
||||
QPath::TypeRelative(_, _path_seg) => {
|
||||
// This case doesn't exist in the clippy tests codebase.
|
||||
String::new()
|
||||
},
|
||||
QPath::LangItem(_, _) => String::new(),
|
||||
}
|
||||
} else {
|
||||
// Impls for anything that isn't a named type can be skipped.
|
||||
String::new()
|
||||
}
|
||||
},
|
||||
_ => item.ident.name.as_str().to_owned(),
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::absolute_paths::ABSOLUTE_PATHS_INFO,
|
||||
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
|
||||
crate::approx_const::APPROX_CONSTANT_INFO,
|
||||
crate::arbitrary_source_item_ordering::ARBITRARY_SOURCE_ITEM_ORDERING_INFO,
|
||||
crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO,
|
||||
crate::as_conversions::AS_CONVERSIONS_INFO,
|
||||
crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
|
||||
|
|
|
@ -72,6 +72,7 @@ pub mod deprecated_lints;
|
|||
mod absolute_paths;
|
||||
mod almost_complete_range;
|
||||
mod approx_const;
|
||||
mod arbitrary_source_item_ordering;
|
||||
mod arc_with_non_send_sync;
|
||||
mod as_conversions;
|
||||
mod asm_syntax;
|
||||
|
@ -949,5 +950,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
|||
store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf)));
|
||||
store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp));
|
||||
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
|
||||
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
trait-assoc-item-kinds-order = ["fn", "type", "const", "type"]
|
|
@ -0,0 +1 @@
|
|||
trait-assoc-item-kinds-order = ["const", "type"]
|
|
@ -0,0 +1 @@
|
|||
source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"]
|
|
@ -0,0 +1,12 @@
|
|||
trait-assoc-item-kinds-order = ["const", "type", "fn"]
|
||||
source-item-ordering = ["enum", "impl", "module", "struct", "trait"]
|
||||
module-item-order-groupings = [
|
||||
["modules", ["extern_crate", "mod", "foreign_mod"]],
|
||||
["use", ["use"]],
|
||||
["macros", ["macro"]],
|
||||
["global_asm", ["global_asm"]],
|
||||
["UPPER_SNAKE_CASE", ["static", "const"]],
|
||||
["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]],
|
||||
["lower_snake_case", ["fn"]]
|
||||
]
|
||||
|
|
@ -0,0 +1 @@
|
|||
source-item-ordering = ["enum"]
|
|
@ -0,0 +1 @@
|
|||
source-item-ordering = ["impl"]
|
|
@ -0,0 +1 @@
|
|||
source-item-ordering = ["trait"]
|
|
@ -0,0 +1,8 @@
|
|||
error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type]
|
||||
--> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml:1:32
|
||||
|
|
||||
LL | trait-assoc-item-kinds-order = ["fn", "type", "const", "type"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type]
|
||||
--> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml:1:32
|
||||
|
|
||||
LL | trait-assoc-item-kinds-order = ["const", "type"]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
error: error reading Clippy's configuration file: The category "Struct" was enabled more than once in the source ordering configuration.
|
||||
--> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml:1:24
|
||||
|
|
||||
LL | source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3
|
||||
//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default
|
||||
//@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp
|
||||
//@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1
|
||||
//@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2
|
||||
//@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
/// This module gets linted before clippy gives up.
|
||||
mod i_am_just_right {
|
||||
const AFTER: i8 = 0;
|
||||
|
||||
const BEFORE: i8 = 0;
|
||||
}
|
||||
|
||||
/// Since the upper module passes linting, the lint now recurses into this module.
|
||||
mod this_is_in_the_wrong_position {
|
||||
const A: i8 = 1;
|
||||
const C: i8 = 0;
|
||||
}
|
||||
|
||||
// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
|
||||
const SNAKE_CASE: &str = "zzzzzzzz";
|
||||
|
||||
const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
|
||||
|
||||
const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
|
||||
|
||||
trait BasicEmptyTrait {}
|
||||
|
||||
trait CloneSelf {
|
||||
fn clone_self(&self) -> Self;
|
||||
}
|
||||
|
||||
enum EnumOrdered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
#[allow(clippy::arbitrary_source_item_ordering)]
|
||||
enum EnumUnorderedAllowed {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
struct StructOrdered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
}
|
||||
|
||||
impl BasicEmptyTrait for StructOrdered {}
|
||||
|
||||
impl CloneSelf for StructOrdered {
|
||||
fn clone_self(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StructOrdered {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for StructOrdered {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct StructUnordered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TraitUnordered for StructUnordered {
|
||||
const A: bool = false;
|
||||
const B: bool = false;
|
||||
const C: bool = false;
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
fn c() {}
|
||||
}
|
||||
|
||||
impl TraitUnorderedItemKinds for StructUnordered {
|
||||
const A: bool = false;
|
||||
const B: bool = false;
|
||||
const C: bool = false;
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
fn c() {}
|
||||
}
|
||||
|
||||
struct StructUnorderedGeneric<T> {
|
||||
_1: std::marker::PhantomData<T>,
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
trait TraitOrdered {
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
}
|
||||
|
||||
#[derive(std::clone::Clone, Default)]
|
||||
struct ZisShouldBeBeforeZeMainFn;
|
||||
|
||||
fn main() {
|
||||
// test code goes here
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const B: i8 = 1;
|
||||
|
||||
const A: i8 = 0;
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: var_1
|
||||
//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
/// This module gets linted before clippy gives up.
|
||||
mod i_am_just_right {
|
||||
const AFTER: i8 = 0;
|
||||
|
||||
const BEFORE: i8 = 0;
|
||||
}
|
||||
|
||||
/// Since the upper module passes linting, the lint now recurses into this module.
|
||||
mod this_is_in_the_wrong_position {
|
||||
const A: i8 = 1;
|
||||
const C: i8 = 0;
|
||||
}
|
||||
|
||||
// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
|
||||
const SNAKE_CASE: &str = "zzzzzzzz";
|
||||
|
||||
const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
|
||||
|
||||
const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
|
||||
|
||||
trait BasicEmptyTrait {}
|
||||
|
||||
trait CloneSelf {
|
||||
fn clone_self(&self) -> Self;
|
||||
}
|
||||
|
||||
enum EnumOrdered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
#[allow(clippy::arbitrary_source_item_ordering)]
|
||||
enum EnumUnorderedAllowed {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
struct StructOrdered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
}
|
||||
|
||||
impl BasicEmptyTrait for StructOrdered {}
|
||||
|
||||
impl CloneSelf for StructOrdered {
|
||||
fn clone_self(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StructOrdered {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for StructOrdered {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct StructUnordered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TraitUnordered for StructUnordered {
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
fn c() {}
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
const A: bool = false;
|
||||
const B: bool = false;
|
||||
const C: bool = false;
|
||||
}
|
||||
|
||||
impl TraitUnorderedItemKinds for StructUnordered {
|
||||
fn a() {}
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
const A: bool = false;
|
||||
}
|
||||
|
||||
struct StructUnorderedGeneric<T> {
|
||||
_1: std::marker::PhantomData<T>,
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
trait TraitOrdered {
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
fn a();
|
||||
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
}
|
||||
|
||||
#[derive(std::clone::Clone, Default)]
|
||||
struct ZisShouldBeBeforeZeMainFn;
|
||||
|
||||
fn main() {
|
||||
// test code goes here
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const B: i8 = 1;
|
||||
|
||||
const A: i8 = 0;
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:21:14
|
||||
|
|
||||
LL | use std::rc::Weak;
|
||||
| ^^^^
|
||||
|
|
||||
note: should be placed before `SNAKE_CASE`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:19:7
|
||||
|
|
||||
LL | const SNAKE_CASE: &str = "zzzzzzzz";
|
||||
| ^^^^^^^^^^
|
||||
= note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:64:1
|
||||
|
|
||||
LL | / impl CloneSelf for StructOrdered {
|
||||
LL | | fn clone_self(&self) -> Self {
|
||||
LL | | Self {
|
||||
LL | | a: true,
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: should be placed before the following item
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:54:1
|
||||
|
|
||||
LL | / impl Default for StructOrdered {
|
||||
LL | | fn default() -> Self {
|
||||
LL | | Self {
|
||||
LL | | a: true,
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7
|
||||
|
|
||||
LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `TraitUnorderedItemKinds`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:7
|
||||
|
|
||||
LL | trait TraitUnorderedItemKinds {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:1
|
||||
|
|
||||
LL | impl BasicEmptyTrait for StructOrdered {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before the following item
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:138:1
|
||||
|
|
||||
LL | / impl TraitUnordered for StructUnordered {
|
||||
LL | | const A: bool = false;
|
||||
LL | | const C: bool = false;
|
||||
LL | | const B: bool = false;
|
||||
... |
|
||||
LL | | fn b() {}
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:5
|
||||
|
|
||||
LL | mod this_is_in_the_wrong_position {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `main`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:4
|
||||
|
|
||||
LL | fn main() {
|
||||
| ^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:7
|
||||
|
|
||||
LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `ZisShouldBeBeforeZeMainFn`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8
|
||||
|
|
||||
LL | struct ZisShouldBeBeforeZeMainFn;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11
|
||||
|
|
||||
LL | const AFTER: i8 = 0;
|
||||
| ^^^^^
|
||||
|
|
||||
note: should be placed before `BEFORE`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:10:11
|
||||
|
|
||||
LL | const BEFORE: i8 = 0;
|
||||
| ^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:38:5
|
||||
|
|
||||
LL | B,
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:37:5
|
||||
|
|
||||
LL | C,
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:88:5
|
||||
|
|
||||
LL | b: bool,
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:87:5
|
||||
|
|
||||
LL | c: bool,
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5
|
||||
|
|
||||
LL | b: bool,
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5
|
||||
|
|
||||
LL | c: bool,
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:115:11
|
||||
|
|
||||
LL | const B: bool;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:114:11
|
||||
|
|
||||
LL | const C: bool;
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:8
|
||||
|
|
||||
LL | fn b();
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:8
|
||||
|
|
||||
LL | fn c();
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of trait items (defined order: [Const, Type, Fn])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:5
|
||||
|
|
||||
LL | const A: bool;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:5
|
||||
|
|
||||
LL | type SomeType;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11
|
||||
|
|
||||
LL | const B: bool = false;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11
|
||||
|
|
||||
LL | const C: bool = false;
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8
|
||||
|
|
||||
LL | fn b() {}
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8
|
||||
|
|
||||
LL | fn c() {}
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:156:5
|
||||
|
|
||||
LL | const A: bool = false;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5
|
||||
|
|
||||
LL | type SomeType = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:172:11
|
||||
|
|
||||
LL | const A: i8 = 1;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11
|
||||
|
|
||||
LL | const C: i8 = 0;
|
||||
| ^
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: default
|
||||
//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
/// This module gets linted before clippy gives up.
|
||||
mod i_am_just_right {
|
||||
const BEFORE: i8 = 0;
|
||||
|
||||
const AFTER: i8 = 0;
|
||||
}
|
||||
|
||||
// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
|
||||
const SNAKE_CASE: &str = "zzzzzzzz";
|
||||
|
||||
use std::rc::Weak;
|
||||
|
||||
trait BasicEmptyTrait {}
|
||||
|
||||
trait CloneSelf {
|
||||
fn clone_self(&self) -> Self;
|
||||
}
|
||||
|
||||
enum EnumOrdered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
A,
|
||||
C,
|
||||
B,
|
||||
}
|
||||
|
||||
#[allow(clippy::arbitrary_source_item_ordering)]
|
||||
enum EnumUnorderedAllowed {
|
||||
A,
|
||||
C,
|
||||
B,
|
||||
}
|
||||
|
||||
struct StructOrdered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
}
|
||||
|
||||
impl Default for StructOrdered {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CloneSelf for StructOrdered {
|
||||
fn clone_self(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for StructOrdered {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct StructUnordered {
|
||||
a: bool,
|
||||
c: bool,
|
||||
b: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
struct StructUnorderedGeneric<T> {
|
||||
_1: std::marker::PhantomData<T>,
|
||||
a: bool,
|
||||
c: bool,
|
||||
b: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
trait TraitOrdered {
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
const A: bool;
|
||||
const C: bool;
|
||||
const B: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn c();
|
||||
fn b();
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
}
|
||||
|
||||
const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
|
||||
|
||||
impl TraitUnordered for StructUnordered {
|
||||
const A: bool = false;
|
||||
const C: bool = false;
|
||||
const B: bool = false;
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
fn a() {}
|
||||
fn c() {}
|
||||
fn b() {}
|
||||
}
|
||||
|
||||
// Trait impls should be located just after the type they implement it for.
|
||||
impl BasicEmptyTrait for StructOrdered {}
|
||||
|
||||
impl TraitUnorderedItemKinds for StructUnordered {
|
||||
type SomeType = ();
|
||||
|
||||
const A: bool = false;
|
||||
const B: bool = false;
|
||||
const C: bool = false;
|
||||
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
fn c() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// test code goes here
|
||||
}
|
||||
|
||||
/// Note that the linting pass is stopped before recursing into this module.
|
||||
mod this_is_in_the_wrong_position {
|
||||
const C: i8 = 0;
|
||||
const A: i8 = 1;
|
||||
}
|
||||
|
||||
#[derive(Default, std::clone::Clone)]
|
||||
struct ZisShouldBeBeforeZeMainFn;
|
||||
|
||||
const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const B: i8 = 1;
|
||||
|
||||
const A: i8 = 0;
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: var_1
|
||||
//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
/// This module gets linted before clippy gives up.
|
||||
mod i_am_just_right {
|
||||
const AFTER: i8 = 0;
|
||||
|
||||
const BEFORE: i8 = 0;
|
||||
}
|
||||
|
||||
/// Since the upper module passes linting, the lint now recurses into this module.
|
||||
mod this_is_in_the_wrong_position {
|
||||
const A: i8 = 1;
|
||||
const C: i8 = 0;
|
||||
}
|
||||
|
||||
// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
|
||||
const SNAKE_CASE: &str = "zzzzzzzz";
|
||||
|
||||
const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
|
||||
|
||||
const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
|
||||
|
||||
trait BasicEmptyTrait {}
|
||||
|
||||
trait CloneSelf {
|
||||
fn clone_self(&self) -> Self;
|
||||
}
|
||||
|
||||
enum EnumOrdered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
#[allow(clippy::arbitrary_source_item_ordering)]
|
||||
enum EnumUnorderedAllowed {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
struct StructOrdered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
}
|
||||
|
||||
impl BasicEmptyTrait for StructOrdered {}
|
||||
|
||||
impl CloneSelf for StructOrdered {
|
||||
fn clone_self(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StructOrdered {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for StructOrdered {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct StructUnordered {
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
impl TraitUnordered for StructUnordered {
|
||||
fn a() {}
|
||||
fn c() {}
|
||||
fn b() {}
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
const A: bool = false;
|
||||
const C: bool = false;
|
||||
const B: bool = false;
|
||||
}
|
||||
|
||||
impl TraitUnorderedItemKinds for StructUnordered {
|
||||
const A: bool = false;
|
||||
|
||||
type SomeType = ();
|
||||
|
||||
fn a() {}
|
||||
}
|
||||
|
||||
struct StructUnorderedGeneric<T> {
|
||||
_1: std::marker::PhantomData<T>,
|
||||
a: bool,
|
||||
b: bool,
|
||||
c: bool,
|
||||
d: bool,
|
||||
}
|
||||
|
||||
trait TraitOrdered {
|
||||
fn a();
|
||||
fn b();
|
||||
fn c();
|
||||
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
const C: bool;
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
fn a();
|
||||
fn c();
|
||||
fn b();
|
||||
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
const C: bool;
|
||||
const B: bool;
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
const A: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
}
|
||||
|
||||
#[derive(std::clone::Clone, Default)]
|
||||
struct ZisShouldBeBeforeZeMainFn;
|
||||
|
||||
fn main() {
|
||||
// test code goes here
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const B: i8 = 1;
|
||||
|
||||
const A: i8 = 0;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:105:8
|
||||
|
|
||||
LL | fn b() {}
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:104:8
|
||||
|
|
||||
LL | fn c() {}
|
||||
| ^
|
||||
= note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11
|
||||
|
|
||||
LL | const B: bool = false;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:110:11
|
||||
|
|
||||
LL | const C: bool = false;
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of impl items (defined order: [Fn, Type, Const])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5
|
||||
|
|
||||
LL | type SomeType = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `A`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:115:5
|
||||
|
|
||||
LL | const A: bool = false;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of impl items (defined order: [Fn, Type, Const])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5
|
||||
|
|
||||
LL | fn a() {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5
|
||||
|
|
||||
LL | type SomeType = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:145:8
|
||||
|
|
||||
LL | fn b();
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `c`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:144:8
|
||||
|
|
||||
LL | fn c();
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:151:11
|
||||
|
|
||||
LL | const B: bool;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `C`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:150:11
|
||||
|
|
||||
LL | const C: bool;
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of trait items (defined order: [Fn, Type, Const])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5
|
||||
|
|
||||
LL | type SomeType;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `A`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:5
|
||||
|
|
||||
LL | const A: bool;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of trait items (defined order: [Fn, Type, Const])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:159:5
|
||||
|
|
||||
LL | fn a();
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5
|
||||
|
|
||||
LL | type SomeType;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:22:5
|
||||
|
|
||||
LL | A,
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `B`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:21:5
|
||||
|
|
||||
LL | B,
|
||||
| ^
|
||||
= note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: only_enum
|
||||
//@[only_enum] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_enum
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct StructUnordered {
|
||||
b: bool,
|
||||
a: bool,
|
||||
}
|
||||
|
||||
enum EnumOrdered {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
B,
|
||||
A,
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
const B: bool;
|
||||
const A: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn b();
|
||||
fn a();
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
|
||||
fn a();
|
||||
}
|
||||
|
||||
const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
|
|
@ -0,0 +1,40 @@
|
|||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:8
|
||||
|
|
||||
LL | fn a() {}
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `b`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:8
|
||||
|
|
||||
LL | fn b() {}
|
||||
| ^
|
||||
= note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
|
||||
|
||||
error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5
|
||||
|
|
||||
LL | type SomeType = i8;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `a`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:5
|
||||
|
|
||||
LL | fn a() {}
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:47:5
|
||||
|
|
||||
LL | const A: bool = true;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5
|
||||
|
|
||||
LL | type SomeType = i8;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: only_impl
|
||||
//@[only_impl] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_impl
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct StructUnordered {
|
||||
b: bool,
|
||||
a: bool,
|
||||
}
|
||||
|
||||
struct BasicStruct {}
|
||||
|
||||
trait BasicTrait {
|
||||
const A: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn b();
|
||||
fn a();
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
B,
|
||||
A,
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
const B: bool;
|
||||
const A: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn b();
|
||||
fn a();
|
||||
}
|
||||
|
||||
impl BasicTrait for StructUnordered {
|
||||
fn b() {}
|
||||
fn a() {}
|
||||
|
||||
type SomeType = i8;
|
||||
|
||||
const A: bool = true;
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
|
||||
fn a();
|
||||
}
|
||||
|
||||
const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
|
||||
|
||||
impl BasicTrait for BasicStruct {
|
||||
const A: bool = true;
|
||||
|
||||
type SomeType = i8;
|
||||
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:32:11
|
||||
|
|
||||
LL | const A: bool;
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `B`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:31:11
|
||||
|
|
||||
LL | const B: bool;
|
||||
| ^
|
||||
= note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
|
||||
|
||||
error: incorrect ordering of items (must be alphabetically ordered)
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8
|
||||
|
|
||||
LL | fn a();
|
||||
| ^
|
||||
|
|
||||
note: should be placed before `b`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:36:8
|
||||
|
|
||||
LL | fn b();
|
||||
| ^
|
||||
|
||||
error: incorrect ordering of trait items (defined order: [Const, Type, Fn])
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5
|
||||
|
|
||||
LL | const A: bool;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: should be placed before `SomeType`
|
||||
--> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:41:5
|
||||
|
|
||||
LL | type SomeType;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
//@aux-build:../../ui/auxiliary/proc_macros.rs
|
||||
//@revisions: only_trait
|
||||
//@[only_trait] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_trait
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::arbitrary_source_item_ordering)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct StructUnordered {
|
||||
b: bool,
|
||||
a: bool,
|
||||
}
|
||||
|
||||
trait TraitOrdered {
|
||||
const A: bool;
|
||||
const B: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn a();
|
||||
fn b();
|
||||
}
|
||||
|
||||
enum EnumUnordered {
|
||||
B,
|
||||
A,
|
||||
}
|
||||
|
||||
trait TraitUnordered {
|
||||
const B: bool;
|
||||
const A: bool;
|
||||
|
||||
type SomeType;
|
||||
|
||||
fn b();
|
||||
fn a();
|
||||
}
|
||||
|
||||
trait TraitUnorderedItemKinds {
|
||||
type SomeType;
|
||||
|
||||
const A: bool;
|
||||
|
||||
fn a();
|
||||
}
|
||||
|
||||
const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
|
|
@ -0,0 +1 @@
|
|||
trait-assoc-item-kinds-order = ["fn", "type", "const"]
|
|
@ -54,12 +54,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
|
|||
max-trait-bounds
|
||||
min-ident-chars-threshold
|
||||
missing-docs-in-crate-items
|
||||
module-item-order-groupings
|
||||
msrv
|
||||
pass-by-value-size-limit
|
||||
pub-underscore-fields-behavior
|
||||
semicolon-inside-block-ignore-singleline
|
||||
semicolon-outside-block-ignore-multiline
|
||||
single-char-binding-names-threshold
|
||||
source-item-ordering
|
||||
stack-size-threshold
|
||||
standard-macro-braces
|
||||
struct-field-name-threshold
|
||||
|
@ -68,6 +70,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
|
|||
too-large-for-stack
|
||||
too-many-arguments-threshold
|
||||
too-many-lines-threshold
|
||||
trait-assoc-item-kinds-order
|
||||
trivial-copy-size-limit
|
||||
type-complexity-threshold
|
||||
unnecessary-box-size
|
||||
|
@ -138,12 +141,14 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
|
|||
max-trait-bounds
|
||||
min-ident-chars-threshold
|
||||
missing-docs-in-crate-items
|
||||
module-item-order-groupings
|
||||
msrv
|
||||
pass-by-value-size-limit
|
||||
pub-underscore-fields-behavior
|
||||
semicolon-inside-block-ignore-singleline
|
||||
semicolon-outside-block-ignore-multiline
|
||||
single-char-binding-names-threshold
|
||||
source-item-ordering
|
||||
stack-size-threshold
|
||||
standard-macro-braces
|
||||
struct-field-name-threshold
|
||||
|
@ -152,6 +157,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
|
|||
too-large-for-stack
|
||||
too-many-arguments-threshold
|
||||
too-many-lines-threshold
|
||||
trait-assoc-item-kinds-order
|
||||
trivial-copy-size-limit
|
||||
type-complexity-threshold
|
||||
unnecessary-box-size
|
||||
|
@ -222,12 +228,14 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
|
|||
max-trait-bounds
|
||||
min-ident-chars-threshold
|
||||
missing-docs-in-crate-items
|
||||
module-item-order-groupings
|
||||
msrv
|
||||
pass-by-value-size-limit
|
||||
pub-underscore-fields-behavior
|
||||
semicolon-inside-block-ignore-singleline
|
||||
semicolon-outside-block-ignore-multiline
|
||||
single-char-binding-names-threshold
|
||||
source-item-ordering
|
||||
stack-size-threshold
|
||||
standard-macro-braces
|
||||
struct-field-name-threshold
|
||||
|
@ -236,6 +244,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
|
|||
too-large-for-stack
|
||||
too-many-arguments-threshold
|
||||
too-many-lines-threshold
|
||||
trait-assoc-item-kinds-order
|
||||
trivial-copy-size-limit
|
||||
type-complexity-threshold
|
||||
unnecessary-box-size
|
||||
|
|
Loading…
Reference in New Issue