Make sure that imports are always in the same order between runs. This
makes the output more stable for putting it into a versioning system like git
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
error::Error,
|
||||
fmt::{Debug, Display},
|
||||
hash::{Hash, Hasher},
|
||||
@@ -20,7 +20,7 @@ pub trait Definition: Debug {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IR {
|
||||
pub options: HashMap<String, String>,
|
||||
pub options: BTreeMap<String, String>,
|
||||
pub steps: Vec<Step>,
|
||||
}
|
||||
|
||||
@@ -58,7 +58,12 @@ impl ToString for BaseType {
|
||||
|
||||
impl Hash for BaseType {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.to_string().hash(state);
|
||||
// Hash the enum variant itself
|
||||
std::mem::discriminant(self).hash(state);
|
||||
// If the variant has data, hash that too
|
||||
if let BaseType::Custom(name) = self {
|
||||
name.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +183,7 @@ impl Type {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeDefinition {
|
||||
pub name: String,
|
||||
pub depends: HashSet<BaseType>,
|
||||
pub depends: BTreeSet<BaseType>,
|
||||
pub fields: Vec<Field>,
|
||||
pub position: ParserPosition,
|
||||
}
|
||||
@@ -223,7 +228,7 @@ pub struct EnumField {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServiceDefinition {
|
||||
pub name: String,
|
||||
pub depends: HashSet<BaseType>,
|
||||
pub depends: BTreeSet<BaseType>,
|
||||
pub methods: Vec<Method>,
|
||||
pub position: ParserPosition,
|
||||
}
|
||||
@@ -259,7 +264,7 @@ pub struct MethodOutput {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MethodDecorators {
|
||||
pub description: Option<String>,
|
||||
pub parameter_descriptions: HashMap<String, String>,
|
||||
pub parameter_descriptions: BTreeMap<String, String>,
|
||||
pub return_description: Option<String>,
|
||||
}
|
||||
|
||||
@@ -267,7 +272,7 @@ fn build_type(stmt: &TypeStatement) -> Result<TypeDefinition> {
|
||||
let mut typedef = TypeDefinition {
|
||||
position: stmt.position.clone(),
|
||||
name: stmt.name.clone(),
|
||||
depends: HashSet::new(),
|
||||
depends: BTreeSet::new(),
|
||||
fields: Vec::new(),
|
||||
};
|
||||
|
||||
@@ -332,7 +337,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
let mut servdef = ServiceDefinition {
|
||||
position: stmt.position.clone(),
|
||||
name: stmt.name.clone(),
|
||||
depends: HashSet::new(),
|
||||
depends: BTreeSet::new(),
|
||||
methods: Vec::new(),
|
||||
};
|
||||
|
||||
@@ -349,7 +354,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
}),
|
||||
decorators: MethodDecorators {
|
||||
description: None,
|
||||
parameter_descriptions: HashMap::new(),
|
||||
parameter_descriptions: BTreeMap::new(),
|
||||
return_description: None,
|
||||
},
|
||||
};
|
||||
@@ -450,7 +455,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
}
|
||||
|
||||
pub fn build_ir(root: &Vec<RootNode>) -> Result<IR> {
|
||||
let mut options = HashMap::<String, String>::new();
|
||||
let mut options = BTreeMap::<String, String>::new();
|
||||
let mut steps = Vec::new();
|
||||
|
||||
for node in root {
|
||||
@@ -476,8 +481,8 @@ pub fn build_ir(root: &Vec<RootNode>) -> Result<IR> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut all_types = HashSet::<String>::new();
|
||||
let mut serv_types = HashSet::<String>::new();
|
||||
let mut all_types = BTreeSet::<String>::new();
|
||||
let mut serv_types = BTreeSet::<String>::new();
|
||||
|
||||
for bi in &BUILT_INS {
|
||||
all_types.insert(bi.to_string());
|
||||
@@ -577,3 +582,36 @@ impl Display for IRError {
|
||||
write!(f, "ParserError: {} at {:?}", self.message, self.position)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn btreeset_order_is_consistent() {
|
||||
let mut set1 = BTreeSet::new();
|
||||
let mut set2 = BTreeSet::new();
|
||||
|
||||
let elements = vec![
|
||||
BaseType::Custom("CustomType".to_string()),
|
||||
BaseType::Void,
|
||||
BaseType::Bytes,
|
||||
BaseType::Float,
|
||||
];
|
||||
|
||||
// Insert in normal order
|
||||
for elem in &elements {
|
||||
set1.insert(elem.clone());
|
||||
}
|
||||
|
||||
// Insert in reverse order
|
||||
for elem in elements.iter().rev() {
|
||||
set2.insert(elem.clone());
|
||||
}
|
||||
|
||||
let iter1: Vec<_> = set1.iter().cloned().collect();
|
||||
let iter2: Vec<_> = set2.iter().cloned().collect();
|
||||
|
||||
assert_eq!(iter1, iter2); // Order must be the same
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user