Use collection_trailing_sep_e for packages decl, to allow trailing commas there

This commit is contained in:
Joshua Warner 2021-11-10 18:47:48 -08:00
parent f82ca36b19
commit 6a694b7772
4 changed files with 68 additions and 7 deletions

View file

@ -9,13 +9,13 @@ use crate::string_literal;
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use roc_region::all::Loc; use roc_region::all::Loc;
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct PackageName<'a> { pub struct PackageName<'a> {
pub account: &'a str, pub account: &'a str,
pub pkg: &'a str, pub pkg: &'a str,
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum Version<'a> { pub enum Version<'a> {
Exact(&'a str), Exact(&'a str),
Range { Range {
@ -32,7 +32,7 @@ pub enum VersionComparison {
DisallowsEqual, DisallowsEqual,
} }
#[derive(Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
pub enum PackageOrPath<'a> { pub enum PackageOrPath<'a> {
Package(PackageName<'a>, Version<'a>), Package(PackageName<'a>, Version<'a>),
Path(StrLiteral<'a>), Path(StrLiteral<'a>),
@ -240,7 +240,7 @@ pub enum TypedIdent<'a> {
SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]),
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum PackageEntry<'a> { pub enum PackageEntry<'a> {
Entry { Entry {
shorthand: &'a str, shorthand: &'a str,

View file

@ -586,6 +586,7 @@ struct Packages<'a> {
before_packages_keyword: &'a [CommentOrNewline<'a>], before_packages_keyword: &'a [CommentOrNewline<'a>],
after_packages_keyword: &'a [CommentOrNewline<'a>], after_packages_keyword: &'a [CommentOrNewline<'a>],
final_comments: &'a [CommentOrNewline<'a>],
} }
#[inline(always)] #[inline(always)]
@ -602,21 +603,24 @@ fn packages<'a>() -> impl Parser<'a, Packages<'a>, EPackages<'a>> {
EPackages::IndentPackages, EPackages::IndentPackages,
EPackages::IndentListStart EPackages::IndentListStart
), ),
collection_e!( collection_trailing_sep_e!(
word1(b'{', EPackages::ListStart), word1(b'{', EPackages::ListStart),
specialize(EPackages::PackageEntry, loc!(package_entry())), specialize(EPackages::PackageEntry, loc!(package_entry())),
word1(b',', EPackages::ListEnd), word1(b',', EPackages::ListEnd),
word1(b'}', EPackages::ListEnd), word1(b'}', EPackages::ListEnd),
min_indent, min_indent,
EPackages::Open,
EPackages::Space, EPackages::Space,
EPackages::IndentListEnd EPackages::IndentListEnd,
PackageEntry::SpaceBefore
) )
), ),
|((before_packages_keyword, after_packages_keyword), entries)| { |((before_packages_keyword, after_packages_keyword), (entries, final_comments))| {
Packages { Packages {
entries, entries,
before_packages_keyword, before_packages_keyword,
after_packages_keyword, after_packages_keyword,
final_comments,
} }
} }
) )

View file

@ -265,6 +265,7 @@ pub enum ETypedIdent<'a> {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum EPackages<'a> { pub enum EPackages<'a> {
Open(Row, Col),
Space(BadInputError, Row, Col), Space(BadInputError, Row, Col),
Packages(Row, Col), Packages(Row, Col),
IndentPackages(Row, Col), IndentPackages(Row, Col),

View file

@ -3223,6 +3223,62 @@ mod test_parse {
assert_eq!(Ok(expected), actual); assert_eq!(Ok(expected), actual);
} }
#[test]
fn full_app_header_trailing_commas() {
use ExposesEntry::Exposed;
use PackageOrPath::Path;
let newlines = &[Newline];
let pkg_entry = PackageEntry::Entry {
shorthand: "base",
spaces_after_shorthand: &[],
package_or_path: Located::new(1, 1, 21, 33, Path(PlainLine("./platform"))),
};
let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
let arena = Bump::new();
let packages = bumpalo::vec![in &arena; loc_pkg_entry];
let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
let loc_import = Located::new(2, 2, 14, 25, import);
let imports = bumpalo::vec![in &arena; loc_import];
let provide_entry = Located::new(3, 3, 15, 24, Exposed("quicksort"));
let provides = bumpalo::vec![in &arena; provide_entry];
let module_name = StrLiteral::PlainLine("quicksort");
let header = AppHeader {
before_header: &[],
name: Located::new(0, 0, 4, 15, module_name),
packages,
imports,
provides,
to: Located::new(3, 3, 30, 34, To::ExistingPackage("base")),
after_app_keyword: &[],
before_packages: newlines,
after_packages: &[],
before_imports: newlines,
after_imports: &[],
before_provides: newlines,
after_provides: &[],
before_to: &[],
after_to: &[],
};
let expected = roc_parse::ast::Module::App { header };
let src = indoc!(
r#"
app "quicksort"
packages { base: "./platform", }
imports [ foo.Bar.Baz ]
provides [ quicksort ] to base
"#
);
let actual = roc_parse::module::parse_header(&arena, State::new(src.as_bytes()))
.map(|tuple| tuple.0);
assert_eq!(Ok(expected), actual);
}
#[test] #[test]
fn empty_platform_header() { fn empty_platform_header() {
let pkg_name = PackageName { let pkg_name = PackageName {