Parse and format inline ingested file imports

This commit is contained in:
Agus Zubiaga 2023-12-10 01:23:57 -03:00
parent 42e755677c
commit 4d6e641864
No known key found for this signature in database
10 changed files with 165 additions and 12 deletions

View file

@ -1,5 +1,6 @@
use crate::annotation::{is_collection_multiline, Formattable, Newlines, Parens};
use crate::collection::{fmt_collection, Braces};
use crate::expr::fmt_str_literal;
use crate::pattern::fmt_pattern;
use crate::spaces::{fmt_default_newline, fmt_default_spaces, fmt_spaces, INDENT};
use crate::Buf;
@ -287,6 +288,11 @@ impl<'a> Formattable for ValueDef<'a> {
a.keyword.is_multiline() || is_collection_multiline(&a.item)
})
}
IngestedFileImport {
before_path,
path: _,
name,
} => !before_path.is_empty() || name.is_multiline(),
}
}
@ -365,6 +371,20 @@ impl<'a> Formattable for ValueDef<'a> {
fmt_collection(buf, list_indent, Braces::Square, exposed.item, Newlines::No);
}
}
IngestedFileImport {
before_path,
path,
name,
} => {
buf.indent(indent);
buf.push_str("import");
let indent = indent + INDENT;
fmt_default_spaces(buf, before_path, indent);
fmt_str_literal(buf, path.value, indent);
name.format(buf, indent);
}
}
}
}

View file

@ -577,6 +577,15 @@ impl<'a> RemoveSpaces<'a> for ValueDef<'a> {
alias: alias.remove_spaces(arena),
exposed: exposed.remove_spaces(arena),
},
IngestedFileImport {
before_path: _,
path,
name,
} => IngestedFileImport {
before_path: &[],
path: path.remove_spaces(arena),
name: name.remove_spaces(arena),
},
}
}
}

View file

@ -471,6 +471,13 @@ pub enum ValueDef<'a> {
>,
>,
},
/// e.g. `import "path/to/my/file.txt" as myFile : Str`
IngestedFileImport {
before_path: &'a [CommentOrNewline<'a>],
path: Loc<StrLiteral<'a>>,
name: header::KeywordItem<'a, ImportAsKeyword, Loc<Spaced<'a, header::TypedIdent<'a>>>>,
},
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -1847,6 +1854,11 @@ impl<'a> Malformed for ValueDef<'a> {
alias: _,
exposed: _,
} => false,
ValueDef::IngestedFileImport {
before_path: _,
path,
name: _,
} => path.is_malformed(),
}
}
}

View file

