mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-08 04:50:32 +00:00
Parse and format top-level import defs with no alias or exposed members
This commit is contained in:
parent
ebfcd71e8d
commit
933fde77a0
12 changed files with 117 additions and 25 deletions
|
@ -196,6 +196,7 @@ impl<'a> Formattable for ValueDef<'a> {
|
|||
Expect { condition, .. } => condition.is_multiline(),
|
||||
ExpectFx { condition, .. } => condition.is_multiline(),
|
||||
Dbg { condition, .. } => condition.is_multiline(),
|
||||
ModuleImport { name: _ } => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,6 +239,13 @@ impl<'a> Formattable for ValueDef<'a> {
|
|||
buf.newline();
|
||||
fmt_body(buf, &body_pattern.value, &body_expr.value, indent);
|
||||
}
|
||||
ModuleImport { name } => {
|
||||
buf.indent(indent);
|
||||
|
||||
buf.push_str("import");
|
||||
buf.spaces(1);
|
||||
buf.push_str(name.value.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -565,6 +565,9 @@ impl<'a> RemoveSpaces<'a> for ValueDef<'a> {
|
|||
condition: arena.alloc(condition.remove_spaces(arena)),
|
||||
preceding_comment: Region::zero(),
|
||||
},
|
||||
ModuleImport { name } => ModuleImport {
|
||||
name: name.remove_spaces(arena),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -455,6 +455,11 @@ pub enum ValueDef<'a> {
|
|||
condition: &'a Loc<Expr<'a>>,
|
||||
preceding_comment: Region,
|
||||
},
|
||||
|
||||
/// e.g. `import [Req] as Http from InternalHttp`.
|
||||
ModuleImport {
|
||||
name: Loc<crate::header::ModuleName<'a>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
|
@ -1792,6 +1797,7 @@ impl<'a> Malformed for ValueDef<'a> {
|
|||
condition,
|
||||
preceding_comment: _,
|
||||
} => condition.is_malformed(),
|
||||
ValueDef::ModuleImport { name } => name.value.contains_dot(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ use crate::keyword;
|
|||
use crate::parser::{
|
||||
self, backtrackable, increment_min_indent, line_min_indent, optional, reset_min_indent,
|
||||
sep_by1, sep_by1_e, set_min_indent, specialize, specialize_ref, then, word1, word1_indent,
|
||||
word2, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord, EString,
|
||||
EType, EWhen, Either, ParseResult, Parser,
|
||||
word2, EClosure, EExpect, EExpr, EIf, EImport, EInParens, EList, ENumber, EPattern, ERecord,
|
||||
EString, EType, EWhen, Either, ParseResult, Parser,
|
||||
};
|
||||
use crate::pattern::{closure_param, loc_implements_parser};
|
||||
use crate::state::State;
|
||||
|
@ -574,30 +574,43 @@ pub fn parse_single_def<'a>(
|
|||
min_indent,
|
||||
) {
|
||||
Err((NoProgress, _)) => {
|
||||
match parse_expect.parse(arena, state.clone(), min_indent) {
|
||||
match loc!(import()).parse(arena, state.clone(), min_indent) {
|
||||
Err((_, _)) => {
|
||||
// a hacky way to get expression-based error messages. TODO fix this
|
||||
Ok((NoProgress, None, initial))
|
||||
match parse_expect.parse(arena, state.clone(), min_indent) {
|
||||
Err((_, _)) => {
|
||||
// a hacky way to get expression-based error messages. TODO fix this
|
||||
Ok((NoProgress, None, initial))
|
||||
}
|
||||
Ok((_, expect_flavor, state)) => parse_statement_inside_def(
|
||||
arena,
|
||||
state,
|
||||
min_indent,
|
||||
options,
|
||||
start,
|
||||
spaces_before_current_start,
|
||||
spaces_before_current,
|
||||
|preceding_comment, loc_def_expr| match expect_flavor {
|
||||
Either::Second(_) => ValueDef::Expect {
|
||||
condition: arena.alloc(loc_def_expr),
|
||||
preceding_comment,
|
||||
},
|
||||
Either::First(_) => ValueDef::ExpectFx {
|
||||
condition: arena.alloc(loc_def_expr),
|
||||
preceding_comment,
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok((_, expect_flavor, state)) => parse_statement_inside_def(
|
||||
arena,
|
||||
Ok((_, loc_import, state)) => Ok((
|
||||
MadeProgress,
|
||||
Some(SingleDef {
|
||||
type_or_value: Either::Second(loc_import.value),
|
||||
region: loc_import.region,
|
||||
spaces_before: spaces_before_current,
|
||||
}),
|
||||
state,
|
||||
min_indent,
|
||||
options,
|
||||
start,
|
||||
spaces_before_current_start,
|
||||
spaces_before_current,
|
||||
|preceding_comment, loc_def_expr| match expect_flavor {
|
||||
Either::Second(_) => ValueDef::Expect {
|
||||
condition: arena.alloc(loc_def_expr),
|
||||
preceding_comment,
|
||||
},
|
||||
Either::First(_) => ValueDef::ExpectFx {
|
||||
condition: arena.alloc(loc_def_expr),
|
||||
preceding_comment,
|
||||
},
|
||||
},
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
Err((MadeProgress, _)) => {
|
||||
|
@ -823,6 +836,24 @@ pub fn parse_single_def<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn import<'a>() -> impl Parser<'a, ValueDef<'a>, EImport> {
|
||||
map!(
|
||||
skip_first!(
|
||||
and!(
|
||||
crate::parser::keyword_e(crate::keyword::IMPORT, EImport::Import),
|
||||
spaces()
|
||||
),
|
||||
loc!(crate::module::module_name_help(EImport::ModuleName))
|
||||
),
|
||||
|loc_module_name| {
|
||||
ValueDef::ModuleImport {
|
||||
name: loc_module_name,
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
|
|
|
@ -128,6 +128,10 @@ impl<'a> ModuleName<'a> {
|
|||
pub const fn as_str(&'a self) -> &'a str {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn contains_dot(&self) -> bool {
|
||||
self.0.contains('.')
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
|
|
|
@ -6,6 +6,7 @@ pub const WHEN: &str = "when";
|
|||
pub const AS: &str = "as";
|
||||
pub const IS: &str = "is";
|
||||
pub const DBG: &str = "dbg";
|
||||
pub const IMPORT: &str = "import";
|
||||
pub const EXPECT: &str = "expect";
|
||||
pub const EXPECT_FX: &str = "expect-fx";
|
||||
pub const CRASH: &str = "crash";
|
||||
|
@ -14,4 +15,6 @@ pub const CRASH: &str = "crash";
|
|||
pub const IMPLEMENTS: &str = "implements";
|
||||
pub const WHERE: &str = "where";
|
||||
|
||||
pub const KEYWORDS: [&str; 10] = [IF, THEN, ELSE, WHEN, AS, IS, DBG, EXPECT, EXPECT_FX, CRASH];
|
||||
pub const KEYWORDS: [&str; 11] = [
|
||||
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, EXPECT_FX, CRASH,
|
||||
];
|
||||
|
|
|
@ -590,7 +590,7 @@ fn shortname<'a>() -> impl Parser<'a, &'a str, EImports> {
|
|||
specialize(|_, pos| EImports::Shorthand(pos), lowercase_ident())
|
||||
}
|
||||
|
||||
fn module_name_help<'a, F, E>(to_expectation: F) -> impl Parser<'a, ModuleName<'a>, E>
|
||||
pub fn module_name_help<'a, F, E>(to_expectation: F) -> impl Parser<'a, ModuleName<'a>, E>
|
||||
where
|
||||
F: Fn(Position) -> E,
|
||||
E: 'a,
|
||||
|
|
|
@ -87,6 +87,7 @@ impl_space_problem! {
|
|||
EGeneratesWith,
|
||||
EHeader<'a>,
|
||||
EIf<'a>,
|
||||
EImport,
|
||||
EImports,
|
||||
EInParens<'a>,
|
||||
EClosure<'a>,
|
||||
|
@ -346,6 +347,7 @@ pub enum EExpr<'a> {
|
|||
|
||||
Expect(EExpect<'a>, Position),
|
||||
Dbg(EExpect<'a>, Position),
|
||||
Import(EImport, Position),
|
||||
|
||||
Closure(EClosure<'a>, Position),
|
||||
Underscore(Position),
|
||||
|
@ -517,6 +519,13 @@ pub enum EExpect<'a> {
|
|||
IndentCondition(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EImport {
|
||||
Import(Position),
|
||||
ModuleName(Position),
|
||||
Space(BadInputError, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EPattern<'a> {
|
||||
Record(PRecord<'a>, Position),
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
import Json
|
|
@ -0,0 +1,23 @@
|
|||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-12,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
spaces: [],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
ModuleImport {
|
||||
name: @8-12 ModuleName(
|
||||
"Json",
|
||||
),
|
||||
},
|
||||
],
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
import Json
|
|
@ -323,6 +323,7 @@ mod test_snapshots {
|
|||
pass/highest_float.expr,
|
||||
pass/highest_int.expr,
|
||||
pass/if_def.expr,
|
||||
pass/import.moduledefs,
|
||||
pass/int_with_underscore.expr,
|
||||
pass/interface_with_newline.header,
|
||||
pass/lambda_in_chain.expr,
|
||||
|
@ -568,6 +569,8 @@ mod test_snapshots {
|
|||
Err(err) => Err(format!("{err:?}")),
|
||||
};
|
||||
|
||||
println!("{:?}", result);
|
||||
|
||||
if expect == TestExpectation::Pass {
|
||||
let tokens = roc_parse::highlight::highlight(&source);
|
||||
for token in tokens {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue