Allow trailing comments in imports decl

This commit is contained in:
Joshua Warner 2021-11-10 19:39:02 -08:00
parent c10f403c94
commit 23c75d2699
5 changed files with 27 additions and 25 deletions

View file

@ -1,6 +1,6 @@
use crate::spaces::{fmt_spaces, INDENT}; use crate::spaces::{fmt_spaces, INDENT};
use bumpalo::collections::{String, Vec}; use bumpalo::collections::{String, Vec};
use roc_parse::ast::Module; use roc_parse::ast::{Collection, Module};
use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader}; use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader};
use roc_region::all::Located; use roc_region::all::Located;
@ -64,7 +64,7 @@ pub fn fmt_interface_header<'a>(buf: &mut String<'a>, header: &'a InterfaceHeade
fmt_spaces(buf, header.after_imports.iter(), indent); fmt_spaces(buf, header.after_imports.iter(), indent);
} }
fmt_imports(buf, &header.imports, indent); fmt_imports(buf, header.imports, indent);
} }
pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) { pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
@ -76,7 +76,7 @@ pub fn fmt_app_header<'a>(buf: &mut String<'a>, header: &'a AppHeader<'a>) {
buf.push_str("imports"); buf.push_str("imports");
fmt_spaces(buf, header.before_imports.iter(), indent); fmt_spaces(buf, header.before_imports.iter(), indent);
fmt_imports(buf, &header.imports, indent); fmt_imports(buf, header.imports, indent);
fmt_spaces(buf, header.after_imports.iter(), indent); fmt_spaces(buf, header.after_imports.iter(), indent);
} }
@ -86,7 +86,7 @@ pub fn fmt_platform_header<'a>(_buf: &mut String<'a>, _header: &'a PlatformHeade
fn fmt_imports<'a>( fn fmt_imports<'a>(
buf: &mut String<'a>, buf: &mut String<'a>,
loc_entries: &'a Vec<'a, Located<ImportsEntry<'a>>>, loc_entries: Collection<'a, Located<ImportsEntry<'a>>>,
indent: u16, indent: u16,
) { ) {
buf.push('['); buf.push('[');

View file

@ -2609,7 +2609,7 @@ fn parse_header<'a>(
header_src, header_src,
packages: &[], packages: &[],
exposes: header.exposes.into_bump_slice(), exposes: header.exposes.into_bump_slice(),
imports: header.imports.into_bump_slice(), imports: header.imports.items,
to_platform: None, to_platform: None,
}; };
@ -2643,7 +2643,7 @@ fn parse_header<'a>(
header_src, header_src,
packages, packages,
exposes: header.provides.into_bump_slice(), exposes: header.provides.into_bump_slice(),
imports: header.imports.into_bump_slice(), imports: header.imports.items,
to_platform: Some(header.to.value.clone()), to_platform: Some(header.to.value.clone()),
}; };
@ -3421,7 +3421,7 @@ fn fabricate_pkg_config_module<'a>(
packages: &[], packages: &[],
provides, provides,
requires: arena.alloc([header.requires.signature.clone()]), requires: arena.alloc([header.requires.signature.clone()]),
imports: header.imports.clone().into_bump_slice(), imports: header.imports.items,
}; };
send_header_two( send_header_two(

View file

@ -38,7 +38,7 @@ pub enum PackageOrPath<'a> {
Path(StrLiteral<'a>), Path(StrLiteral<'a>),
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct ModuleName<'a>(&'a str); pub struct ModuleName<'a>(&'a str);
impl<'a> From<ModuleName<'a>> for &'a str { impl<'a> From<ModuleName<'a>> for &'a str {
@ -61,7 +61,7 @@ impl<'a> ModuleName<'a> {
pub struct InterfaceHeader<'a> { pub struct InterfaceHeader<'a> {
pub name: Loc<ModuleName<'a>>, pub name: Loc<ModuleName<'a>>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>, pub exposes: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>, pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
// Potential comments and newlines - these will typically all be empty. // Potential comments and newlines - these will typically all be empty.
pub before_header: &'a [CommentOrNewline<'a>], pub before_header: &'a [CommentOrNewline<'a>],
@ -82,7 +82,7 @@ pub enum To<'a> {
pub struct AppHeader<'a> { pub struct AppHeader<'a> {
pub name: Loc<StrLiteral<'a>>, pub name: Loc<StrLiteral<'a>>,
pub packages: Collection<'a, Loc<PackageEntry<'a>>>, pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>, pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>, pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub to: Loc<To<'a>>, pub to: Loc<To<'a>>,
@ -147,7 +147,7 @@ pub struct PlatformHeader<'a> {
pub requires: PlatformRequires<'a>, pub requires: PlatformRequires<'a>,
pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>, pub exposes: Vec<'a, Loc<ExposesEntry<'a, ModuleName<'a>>>>,
pub packages: Collection<'a, Loc<PackageEntry<'a>>>, pub packages: Collection<'a, Loc<PackageEntry<'a>>>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>, pub imports: Collection<'a, Loc<ImportsEntry<'a>>>,
pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>, pub provides: Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
pub effects: Effects<'a>, pub effects: Effects<'a>,
@ -196,7 +196,7 @@ impl<'a, T> Spaceable<'a> for ExposesEntry<'a, T> {
} }
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum ImportsEntry<'a> { pub enum ImportsEntry<'a> {
/// e.g. `Task` or `Task.{ Task, after }` /// e.g. `Task` or `Task.{ Task, after }`
Module( Module(

View file

@ -220,11 +220,11 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
let opt_imports: Option<( let opt_imports: Option<(
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
Vec<'a, Located<ImportsEntry<'a>>>, Collection<'a, Located<ImportsEntry<'a>>>,
)> = opt_imports; )> = opt_imports;
let ((before_imports, after_imports), imports) = let ((before_imports, after_imports), imports) =
opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Vec::new_in(arena))); opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Collection::empty()));
let provides: ProvidesTo<'a> = provides; // rustc must be told the type here let provides: ProvidesTo<'a> = provides; // rustc must be told the type here
let header = AppHeader { let header = AppHeader {
@ -631,7 +631,7 @@ fn imports<'a>() -> impl Parser<
'a, 'a,
( (
(&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]),
Vec<'a, Located<ImportsEntry<'a>>>, Collection<'a, Located<ImportsEntry<'a>>>,
), ),
EImports, EImports,
> { > {
@ -646,14 +646,16 @@ fn imports<'a>() -> impl Parser<
EImports::IndentImports, EImports::IndentImports,
EImports::IndentListStart EImports::IndentListStart
), ),
collection_e!( collection_trailing_sep_e!(
word1(b'[', EImports::ListStart), word1(b'[', EImports::ListStart),
loc!(imports_entry()), loc!(imports_entry()),
word1(b',', EImports::ListEnd), word1(b',', EImports::ListEnd),
word1(b']', EImports::ListEnd), word1(b']', EImports::ListEnd),
min_indent, min_indent,
EImports::Open,
EImports::Space, EImports::Space,
EImports::IndentListEnd EImports::IndentListEnd,
ImportsEntry::SpaceBefore
) )
) )
} }