@ -20,7 +20,7 @@ use crate::parser::{
};
use crate::pattern::{closure_param, loc_implements_parser};
use crate::state::State;
use crate::string_literal::StrLikeLiteral;
use crate::string_literal::{self, StrLikeLiteral};
use crate::{header, keyword};
use crate::{module, type_annotation};
use bumpalo::collections::Vec;
@ -840,14 +840,14 @@ pub fn parse_single_def<'a>(
}
}
fn import<'a>() -> impl Parser<'a, ValueDef<'a>, EImport> {
fn import<'a>() -> impl Parser<'a, ValueDef<'a>, EImport<'a>> {
skip_first!(
parser::keyword_e(keyword::IMPORT, EImport::Import),
increment_min_indent(import_body())
increment_min_indent(one_of!(import_body(), import_ingested_file_body()))
)
}
fn import_body<'a>() -> impl Parser<'a, ValueDef<'a>, EImport> {
fn import_body<'a>() -> impl Parser<'a, ValueDef<'a>, EImport<'a>> {
record!(ValueDef::ModuleImport {
before_name: space0_e(EImport::IndentStart),
name: loc!(imported_module_name()),
@ -857,7 +857,7 @@ fn import_body<'a>() -> impl Parser<'a, ValueDef<'a>, EImport> {
}
#[inline(always)]
fn imported_module_name<'a>() -> impl Parser<'a, ImportedModuleName<'a>, EImport> {
fn imported_module_name<'a>() -> impl Parser<'a, ImportedModuleName<'a>, EImport<'a>> {
record!(ImportedModuleName {
package: optional(skip_second!(
specialize(|_, pos| EImport::PackageShorthand(pos), lowercase_ident()),
@ -869,7 +869,7 @@ fn imported_module_name<'a>() -> impl Parser<'a, ImportedModuleName<'a>, EImport
#[inline(always)]
fn import_as<'a>(
) -> impl Parser<'a, header::KeywordItem<'a, ImportAsKeyword, Loc<ImportAlias<'a>>>, EImport> {
) -> impl Parser<'a, header::KeywordItem<'a, ImportAsKeyword, Loc<ImportAlias<'a>>>, EImport<'a>> {
record!(header::KeywordItem {
keyword: module::spaces_around_keyword(
ImportAsKeyword,
@ -892,7 +892,7 @@ fn import_exposing<'a>() -> impl Parser<
ImportExposingKeyword,
Collection<'a, Loc<Spaced<'a, header::ExposedName<'a>>>>,
>,
EImport,
EImport<'a>,
> {
record!(header::KeywordItem {
keyword: module::spaces_around_keyword(
@ -913,13 +913,42 @@ fn import_exposing<'a>() -> impl Parser<
#[inline(always)]
fn import_exposed_name<'a>(
) -> impl Parser<'a, crate::ast::Spaced<'a, crate::header::ExposedName<'a>>, EImport> {
) -> impl Parser<'a, crate::ast::Spaced<'a, crate::header::ExposedName<'a>>, EImport<'a>> {
map!(
specialize(|_, pos| EImport::ExposedName(pos), unqualified_ident()),
|n| Spaced::Item(crate::header::ExposedName::new(n))
)
}
#[inline(always)]
fn import_ingested_file_body<'a>() -> impl Parser<'a, ValueDef<'a>, EImport<'a>> {
record!(ValueDef::IngestedFileImport {
before_path: space0_e(EImport::IndentStart),
path: loc!(specialize(
|_, pos| EImport::IngestedPath(pos),
string_literal::parse_str_literal()
)),
name: import_ingested_file_as(),
})
}
#[inline(always)]
fn import_ingested_file_as<'a>() -> impl Parser<
'a,
header::KeywordItem<'a, ImportAsKeyword, Loc<Spaced<'a, header::TypedIdent<'a>>>>,
EImport<'a>,
> {
record!(header::KeywordItem {
keyword: module::spaces_around_keyword(
ImportAsKeyword,
EImport::As,
EImport::IndentAs,
EImport::IndentIngestedName
),
item: specialize(EImport::IngestedName, loc!(module::typed_ident()))
})
}
/// e.g. Things that can be on their own line in a def, e.g. `expect`, `expect-fx`, or `dbg`
#[allow(clippy::too_many_arguments)]
fn parse_statement_inside_def<'a>(

View file

@ -552,7 +552,7 @@ fn imports<'a>() -> impl Parser<
}
#[inline(always)]
fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<'a>> {
pub fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<'a>> {
// e.g.
//
// printLine : Str -> Effect {}

View file

@ -87,7 +87,7 @@ impl_space_problem! {
EGeneratesWith,
EHeader<'a>,
EIf<'a>,
EImport,
EImport<'a>,
EImports,
EInParens<'a>,
EClosure<'a>,
@ -347,7 +347,7 @@ pub enum EExpr<'a> {
Expect(EExpect<'a>, Position),
Dbg(EExpect<'a>, Position),
Import(EImport, Position),
Import(EImport<'a>, Position),
Closure(EClosure<'a>, Position),
Underscore(Position),
@ -520,7 +520,7 @@ pub enum EExpect<'a> {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EImport {
pub enum EImport<'a> {
Import(Position),
IndentStart(Position),
PackageShorthand(Position),
@ -535,6 +535,10 @@ pub enum EImport {
ExposingListStart(Position),
ExposedName(Position),
ExposingListEnd(Position),
IndentIngestedPath(Position),
IngestedPath(Position),
IndentIngestedName(Position),
IngestedName(ETypedIdent<'a>, Position),
Space(BadInputError, Position),
}

View file

@ -0,0 +1,2 @@
import "path/to/file.txt" as file : Str
import "path/to/file.txt" as file : List U8

View file

@ -0,0 +1,74 @@
Defs {
tags: [
Index(2147483648),
Index(2147483649),
],
regions: [
@0-39,
@40-85,
],
space_before: [
Slice(start = 0, length = 0),
Slice(start = 0, length = 1),
],
space_after: [
Slice(start = 0, length = 0),
Slice(start = 1, length = 0),
],
spaces: [
Newline,
],
type_defs: [],
value_defs: [
IngestedFileImport {
before_path: [],
path: @7-25 PlainLine(
"path/to/file.txt",
),
name: KeywordItem {
keyword: Spaces {
before: [],
item: ImportAsKeyword,
after: [],
},
item: @29-39 TypedIdent {
ident: @29-33 "file",
spaces_before_colon: [],
ann: @36-39 Apply(
"",
"Str",
[],
),
},
},
},
IngestedFileImport {
before_path: [],
path: @47-65 PlainLine(
"path/to/file.txt",
),
name: KeywordItem {
keyword: Spaces {
before: [],
item: ImportAsKeyword,
after: [],
},
item: @70-85 TypedIdent {
ident: @70-74 "file",
spaces_before_colon: [],
ann: @78-85 Apply(
"",
"List",
[
@83-85 Apply(
"",
"U8",
[],
),
],
),
},
},
},
],
}

View file

@ -0,0 +1,2 @@
import "path/to/file.txt" as file : Str
import "path/to/file.txt" as file : List U8

View file

@ -329,6 +329,7 @@ mod test_snapshots {
pass/import_with_alias.moduledefs,
pass/import_with_comments.moduledefs,
pass/import_with_exposed.moduledefs,
pass/ingested_file.moduledefs,
pass/int_with_underscore.expr,
pass/interface_with_newline.header,
pass/lambda_in_chain.expr,