aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Banks <_@jeremy.ca>2019-05-11 10:52:18 -0400
committerJeremy Banks <_@jeremy.ca>2019-05-11 11:07:51 -0400
commitc41add741dbe4a97fb04d5236ba91f87ca567b4e (patch)
tree5bc1079fa5173d1a4ece44f78119cc99f64f1e85 /src
parent320efb2ae98e815be196609d7ba600a78cf6727f (diff)
downloadremain-c41add741dbe4a97fb04d5236ba91f87ca567b4e.tar.gz
Add support for sorting named struct fields.
Diffstat (limited to 'src')
-rw-r--r--src/check.rs17
-rw-r--r--src/emit.rs5
-rw-r--r--src/lib.rs6
-rw-r--r--src/parse.rs14
4 files changed, 34 insertions, 8 deletions
diff --git a/src/check.rs b/src/check.rs
index 281c052..1b50442 100644
--- a/src/check.rs
+++ b/src/check.rs
@@ -1,5 +1,5 @@
use syn::{Arm, Ident, Result, Variant};
-use syn::{Error, Pat, PatIdent};
+use syn::{Error, Field, Fields, Pat, PatIdent};
use crate::compare::Path;
use crate::format;
@@ -8,6 +8,13 @@ use crate::parse::Input::{self, *};
pub fn sorted(input: Input) -> Result<()> {
let paths = match input {
Enum(item) => collect_paths(item.variants)?,
+ Struct(item) => {
+ if let Fields::Named(fields) = item.fields {
+ collect_paths(fields.named)?
+ } else {
+ unreachable!("must be named field")
+ }
+ }
Match(expr) | Let(expr) => collect_paths(expr.arms)?,
};
@@ -44,6 +51,14 @@ impl IntoPath for Variant {
}
}
+impl IntoPath for Field {
+ fn into_path(self) -> Result<Path> {
+ Ok(Path {
+ segments: vec![self.ident.expect("must be named field")],
+ })
+ }
+}
+
impl IntoPath for Arm {
fn into_path(self) -> Result<Path> {
// Sort by just the first pat.
diff --git a/src/emit.rs b/src/emit.rs
index b98ad1d..d1ddda8 100644
--- a/src/emit.rs
+++ b/src/emit.rs
@@ -7,6 +7,7 @@ use syn::Error;
pub enum Kind {
Enum,
Match,
+ Struct,
Let,
}
@@ -21,7 +22,7 @@ pub fn emit(err: Error, kind: Kind, original: TokenStream) -> TokenStream {
let original = proc_macro2::TokenStream::from(original);
let expanded = match kind {
- Kind::Enum | Kind::Let => quote!(#err #original),
+ Kind::Enum | Kind::Let | Kind::Struct => quote!(#err #original),
Kind::Match => quote!({ #err #original }),
};
@@ -32,7 +33,7 @@ pub fn emit(err: Error, kind: Kind, original: TokenStream) -> TokenStream {
// https://github.com/rust-lang/rust/issues/43081
fn probably_has_spans(kind: Kind) -> bool {
match kind {
- Kind::Enum => true,
+ Kind::Enum | Kind::Struct => true,
Kind::Match | Kind::Let => false,
}
}
diff --git a/src/lib.rs b/src/lib.rs
index dc1ab0b..4034303 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,8 +4,8 @@
//!
//! # Syntax
//!
-//! Place a `#[remain::sorted]` attribute on enums, on match-expressions, or on
-//! let-statements whose value is a match-expression.
+//! Place a `#[remain::sorted]` attribute on enums, on named structs, on
+//! match-expressions, or on let-statements whose value is a match-expression.
//!
//! Alternatively, import as `use remain::sorted;` and use `#[sorted]` as the
//! attribute.
@@ -76,7 +76,7 @@
//! # fn main() {}
//! ```
//!
-//! If an enum variant or match arm is inserted out of order,
+//! If an enum variant, struct field, or match arm is inserted out of order,\
//!
//! ```diff
//! NetDeviceNew(virtio::NetError),
diff --git a/src/parse.rs b/src/parse.rs
index 77fd4bc..98b8c86 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -1,6 +1,6 @@
use proc_macro2::Span;
use syn::parse::{Parse, ParseStream};
-use syn::{Attribute, Error, Expr, Result, Stmt, Token, Visibility};
+use syn::{Attribute, Error, Expr, Fields, Result, Stmt, Token, Visibility};
use crate::emit::Kind;
@@ -15,6 +15,7 @@ impl Parse for Nothing {
pub enum Input {
Enum(syn::ItemEnum),
Match(syn::ExprMatch),
+ Struct(syn::ItemStruct),
Let(syn::ExprMatch),
}
@@ -23,6 +24,7 @@ impl Input {
match self {
Input::Enum(_) => Kind::Enum,
Input::Match(_) => Kind::Match,
+ Input::Struct(_) => Kind::Struct,
Input::Let(_) => Kind::Let,
}
}
@@ -61,6 +63,14 @@ impl Parse for Input {
if ahead.peek(Token![enum]) {
return input.parse().map(Input::Enum);
}
+ if ahead.peek(Token![struct]) {
+ let input = input.parse().map(Input::Struct)?;
+ if let Input::Struct(ref item) = input {
+ if let Fields::Named(_) = item.fields {
+ return Ok(input);
+ }
+ }
+ }
Err(unexpected())
}
@@ -68,6 +78,6 @@ impl Parse for Input {
fn unexpected() -> Error {
let span = Span::call_site();
- let msg = "expected enum or match expression";
+ let msg = "expected enum, named struct, or match expression";
Error::new(span, msg)
}