View file

@ -3077,7 +3077,7 @@ mod test_parse {
fn empty_app_header() { fn empty_app_header() {
let arena = Bump::new(); let arena = Bump::new();
let packages = Collection::empty(); let packages = Collection::empty();
let imports = Vec::new_in(&arena); let imports = Collection::empty();
let provides = Vec::new_in(&arena); let provides = Vec::new_in(&arena);
let module_name = StrLiteral::PlainLine("test-app"); let module_name = StrLiteral::PlainLine("test-app");
let header = AppHeader { let header = AppHeader {
@ -3117,7 +3117,7 @@ mod test_parse {
let arena = Bump::new(); let arena = Bump::new();
let packages = Collection::empty(); let packages = Collection::empty();
let imports = Vec::new_in(&arena); let imports = Collection::empty();
let provides = Vec::new_in(&arena); let provides = Vec::new_in(&arena);
let module_name = StrLiteral::PlainLine("test-app"); let module_name = StrLiteral::PlainLine("test-app");
let header = AppHeader { let header = AppHeader {
@ -3168,7 +3168,7 @@ mod test_parse {
let packages = Collection::with_items(arena.alloc([loc_pkg_entry])); let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Collection::empty()); let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Collection::empty());
let loc_import = Located::new(2, 2, 14, 25, import); let loc_import = Located::new(2, 2, 14, 25, import);
let imports = bumpalo::vec![in &arena; loc_import]; let imports = Collection::with_items(arena.alloc([loc_import]));
let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort")); let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort"));
let provides = bumpalo::vec![in &arena; provide_entry]; let provides = bumpalo::vec![in &arena; provide_entry];
let module_name = StrLiteral::PlainLine("quicksort"); let module_name = StrLiteral::PlainLine("quicksort");
@ -3253,7 +3253,7 @@ mod test_parse {
), ),
); );
let loc_import = Located::new(2, 6, 14, 5, import); let loc_import = Located::new(2, 6, 14, 5, import);
let imports = bumpalo::vec![in &arena; loc_import]; let imports = Collection::with_items(arena.alloc([loc_import]));
let provide_entry = Located::new(7, 7, 15, 24, Exposed("quicksort")); let provide_entry = Located::new(7, 7, 15, 24, Exposed("quicksort"));
let provides = bumpalo::vec![in &arena; provide_entry]; let provides = bumpalo::vec![in &arena; provide_entry];
let module_name = StrLiteral::PlainLine("quicksort"); let module_name = StrLiteral::PlainLine("quicksort");
@ -3342,7 +3342,7 @@ mod test_parse {
requires, requires,
exposes: Vec::new_in(&arena), exposes: Vec::new_in(&arena),
packages: Collection::empty(), packages: Collection::empty(),
imports: Vec::new_in(&arena), imports: Collection::empty(),
provides: Vec::new_in(&arena), provides: Vec::new_in(&arena),
effects, effects,
after_platform_keyword: &[], after_platform_keyword: &[],
@ -3385,7 +3385,7 @@ mod test_parse {
let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry); let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry);
let arena = Bump::new(); let arena = Bump::new();
let packages = Collection::with_items(arena.alloc([loc_pkg_entry])); let packages = Collection::with_items(arena.alloc([loc_pkg_entry]));
let imports = Vec::new_in(&arena); let imports = Collection::empty();
let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost")); let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost"));
let provides = bumpalo::vec![in &arena; provide_entry]; let provides = bumpalo::vec![in &arena; provide_entry];
let effects = Effects { let effects = Effects {
@ -3466,7 +3466,7 @@ mod test_parse {
fn empty_interface_header() { fn empty_interface_header() {
let arena = Bump::new(); let arena = Bump::new();
let exposes = Vec::new_in(&arena); let exposes = Vec::new_in(&arena);
let imports = Vec::new_in(&arena); let imports = Collection::empty();
let module_name = ModuleName::new("Foo"); let module_name = ModuleName::new("Foo");
let header = InterfaceHeader { let header = InterfaceHeader {
before_header: &[], before_header: &[],
@ -3498,7 +3498,7 @@ mod test_parse {
fn nested_module() { fn nested_module() {
let arena = Bump::new(); let arena = Bump::new();
let exposes = Vec::new_in(&arena); let exposes = Vec::new_in(&arena);
let imports = Vec::new_in(&arena); let imports = Collection::empty();
let module_name = ModuleName::new("Foo.Bar.Baz"); let module_name = ModuleName::new("Foo.Bar.Baz");
let header = InterfaceHeader { let header = InterfaceHeader {
before_header: &[], before_header: &[],