Merge pull request #743 from rtfeldman/parse-pkg-imports

Parse package-qualified imports
This commit is contained in:
Richard Feldman 2020-11-26 22:09:17 -05:00 committed by GitHub
commit 59ca5282ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 19 deletions

View file

@ -175,7 +175,7 @@ fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &'a ImportsEntry<'a>, inde
} }
} }
Package(_name, _entries) => { Package(_pkg, _name, _entries) => {
todo!("TODO Format imported package"); todo!("TODO Format imported package");
} }

View file

@ -2796,7 +2796,7 @@ fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec<Ident>) {
(module_name.as_str().into(), exposed) (module_name.as_str().into(), exposed)
} }
Package(_package_name, _exposes) => { Package(_package_name, _module_name, _exposes) => {
todo!("TODO support exposing package-qualified module names."); todo!("TODO support exposing package-qualified module names.");
} }

View file

@ -177,7 +177,11 @@ pub enum ImportsEntry<'a> {
Module(ModuleName<'a>, Vec<'a, Loc<ExposesEntry<'a, &'a str>>>), Module(ModuleName<'a>, Vec<'a, Loc<ExposesEntry<'a, &'a str>>>),
/// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }` /// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }`
Package(&'a str, Vec<'a, Loc<&'a ImportsEntry<'a>>>), Package(
&'a str,
ModuleName<'a>,
Vec<'a, Loc<ExposesEntry<'a, &'a str>>>,
),
// Spaces // Spaces
SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]),

View file

@ -544,11 +544,16 @@ fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>> {
} }
#[inline(always)] #[inline(always)]
#[allow(clippy::type_complexity)]
fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> { fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> {
map_with_arena!( map_with_arena!(
and!( and!(
// e.g. `Task` and!(
module_name(), // e.g. `base.`
optional(skip_second!(lowercase_ident(), ascii_char(b'.'))),
// e.g. `Task`
module_name()
),
// e.g. `.{ Task, after}` // e.g. `.{ Task, after}`
optional(skip_first!( optional(skip_first!(
ascii_char(b'.'), ascii_char(b'.'),
@ -562,13 +567,17 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> {
)) ))
), ),
|arena, |arena,
(module_name, opt_values): ( ((opt_shortname, module_name), opt_values): (
ModuleName<'a>, (Option<&'a str>, ModuleName<'a>),
Option<Vec<'a, Located<ExposesEntry<'a, &'a str>>>> Option<Vec<'a, Located<ExposesEntry<'a, &'a str>>>>
)| { )| {
let exposed_values = opt_values.unwrap_or_else(|| Vec::new_in(arena)); let exposed_values = opt_values.unwrap_or_else(|| Vec::new_in(arena));
ImportsEntry::Module(module_name, exposed_values) match opt_shortname {
Some(shortname) => ImportsEntry::Package(shortname, module_name, exposed_values),
None => ImportsEntry::Module(module_name, exposed_values),
}
} }
) )
} }

View file

@ -27,8 +27,8 @@ mod test_parse {
self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch, self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch,
}; };
use roc_parse::header::{ use roc_parse::header::{
AppHeader, Effects, ExposesEntry, InterfaceHeader, ModuleName, PackageEntry, PackageName, AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
PackageOrPath, PlatformHeader, To, PackageName, PackageOrPath, PlatformHeader, To,
}; };
use roc_parse::module::{app_header, interface_header, module_defs, platform_header}; use roc_parse::module::{app_header, interface_header, module_defs, platform_header};
use roc_parse::parser::{Fail, FailReason, Parser, State}; use roc_parse::parser::{Fail, FailReason, Parser, State};
@ -2358,16 +2358,19 @@ mod test_parse {
use ExposesEntry::Exposed; use ExposesEntry::Exposed;
use PackageOrPath::Path; use PackageOrPath::Path;
let newlines = &[Newline];
let pkg_entry = PackageEntry::Entry { let pkg_entry = PackageEntry::Entry {
shorthand: "base", shorthand: "base",
spaces_after_shorthand: &[], spaces_after_shorthand: &[],
package_or_path: Located::new(0, 0, 33, 45, Path(PlainLine("./platform"))), package_or_path: Located::new(1, 1, 21, 33, Path(PlainLine("./platform"))),
}; };
let loc_pkg_entry = Located::new(0, 0, 27, 45, pkg_entry); let loc_pkg_entry = Located::new(1, 1, 15, 33, pkg_entry);
let arena = Bump::new(); let arena = Bump::new();
let packages = bumpalo::vec![in &arena; loc_pkg_entry]; let packages = bumpalo::vec![in &arena; loc_pkg_entry];
let imports = Vec::new_in(&arena); let import = ImportsEntry::Package("foo", ModuleName::new("Bar.Baz"), Vec::new_in(&arena));
let provide_entry = Located::new(0, 0, 59, 68, Exposed("quicksort")); 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 provides = bumpalo::vec![in &arena; provide_entry];
let module_name = StrLiteral::PlainLine("quicksort"); let module_name = StrLiteral::PlainLine("quicksort");
let expected = AppHeader { let expected = AppHeader {
@ -2375,13 +2378,13 @@ mod test_parse {
packages, packages,
imports, imports,
provides, provides,
to: Located::new(0, 0, 74, 78, To::ExistingPackage("base")), to: Located::new(3, 3, 30, 34, To::ExistingPackage("base")),
after_app_keyword: &[], after_app_keyword: &[],
before_packages: &[], before_packages: newlines,
after_packages: &[], after_packages: &[],
before_imports: &[], before_imports: newlines,
after_imports: &[], after_imports: &[],
before_provides: &[], before_provides: newlines,
after_provides: &[], after_provides: &[],
before_to: &[], before_to: &[],
after_to: &[], after_to: &[],
@ -2389,7 +2392,10 @@ mod test_parse {
let src = indoc!( let src = indoc!(
r#" r#"
app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base app "quicksort"
packages { base: "./platform" }
imports [ foo.Bar.Baz ]
provides [ quicksort ] to base
"# "#
); );
let actual = app_header() let actual = app_header()