Sort import alphabetically when formatting.

Fixes #211.
This commit is contained in:
KtorZ 2022-12-22 17:59:31 +01:00
parent 1ca705005d
commit 1f15c2ca20
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
2 changed files with 76 additions and 35 deletions

View File

@ -133,14 +133,14 @@ impl<'comments> Formatter<'comments> {
let start = def.location().start; let start = def.location().start;
match def { match def {
Definition::Use { .. } => { Definition::Use(import) => {
has_imports = true; has_imports = true;
let comments = self.pop_comments(start); let comments = self.pop_comments(start);
let def = self.definition(def); let def = self.definition(def);
imports.push(commented(def, comments)) imports.push((import, commented(def, comments)))
} }
_other => { _other => {
@ -155,7 +155,15 @@ impl<'comments> Formatter<'comments> {
} }
} }
let imports = join(imports.into_iter(), line()); let imports = join(
imports
.into_iter()
.sorted_by(|(import_a, _), (import_b, _)| {
Ord::cmp(&import_a.module, &import_b.module)
})
.map(|(_, doc)| doc),
line(),
);
let declarations = join(declarations.into_iter(), lines(2)); let declarations = join(declarations.into_iter(), lines(2));
@ -253,12 +261,35 @@ impl<'comments> Formatter<'comments> {
.. ..
}) => self.data_type(*public, *opaque, name, parameters, constructors, location), }) => self.data_type(*public, *opaque, name, parameters, constructors, location),
Definition::Use(Use { Definition::Use(import) => self.import(import),
Definition::ModuleConstant(ModuleConstant {
public,
name,
annotation,
value,
..
}) => {
let head = pub_(*public).append("const ").append(name.as_str());
let head = match annotation {
None => head,
Some(t) => head.append(": ").append(self.annotation(t)),
};
head.append(" = ").append(self.const_expr(value))
}
}
}
fn import<'a>(
&mut self,
Use {
module, module,
as_name, as_name,
unqualified, unqualified,
.. ..
}) => "use " }: &'a Use<()>,
) -> Document<'a> {
"use "
.to_doc() .to_doc()
.append(Document::String(module.join("/"))) .append(Document::String(module.join("/")))
.append(if unqualified.is_empty() { .append(if unqualified.is_empty() {
@ -282,23 +313,7 @@ impl<'comments> Formatter<'comments> {
docvec![" as ", name] docvec![" as ", name]
} else { } else {
nil() nil()
}), })
Definition::ModuleConstant(ModuleConstant {
public,
name,
annotation,
value,
..
}) => {
let head = pub_(*public).append("const ").append(name.as_str());
let head = match annotation {
None => head,
Some(t) => head.append(": ").append(self.annotation(t)),
};
head.append(" = ").append(self.const_expr(value))
}
}
} }
fn const_expr<'a, A, B>(&mut self, value: &'a Constant<A, B>) -> Document<'a> { fn const_expr<'a, A, B>(&mut self, value: &'a Constant<A, B>) -> Document<'a> {

View File

@ -5,14 +5,15 @@ use pretty_assertions::assert_eq;
fn assert_fmt(src: &str, expected: &str) { fn assert_fmt(src: &str, expected: &str) {
let (module, extra) = parser::module(src, ModuleKind::Lib).unwrap(); let (module, extra) = parser::module(src, ModuleKind::Lib).unwrap();
let mut out = String::new(); let mut out = String::new();
format::pretty(&mut out, module.clone(), extra.clone(), src); format::pretty(&mut out, module, extra, src);
// Output is what we expect // Output is what we expect
assert_eq!(out, expected); assert_eq!(out, expected);
// Formatting is idempotent // Formatting is idempotent
let (module2, extra2) = parser::module(&out, ModuleKind::Lib).unwrap();
let mut out2 = String::new(); let mut out2 = String::new();
format::pretty(&mut out2, module, extra, &out); format::pretty(&mut out2, module2, extra2, &out);
assert_eq!(out, out2); assert_eq!(out, out2);
} }
@ -171,3 +172,28 @@ fn test_format_nested_when() {
assert_fmt(src, expected) assert_fmt(src, expected)
} }
#[test]
fn test_format_imports() {
let src = indoc! {r#"
use aiken/list
// foo
use aiken/bytearray
use aiken/transaction/certificate
// bar
use aiken/transaction
use aiken/transaction/value
"#};
let expected = indoc! {r#"
// foo
use aiken/bytearray
use aiken/list
// bar
use aiken/transaction
use aiken/transaction/certificate
use aiken/transaction/value
"#};
assert_fmt(src, expected)
}