mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
finished hadnle_new_char tests, bugfixes
This commit is contained in:
parent
81f44b936b
commit
33184b60f8
@ -15,7 +15,10 @@ pub struct CodeLines {
|
||||
impl CodeLines {
|
||||
pub fn from_str(code_str: &str) -> CodeLines {
|
||||
CodeLines {
|
||||
lines: code_str.split_inclusive('\n').map(|s| s.to_owned()).collect(),
|
||||
lines: code_str
|
||||
.split_inclusive('\n')
|
||||
.map(|s| s.to_owned())
|
||||
.collect(),
|
||||
nr_of_chars: code_str.len(),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::lang::ast::{RecordField};
|
||||
use super::attribute::Attributes;
|
||||
use crate::editor::ed_error::EdResult;
|
||||
use crate::editor::ed_error::ExpectedTextNode;
|
||||
@ -7,6 +6,7 @@ use crate::editor::ed_error::NestedNodeRequired;
|
||||
use crate::editor::slow_pool::MarkNodeId;
|
||||
use crate::editor::slow_pool::SlowPool;
|
||||
use crate::editor::syntax_highlight::HighlightStyle;
|
||||
use crate::lang::ast::RecordField;
|
||||
use crate::lang::{
|
||||
ast::Expr2,
|
||||
expr::Env,
|
||||
@ -200,7 +200,12 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||
Expr2::Var(symbol) => {
|
||||
//TODO make bump_format with arena
|
||||
let text = format!("{:?}", symbol);
|
||||
new_markup_node(text, expr2_node_id, HighlightStyle::Variable, markup_node_pool)
|
||||
new_markup_node(
|
||||
text,
|
||||
expr2_node_id,
|
||||
HighlightStyle::Variable,
|
||||
markup_node_pool,
|
||||
)
|
||||
}
|
||||
Expr2::List { elems, .. } => {
|
||||
let mut children_ids = vec![new_markup_node(
|
||||
@ -213,7 +218,13 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||
for (idx, node_id) in elems.iter_node_ids().enumerate() {
|
||||
let sub_expr2 = env.pool.get(node_id);
|
||||
|
||||
children_ids.push(expr2_to_markup(arena, env, sub_expr2, node_id, markup_node_pool));
|
||||
children_ids.push(expr2_to_markup(
|
||||
arena,
|
||||
env,
|
||||
sub_expr2,
|
||||
node_id,
|
||||
markup_node_pool,
|
||||
));
|
||||
|
||||
if idx + 1 < elems.len() {
|
||||
children_ids.push(new_markup_node(
|
||||
@ -284,20 +295,26 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||
markup_node_pool,
|
||||
));
|
||||
|
||||
children_ids.push(new_markup_node(
|
||||
COLON.to_string(),
|
||||
expr2_node_id,
|
||||
HighlightStyle::Operator,
|
||||
markup_node_pool,
|
||||
));
|
||||
|
||||
match record_field {
|
||||
RecordField::InvalidLabelOnly(_, _) => (),
|
||||
RecordField::LabelOnly(_, _, _) => (),
|
||||
RecordField::LabeledValue(_, _, sub_expr2_node_id) => {
|
||||
children_ids.push(new_markup_node(
|
||||
COLON.to_string(),
|
||||
expr2_node_id,
|
||||
HighlightStyle::Operator,
|
||||
markup_node_pool,
|
||||
));
|
||||
|
||||
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
|
||||
children_ids.push(expr2_to_markup(arena, env, sub_expr2, *sub_expr2_node_id, markup_node_pool));
|
||||
},
|
||||
children_ids.push(expr2_to_markup(
|
||||
arena,
|
||||
env,
|
||||
sub_expr2,
|
||||
*sub_expr2_node_id,
|
||||
markup_node_pool,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if idx + 1 < fields.len() {
|
||||
|
@ -23,7 +23,6 @@ use nonempty::NonEmpty;
|
||||
use roc_region::all::Region;
|
||||
use std::path::Path;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EdModel<'a> {
|
||||
pub module: EdModule<'a>,
|
||||
@ -68,8 +67,13 @@ pub fn init_model<'a>(
|
||||
} else {
|
||||
let ast_root = &module.env.pool.get(ast_root_id);
|
||||
|
||||
let temp_markup_root_id =
|
||||
expr2_to_markup(code_arena, &mut module.env, ast_root, ast_root_id, &mut markup_node_pool);
|
||||
let temp_markup_root_id = expr2_to_markup(
|
||||
code_arena,
|
||||
&mut module.env,
|
||||
ast_root,
|
||||
ast_root_id,
|
||||
&mut markup_node_pool,
|
||||
);
|
||||
set_parent_for_all(temp_markup_root_id, &mut markup_node_pool);
|
||||
|
||||
temp_markup_root_id
|
||||
@ -159,23 +163,25 @@ impl<'a> EdModule<'a> {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_ed_model {
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_selection_to_dsl;
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection;
|
||||
use std::{path::Path};
|
||||
use crate::editor::ed_error::EdResult;
|
||||
use crate::editor::mvc::ed_model;
|
||||
use crate::lang::expr::Env;
|
||||
use crate::lang::pool::Pool;
|
||||
use crate::editor::mvc::ed_model;
|
||||
use ed_model::EdModel;
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection;
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_selection_to_dsl;
|
||||
use crate::ui::text::lines::SelectableLines;
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use bumpalo::collections::String as BumpString;
|
||||
use bumpalo::Bump;
|
||||
use ed_model::EdModel;
|
||||
use roc_module::symbol::{IdentIds, ModuleIds};
|
||||
use roc_types::subs::VarStore;
|
||||
use bumpalo::collections::String as BumpString;
|
||||
use crate::editor::ed_error::EdResult;
|
||||
use crate::ui::text::lines::SelectableLines;
|
||||
use std::path::Path;
|
||||
|
||||
|
||||
pub fn init_dummy_model<'a>(code_str: &'a BumpString, ed_model_refs: &'a mut EdModelRefs) -> EdResult<EdModel<'a>> {
|
||||
pub fn init_dummy_model<'a>(
|
||||
code_str: &'a BumpString,
|
||||
ed_model_refs: &'a mut EdModelRefs,
|
||||
) -> EdResult<EdModel<'a>> {
|
||||
let file_path = Path::new("");
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(8);
|
||||
@ -189,14 +195,14 @@ use std::{path::Path};
|
||||
&mut ed_model_refs.env_pool,
|
||||
&mut ed_model_refs.var_store,
|
||||
dep_idents,
|
||||
& ed_model_refs.module_ids,
|
||||
&ed_model_refs.module_ids,
|
||||
exposed_ident_ids,
|
||||
);
|
||||
|
||||
ed_model::init_model(&code_str, file_path, env, &ed_model_refs.code_arena)
|
||||
}
|
||||
|
||||
pub struct EdModelRefs{
|
||||
pub struct EdModelRefs {
|
||||
code_arena: Bump,
|
||||
env_arena: Bump,
|
||||
env_pool: Pool,
|
||||
@ -214,11 +220,13 @@ use std::{path::Path};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ed_model_from_dsl<'a>(clean_code_str: &'a BumpString, code_lines: &[&str], ed_model_refs: &'a mut EdModelRefs) -> Result<EdModel<'a>, String> {
|
||||
pub fn ed_model_from_dsl<'a>(
|
||||
clean_code_str: &'a BumpString,
|
||||
code_lines: &[&str],
|
||||
ed_model_refs: &'a mut EdModelRefs,
|
||||
) -> Result<EdModel<'a>, String> {
|
||||
let code_lines_vec: Vec<String> = (*code_lines).iter().map(|s| s.to_string()).collect();
|
||||
let caret_w_select = convert_dsl_to_selection(
|
||||
&code_lines_vec
|
||||
)?;
|
||||
let caret_w_select = convert_dsl_to_selection(&code_lines_vec)?;
|
||||
|
||||
let mut ed_model = init_dummy_model(clean_code_str, ed_model_refs)?;
|
||||
|
||||
|
@ -443,12 +443,16 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
|
||||
Expr2::EmptyRecord => {
|
||||
let sibling_ids = curr_mark_node.get_sibling_ids(&ed_model.markup_node_pool);
|
||||
|
||||
update_empty_record(
|
||||
&ch.to_string(),
|
||||
prev_mark_node_id,
|
||||
sibling_ids,
|
||||
ed_model
|
||||
)?
|
||||
if ch.is_ascii_alphabetic() && ch.is_ascii_lowercase() {
|
||||
update_empty_record(
|
||||
&ch.to_string(),
|
||||
prev_mark_node_id,
|
||||
sibling_ids,
|
||||
ed_model
|
||||
)?
|
||||
} else {
|
||||
InputOutcome::Ignored
|
||||
}
|
||||
}
|
||||
_ => InputOutcome::Ignored
|
||||
}
|
||||
@ -488,26 +492,26 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_ed_update {
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use crate::editor::mvc::ed_model::test_ed_model::ed_model_to_dsl;
|
||||
use crate::editor::mvc::ed_update::EdResult;
|
||||
use crate::editor::mvc::ed_update::handle_new_char;
|
||||
use crate::editor::mvc::ed_model::test_ed_model::ed_model_from_dsl;
|
||||
use bumpalo::Bump;
|
||||
use bumpalo::collections::String as BumpString;
|
||||
use crate::editor::mvc::ed_model::test_ed_model::ed_model_to_dsl;
|
||||
use crate::editor::mvc::ed_model::test_ed_model::init_model_refs;
|
||||
use crate::editor::mvc::ed_update::handle_new_char;
|
||||
use crate::editor::mvc::ed_update::EdResult;
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use bumpalo::collections::String as BumpString;
|
||||
use bumpalo::Bump;
|
||||
|
||||
fn ed_res_to_res<T>(ed_res: EdResult<T>) -> Result<T, String> {
|
||||
match ed_res {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(e.to_string())
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn ui_res_to_res<T>(ed_res: UIResult<T>) -> Result<T, String> {
|
||||
match ed_res {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(e.to_string())
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,25 +520,16 @@ pub mod test_ed_update {
|
||||
expected_post_lines: &[&str],
|
||||
new_char: char,
|
||||
) -> Result<(), String> {
|
||||
|
||||
assert_insert_char_seq(
|
||||
pre_lines,
|
||||
expected_post_lines,
|
||||
&new_char.to_string()
|
||||
)
|
||||
assert_insert_seq(pre_lines, expected_post_lines, &new_char.to_string())
|
||||
}
|
||||
|
||||
pub fn assert_insert_char_seq(
|
||||
pub fn assert_insert_seq(
|
||||
pre_lines: &[&str],
|
||||
expected_post_lines: &[&str],
|
||||
new_char_seq: &str,
|
||||
) -> Result<(), String> {
|
||||
|
||||
let test_arena = Bump::new();
|
||||
let code_str = BumpString::from_str_in(
|
||||
&pre_lines.join("").replace("┃", ""),
|
||||
&test_arena
|
||||
);
|
||||
let code_str = BumpString::from_str_in(&pre_lines.join("").replace("┃", ""), &test_arena);
|
||||
|
||||
let mut model_refs = init_model_refs();
|
||||
|
||||
@ -551,6 +546,10 @@ pub mod test_ed_update {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn assert_insert_seq_ignore(lines: &[&str], new_char_seq: &str) -> Result<(), String> {
|
||||
assert_insert_seq(lines, lines, new_char_seq)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ignore_basic() -> Result<(), String> {
|
||||
// space is added because Blank is inserted
|
||||
@ -585,9 +584,21 @@ pub mod test_ed_update {
|
||||
assert_insert(&["\"ab ┃\""], &["\"ab {┃\""], '{')?;
|
||||
assert_insert(&["\"ab ┃\""], &["\"ab }┃\""], '}')?;
|
||||
assert_insert(&["\"{ str: 4┃}\""], &["\"{ str: 44┃}\""], '4')?;
|
||||
assert_insert(&["\"┃ello, hello, hello\""], &["\"h┃ello, hello, hello\""], 'h')?;
|
||||
assert_insert(&["\"hello┃ hello, hello\""], &["\"hello,┃ hello, hello\""], ',')?;
|
||||
assert_insert(&["\"hello, hello, hello┃\""], &["\"hello, hello, hello.┃\""], '.')?;
|
||||
assert_insert(
|
||||
&["\"┃ello, hello, hello\""],
|
||||
&["\"h┃ello, hello, hello\""],
|
||||
'h',
|
||||
)?;
|
||||
assert_insert(
|
||||
&["\"hello┃ hello, hello\""],
|
||||
&["\"hello,┃ hello, hello\""],
|
||||
',',
|
||||
)?;
|
||||
assert_insert(
|
||||
&["\"hello, hello, hello┃\""],
|
||||
&["\"hello, hello, hello.┃\""],
|
||||
'.',
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -650,31 +661,41 @@ pub mod test_ed_update {
|
||||
|
||||
assert_insert(&["\"[ 1, 2, 3 ]\"┃"], &["\"[ 1, 2, 3 ]\"┃"], '{')?;
|
||||
assert_insert(&["┃\"[ 1, 2, 3 ]\""], &["┃\"[ 1, 2, 3 ]\""], '{')?;
|
||||
assert_insert(&["\"hello, hello, hello\"┃"], &["\"hello, hello, hello\"┃"], '.')?;
|
||||
assert_insert(&["┃\"hello, hello, hello\""], &["┃\"hello, hello, hello\""], '.')?;
|
||||
assert_insert(
|
||||
&["\"hello, hello, hello\"┃"],
|
||||
&["\"hello, hello, hello\"┃"],
|
||||
'.',
|
||||
)?;
|
||||
assert_insert(
|
||||
&["┃\"hello, hello, hello\""],
|
||||
&["┃\"hello, hello, hello\""],
|
||||
'.',
|
||||
)?;
|
||||
|
||||
// TODO char_seq
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_record() -> Result<(), String> {
|
||||
// assert_insert(&["┃"], &["{ ┃ }"], '{')?;
|
||||
// assert_insert(&["{ ┃ }"], &["{ a┃ }"], 'a')?;
|
||||
// assert_insert(&["{ a┃ }"], &["{ ab┃ }"], 'b')?;
|
||||
// assert_insert(&["{ ab┃ }"], &["{ abc┃ }"], 'c')?;
|
||||
// assert_insert(&["{ ┃ab }"], &["{ z┃abc }"], 'z')?;
|
||||
// assert_insert(&["{ a┃b }"], &["{ az┃b }"], 'z')?;
|
||||
assert_insert(&["┃"], &["{ ┃ }"], '{')?;
|
||||
assert_insert(&["{ ┃ }"], &["{ a┃ }"], 'a')?;
|
||||
assert_insert(&["{ a┃ }"], &["{ ab┃ }"], 'b')?;
|
||||
assert_insert(&["{ a┃ }"], &["{ a1┃ }"], '1')?;
|
||||
assert_insert(&["{ a1┃ }"], &["{ a1z┃ }"], 'z')?;
|
||||
assert_insert(&["{ a1┃ }"], &["{ a15┃ }"], '5')?;
|
||||
assert_insert(&["{ ab┃ }"], &["{ abc┃ }"], 'c')?;
|
||||
assert_insert(&["{ ┃abc }"], &["{ z┃abc }"], 'z')?;
|
||||
assert_insert(&["{ a┃b }"], &["{ az┃b }"], 'z')?;
|
||||
assert_insert(&["{ a┃b }"], &["{ a9┃b }"], '9')?;
|
||||
|
||||
// assert_insert(&["{ a┃ }"], &["{ a: ┃ }"], ':')?;
|
||||
// assert_insert(&["{ abc┃ }"], &["{ abc: ┃ }"], ':')?;
|
||||
// assert_insert(&["{ aBc┃ }"], &["{ aBc: ┃ }"], ':')?;
|
||||
// extra space for Blank node
|
||||
assert_insert(&["{ a┃ }"], &["{ a: ┃ }"], ':')?;
|
||||
assert_insert(&["{ abc┃ }"], &["{ abc: ┃ }"], ':')?;
|
||||
assert_insert(&["{ aBc┃ }"], &["{ aBc: ┃ }"], ':')?;
|
||||
|
||||
// TODO use assert_insert_char_seq here
|
||||
// assert_insert(&["{ a: ┃ }"], &["{ a: \"┃\" }"], '"')?;
|
||||
// assert_insert(&["{ abc: ┃ }"], &["{ abc: \"┃\" }"], '"')?;
|
||||
|
||||
// assert_insert(&["{ a: ┃ }"], &["{ a: { ┃ }"], '{')?;
|
||||
// assert_insert(&["{ abc: ┃ }"], &["{ abc: { ┃ }"], '{')?;
|
||||
assert_insert_seq(&["{ a┃ }"], &["{ a: \"┃\" }"], ":\"")?;
|
||||
assert_insert_seq(&["{ abc┃ }"], &["{ abc: \"┃\" }"], ":\"")?;
|
||||
|
||||
assert_insert(&["{ a: \"┃\" }"], &["{ a: \"a┃\" }"], 'a')?;
|
||||
assert_insert(&["{ a: \"a┃\" }"], &["{ a: \"ab┃\" }"], 'b')?;
|
||||
@ -688,50 +709,328 @@ pub mod test_ed_update {
|
||||
assert_insert(&["{ ┃a: \"\" }"], &["{ z┃a: \"\" }"], 'z')?;
|
||||
assert_insert(&["{ ab┃: \"\" }"], &["{ abc┃: \"\" }"], 'c')?;
|
||||
assert_insert(&["{ ┃ab: \"\" }"], &["{ z┃ab: \"\" }"], 'z')?;
|
||||
assert_insert(&["{ camelCase┃: \"hello\" }"], &["{ camelCaseB┃: \"hello\" }"], 'B')?;
|
||||
assert_insert(&["{ camel┃Case: \"hello\" }"], &["{ camelZ┃Case: \"hello\" }"], 'Z')?;
|
||||
assert_insert(&["{ ┃camelCase: \"hello\" }"], &["{ z┃camelCase: \"hello\" }"], 'z')?;
|
||||
assert_insert(
|
||||
&["{ camelCase┃: \"hello\" }"],
|
||||
&["{ camelCaseB┃: \"hello\" }"],
|
||||
'B',
|
||||
)?;
|
||||
assert_insert(
|
||||
&["{ camel┃Case: \"hello\" }"],
|
||||
&["{ camelZ┃Case: \"hello\" }"],
|
||||
'Z',
|
||||
)?;
|
||||
assert_insert(
|
||||
&["{ ┃camelCase: \"hello\" }"],
|
||||
&["{ z┃camelCase: \"hello\" }"],
|
||||
'z',
|
||||
)?;
|
||||
|
||||
assert_insert_seq(&["┃"], &["{ camelCase: \"hello┃\" }"], "{camelCase:\"hello")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_record() -> Result<(), String> {
|
||||
// TODO construct nested record
|
||||
assert_insert_seq(&["{ a┃ }"], &["{ a: { ┃ } }"], ":{")?;
|
||||
assert_insert_seq(&["{ abc┃ }"], &["{ abc: { ┃ } }"], ":{")?;
|
||||
assert_insert_seq(&["{ camelCase┃ }"], &["{ camelCase: { ┃ } }"], ":{")?;
|
||||
|
||||
assert_insert_char_seq(&["{ ┃ }"], &["{ a: { ┃ } }"], "a:{")?;
|
||||
assert_insert_char_seq(&["{ ┃ }"], &["{ abc: { ┃ } }"], "abc:{")?;
|
||||
assert_insert_char_seq(&["{ ┃ }"], &["{ camelCase: { ┃ } }"], "camelCase:{")?;
|
||||
assert_insert_seq(&["{ a: { ┃ } }"], &["{ a: { zulu┃ } }"], "zulu")?;
|
||||
assert_insert_seq(
|
||||
&["{ abc: { ┃ } }"],
|
||||
&["{ abc: { camelCase┃ } }"],
|
||||
"camelCase",
|
||||
)?;
|
||||
assert_insert_seq(&["{ camelCase: { ┃ } }"], &["{ camelCase: { z┃ } }"], "z")?;
|
||||
|
||||
assert_insert_seq(&["{ a: { zulu┃ } }"], &["{ a: { zulu: ┃ } }"], ":")?;
|
||||
assert_insert_seq(
|
||||
&["{ abc: { camelCase┃ } }"],
|
||||
&["{ abc: { camelCase: ┃ } }"],
|
||||
":",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ camelCase: { z┃ } }"],
|
||||
&["{ camelCase: { z: ┃ } }"],
|
||||
":",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(&["{ a┃: { zulu } }"], &["{ a0┃: { zulu } }"], "0")?;
|
||||
assert_insert_seq(
|
||||
&["{ ab┃c: { camelCase } }"],
|
||||
&["{ abz┃c: { camelCase } }"],
|
||||
"z",
|
||||
)?;
|
||||
assert_insert_seq(&["{ ┃camelCase: { z } }"], &["{ x┃camelCase: { z } }"], "x")?;
|
||||
|
||||
assert_insert_seq(&["{ a: { zulu┃ } }"], &["{ a: { zulu: \"┃\" } }"], ":\"")?;
|
||||
assert_insert_seq(
|
||||
&["{ abc: { camelCase┃ } }"],
|
||||
&["{ abc: { camelCase: \"┃\" } }"],
|
||||
":\"",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ camelCase: { z┃ } }"],
|
||||
&["{ camelCase: { z: \"┃\" } }"],
|
||||
":\"",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(
|
||||
&["{ a: { zulu: \"┃\" } }"],
|
||||
&["{ a: { zulu: \"azula┃\" } }"],
|
||||
"azula",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ a: { zulu: \"az┃a\" } }"],
|
||||
&["{ a: { zulu: \"azul┃a\" } }"],
|
||||
"ul",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(&["{ a: { zulu┃ } }"], &["{ a: { zulu: { ┃ } } }"], ":{")?;
|
||||
assert_insert_seq(
|
||||
&["{ abc: { camelCase┃ } }"],
|
||||
&["{ abc: { camelCase: { ┃ } } }"],
|
||||
":{",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ camelCase: { z┃ } }"],
|
||||
&["{ camelCase: { z: { ┃ } } }"],
|
||||
":{",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(
|
||||
&["{ a: { zulu: { ┃ } } }"],
|
||||
&["{ a: { zulu: { he┃ } } }"],
|
||||
"he",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ a: { ┃zulu: { } } }"],
|
||||
&["{ a: { x┃zulu: { } } }"],
|
||||
"x",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ a: { z┃ulu: { } } }"],
|
||||
&["{ a: { z9┃ulu: { } } }"],
|
||||
"9",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ a: { zulu┃: { } } }"],
|
||||
&["{ a: { zulu7┃: { } } }"],
|
||||
"7",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(
|
||||
&["{ a┃: { bcD: { eFgHij: { k15 } } } }"],
|
||||
&["{ a4┃: { bcD: { eFgHij: { k15 } } } }"],
|
||||
"4",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ ┃a: { bcD: { eFgHij: { k15 } } } }"],
|
||||
&["{ y┃a: { bcD: { eFgHij: { k15 } } } }"],
|
||||
"y",
|
||||
)?;
|
||||
assert_insert_seq(
|
||||
&["{ a: { bcD: { eF┃gHij: { k15 } } } }"],
|
||||
&["{ a: { bcD: { eFxyz┃gHij: { k15 } } } }"],
|
||||
"xyz",
|
||||
)?;
|
||||
|
||||
assert_insert_seq(
|
||||
&["┃"],
|
||||
&["{ g: { oi: { ng: { d: { e: { e: { p: { camelCase┃ } } } } } } } }"],
|
||||
"{g:{oi:{ng:{d:{e:{e:{p:{camelCase",
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ignore_record() -> Result<(), String> {
|
||||
assert_insert(&["┃{ }"], &["┃{ }"], 'a')?;
|
||||
assert_insert(&["┃{ }"], &["┃{ }"], '{')?;
|
||||
assert_insert(&["┃{ }"], &["┃{ }"], '"')?;
|
||||
assert_insert(&["┃{ }"], &["┃{ }"], '5')?;
|
||||
assert_insert_seq_ignore(&["┃{ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ }┃"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃}"], "a{\"5")?;
|
||||
|
||||
assert_insert(&["{ }┃"], &["{ }┃"], 'a')?;
|
||||
assert_insert(&["{ }┃"], &["{ }┃"], '{')?;
|
||||
assert_insert(&["{ }┃"], &["{ }┃"], '"')?;
|
||||
assert_insert(&["{ }┃"], &["{ }┃"], '5')?;
|
||||
assert_insert_seq_ignore(&["{ ┃ }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃a }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃abc }"], "{\"5")?;
|
||||
|
||||
assert_insert(&["{┃ }"], &["{┃ }"], 'a')?;
|
||||
assert_insert(&["{┃ }"], &["{┃ }"], '{')?;
|
||||
assert_insert(&["{┃ }"], &["{┃ }"], '"')?;
|
||||
assert_insert(&["{┃ }"], &["{┃ }"], '5')?;
|
||||
assert_insert_seq_ignore(&["┃{ a }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a }┃"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a ┃}"], "a{\"5")?;
|
||||
|
||||
assert_insert(&["{ ┃}"], &["{ ┃}"], 'a')?;
|
||||
assert_insert(&["{ ┃}"], &["{ ┃}"], '{')?;
|
||||
assert_insert(&["{ ┃}"], &["{ ┃}"], '"')?;
|
||||
assert_insert(&["{ ┃}"], &["{ ┃}"], '5')?;
|
||||
assert_insert_seq_ignore(&["┃{ a15 }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a15 }┃"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a15 }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a15 ┃}"], "a{\"5")?;
|
||||
|
||||
// TODO non-empty records
|
||||
assert_insert_seq_ignore(&["┃{ camelCase }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCase }┃"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ camelCase }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCase ┃}"], "a{\"5")?;
|
||||
|
||||
assert_insert_seq_ignore(&["┃{ a: \"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a: \"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: ┃\"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"\"┃ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"\" }┃"], "a{\"5")?;
|
||||
|
||||
assert_insert_seq_ignore(&["┃{ camelCase: \"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ camelCase: \"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCase: ┃\"\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCase: \"\"┃ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCase: \"\" }┃"], "a{\"5")?;
|
||||
|
||||
assert_insert_seq_ignore(&["┃{ a: \"z\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a: \"z\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: ┃\"z\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"z\"┃ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"z\" }┃"], "a{\"5")?;
|
||||
|
||||
assert_insert_seq_ignore(&["┃{ a: \"hello, hello.12345ZXY{}[]-><-\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a: \"hello, hello.12345ZXY{}[]-><-\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: ┃\"hello, hello.12345ZXY{}[]-><-\" }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"hello, hello.12345ZXY{}[]-><-\"┃ }"], "a{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: \"hello, hello.12345ZXY{}[]-><-\" }┃"], "a{\"5")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ignore_nested_record() -> Result<(), String> {
|
||||
assert_insert_seq_ignore(&["{ a: { ┃ } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: ┃{ } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: {┃ } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: { }┃ }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: { } ┃}"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a: { } }┃"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ a:┃ { } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ a: { } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["┃{ a: { } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃a: { } }"], "1")?;
|
||||
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a ┃} }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: {┃ z15a } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: ┃{ z15a } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a }┃ }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a } ┃}"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a } }┃"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1:┃ { z15a } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ camelCaseB1: { z15a } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["┃{ camelCaseB1: { z15a } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃camelCaseB1: { z15a } }"], "1")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { ┃z15a } }"], "1")?;
|
||||
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: \"\"┃ } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: ┃\"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a:┃ \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: \"\" ┃} }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: {┃ z15a: \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: ┃{ z15a: \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: \"\" }┃ }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: \"\" } ┃}"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { z15a: \"\" } }┃"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1:┃ { z15a: \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{┃ camelCaseB1: { z15a: \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["┃{ camelCaseB1: { z15a: \"\" } }"], "{\"5")?;
|
||||
assert_insert_seq_ignore(&["{ ┃camelCaseB1: { z15a: \"\" } }"], "1")?;
|
||||
assert_insert_seq_ignore(&["{ camelCaseB1: { ┃z15a: \"\" } }"], "1")?;
|
||||
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\"┃ } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: ┃\"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a:┃ \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" ┃} }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: {┃ z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: ┃{ z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" }┃ }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" } ┃}"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" } }┃"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1:┃ { z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{┃ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["┃{ camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ ┃camelCaseB1: { z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"1",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ camelCaseB1: { ┃z15a: \"hello, hello.12345ZXY{}[]-><-\" } }"],
|
||||
"1",
|
||||
)?;
|
||||
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: { e: { p: { camelCase ┃} } } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: { e: { p: { camelCase } ┃} } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }┃"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } ┃} } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: {┃ e: { p: { camelCase } } } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ g: { oi: { ng: { d: { e: { e:┃ { p: { camelCase } } } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{┃ g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["┃{ g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
|
||||
"{\"5",
|
||||
)?;
|
||||
assert_insert_seq_ignore(
|
||||
&["{ ┃g: { oi: { ng: { d: { e: { e: { p: { camelCase } } } } } } } }"],
|
||||
"2",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::lang::ast::RecordField;
|
||||
use crate::editor::ed_error::EdResult;
|
||||
use crate::editor::ed_error::MissingParent;
|
||||
use crate::editor::ed_error::RecordWithoutFields;
|
||||
@ -13,6 +12,7 @@ use crate::editor::slow_pool::MarkNodeId;
|
||||
use crate::editor::syntax_highlight::HighlightStyle;
|
||||
use crate::editor::util::index_of;
|
||||
use crate::lang::ast::Expr2;
|
||||
use crate::lang::ast::RecordField;
|
||||
use crate::lang::pool::{NodeId, PoolStr, PoolVec};
|
||||
use crate::ui::text::text_pos::TextPos;
|
||||
use snafu::OptionExt;
|
||||
@ -197,12 +197,11 @@ pub fn update_record_colon(
|
||||
.next()
|
||||
.with_context(|| RecordWithoutFields {})?;
|
||||
|
||||
*first_field_mut =
|
||||
RecordField::LabeledValue(
|
||||
*first_field_mut.get_record_field_pool_str(),
|
||||
*first_field_mut.get_record_field_var(),
|
||||
new_field_val_id
|
||||
);
|
||||
*first_field_mut = RecordField::LabeledValue(
|
||||
*first_field_mut.get_record_field_pool_str(),
|
||||
*first_field_mut.get_record_field_var(),
|
||||
new_field_val_id,
|
||||
);
|
||||
|
||||
// update Markup
|
||||
let record_colon = nodes::COLON;
|
||||
@ -277,6 +276,17 @@ pub fn update_record_field(
|
||||
let node_caret_offset = ed_model
|
||||
.grid_node_map
|
||||
.get_offset_to_node_id(old_caret_pos, curr_mark_node_id)?;
|
||||
|
||||
if node_caret_offset == 0 {
|
||||
let first_char_opt = new_input.chars().next();
|
||||
let first_char_is_num = first_char_opt.unwrap_or('0').is_ascii_digit();
|
||||
|
||||
// variable name can't start with number
|
||||
if first_char_is_num {
|
||||
return Ok(InputOutcome::Ignored);
|
||||
}
|
||||
}
|
||||
|
||||
content_str_mut.insert_str(node_caret_offset, new_input);
|
||||
|
||||
// update caret
|
||||
@ -296,7 +306,9 @@ pub fn update_record_field(
|
||||
.next()
|
||||
.with_context(|| RecordWithoutFields {})?;
|
||||
|
||||
let field_pool_str = first_field.get_record_field_pool_str().as_str(ed_model.module.env.pool);
|
||||
let field_pool_str = first_field
|
||||
.get_record_field_pool_str()
|
||||
.as_str(ed_model.module.env.pool);
|
||||
|
||||
let mut new_field_name = String::new();
|
||||
|
||||
@ -321,23 +333,22 @@ pub fn update_record_field(
|
||||
|
||||
match first_field_b {
|
||||
RecordField::InvalidLabelOnly(_, _) => {
|
||||
// TODO check if label is now valid
|
||||
},
|
||||
// TODO check if label is now valid. If it is, return LabelOnly
|
||||
}
|
||||
RecordField::LabelOnly(_, _, _symbol) => {
|
||||
// TODO check if symbol is still valid
|
||||
},
|
||||
// TODO check if symbol is still valid. If not, return InvalidLabelOnly
|
||||
}
|
||||
RecordField::LabeledValue(_, _, field_val_id_ref) => {
|
||||
let field_val_id = *field_val_id_ref;
|
||||
let sub_expr2 = ed_model.module.env.pool.get(field_val_id);
|
||||
|
||||
if let Expr2::InvalidLookup(_) = sub_expr2 {
|
||||
ed_model
|
||||
.module
|
||||
.env
|
||||
.pool
|
||||
.set(field_val_id, Expr2::InvalidLookup(new_field_pool_str));
|
||||
.module
|
||||
.env
|
||||
.pool
|
||||
.set(field_val_id, Expr2::InvalidLookup(new_field_pool_str));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ pub enum FloatVal {
|
||||
pub enum RecordField {
|
||||
InvalidLabelOnly(PoolStr, Variable),
|
||||
LabelOnly(PoolStr, Variable, Symbol),
|
||||
LabeledValue(PoolStr, Variable, NodeId<Expr2>)
|
||||
LabeledValue(PoolStr, Variable, NodeId<Expr2>),
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -166,7 +166,7 @@ pub enum Expr2 {
|
||||
},
|
||||
// Product Types
|
||||
Record {
|
||||
record_var: Variable, // 4B
|
||||
record_var: Variable, // 4B
|
||||
fields: PoolVec<RecordField>, // TODO ??B
|
||||
},
|
||||
/// Empty record constant
|
||||
@ -190,10 +190,10 @@ pub enum Expr2 {
|
||||
field_var: Variable, // 4B
|
||||
},
|
||||
Update {
|
||||
symbol: Symbol, // 8B
|
||||
symbol: Symbol, // 8B
|
||||
updates: PoolVec<RecordField>, // 8B
|
||||
record_var: Variable, // 4B
|
||||
ext_var: Variable, // 4B
|
||||
record_var: Variable, // 4B
|
||||
ext_var: Variable, // 4B
|
||||
},
|
||||
|
||||
// Sum Types
|
||||
@ -311,7 +311,6 @@ pub type ExprId = NodeId<Expr2>;
|
||||
|
||||
use RecordField::*;
|
||||
impl RecordField {
|
||||
|
||||
pub fn get_record_field_var(&self) -> &Variable {
|
||||
match self {
|
||||
InvalidLabelOnly(_, var) => var,
|
||||
@ -409,7 +408,7 @@ fn expr2_to_string_helper(
|
||||
pool_str.as_str(pool),
|
||||
var,
|
||||
));
|
||||
},
|
||||
}
|
||||
RecordField::LabelOnly(pool_str, var, symbol) => {
|
||||
out_string.push_str(&format!(
|
||||
"{}({}, Var({:?}), Symbol({:?})",
|
||||
@ -418,7 +417,7 @@ fn expr2_to_string_helper(
|
||||
var,
|
||||
symbol
|
||||
));
|
||||
},
|
||||
}
|
||||
RecordField::LabeledValue(pool_str, var, val_node_id) => {
|
||||
out_string.push_str(&format!(
|
||||
"{}({}, Var({:?}), Expr2(\n",
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![allow(clippy::all)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
use crate::lang::ast::expr2_to_string;
|
||||
use crate::lang::ast::RecordField;
|
||||
use crate::lang::ast::{ClosureExtra, Expr2, ExprId, FloatVal, IntStyle, IntVal, WhenBranch};
|
||||
use crate::lang::def::References;
|
||||
@ -1014,32 +1015,57 @@ enum CanonicalizeRecordProblem {
|
||||
record_region: Region,
|
||||
},
|
||||
}
|
||||
|
||||
enum FieldVar {
|
||||
VarAndExprId(Variable, ExprId),
|
||||
OnlyVar(Variable),
|
||||
}
|
||||
|
||||
fn canonicalize_fields<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
fields: &'a [Located<roc_parse::ast::AssignedField<'a, roc_parse::ast::Expr<'a>>>],
|
||||
) -> Result<(PoolVec<RecordField>, Output), CanonicalizeRecordProblem> {
|
||||
let mut can_fields: MutMap<&'a str, (Variable, ExprId)> = MutMap::default();
|
||||
let mut can_fields: MutMap<&'a str, FieldVar> = MutMap::default();
|
||||
let mut output = Output::default();
|
||||
|
||||
for loc_field in fields.iter() {
|
||||
match canonicalize_field(env, scope, &loc_field.value) {
|
||||
Ok((label, field_expr, field_out, field_var)) => {
|
||||
let expr_id = env.pool.add(field_expr);
|
||||
let replaced = can_fields.insert(label, (field_var, expr_id));
|
||||
Ok(can_field) => {
|
||||
match can_field {
|
||||
CanonicalField::LabelAndValue {
|
||||
label,
|
||||
value_expr,
|
||||
value_output,
|
||||
var,
|
||||
} => {
|
||||
let expr_id = env.pool.add(value_expr);
|
||||
|
||||
if let Some(_old) = replaced {
|
||||
// env.problems.push(Problem::DuplicateRecordFieldValue {
|
||||
// field_name: label,
|
||||
// field_region: loc_field.region,
|
||||
// record_region: region,
|
||||
// replaced_region: old.region,
|
||||
// });
|
||||
todo!()
|
||||
let replaced =
|
||||
can_fields.insert(label, FieldVar::VarAndExprId(var, expr_id));
|
||||
|
||||
if let Some(_old) = replaced {
|
||||
// env.problems.push(Problem::DuplicateRecordFieldValue {
|
||||
// field_name: label,
|
||||
// field_region: loc_field.region,
|
||||
// record_region: region,
|
||||
// replaced_region: old.region,
|
||||
// });
|
||||
todo!()
|
||||
}
|
||||
|
||||
output.references.union_mut(value_output.references);
|
||||
}
|
||||
CanonicalField::InvalidLabelOnly { label, var } => {
|
||||
let replaced = can_fields.insert(label, FieldVar::OnlyVar(var));
|
||||
|
||||
if let Some(_old) = replaced {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output.references.union_mut(field_out.references);
|
||||
}
|
||||
|
||||
Err(CanonicalizeFieldProblem::InvalidOptionalValue {
|
||||
field_name: _,
|
||||
field_region: _,
|
||||
@ -1061,10 +1087,17 @@ fn canonicalize_fields<'a>(
|
||||
|
||||
let pool_vec = PoolVec::with_capacity(can_fields.len() as u32, env.pool);
|
||||
|
||||
for (node_id, (string, (var, expr_id))) in pool_vec.iter_node_ids().zip(can_fields.into_iter())
|
||||
{
|
||||
for (node_id, (string, field_var)) in pool_vec.iter_node_ids().zip(can_fields.into_iter()) {
|
||||
let name = PoolStr::new(string, env.pool);
|
||||
env.pool[node_id] = RecordField::LabeledValue(name, var, expr_id);
|
||||
|
||||
match field_var {
|
||||
FieldVar::VarAndExprId(var, expr_id) => {
|
||||
env.pool[node_id] = RecordField::LabeledValue(name, var, expr_id);
|
||||
}
|
||||
FieldVar::OnlyVar(var) => {
|
||||
env.pool[node_id] = RecordField::InvalidLabelOnly(name, var);
|
||||
} // TODO RecordField::LabelOnly
|
||||
}
|
||||
}
|
||||
|
||||
Ok((pool_vec, output))
|
||||
@ -1076,11 +1109,23 @@ enum CanonicalizeFieldProblem {
|
||||
field_region: Region,
|
||||
},
|
||||
}
|
||||
enum CanonicalField<'a> {
|
||||
LabelAndValue {
|
||||
label: &'a str,
|
||||
value_expr: Expr2,
|
||||
value_output: Output,
|
||||
var: Variable,
|
||||
},
|
||||
InvalidLabelOnly {
|
||||
label: &'a str,
|
||||
var: Variable,
|
||||
}, // TODO make ValidLabelOnly
|
||||
}
|
||||
fn canonicalize_field<'a>(
|
||||
env: &mut Env<'a>,
|
||||
scope: &mut Scope,
|
||||
field: &'a roc_parse::ast::AssignedField<'a, roc_parse::ast::Expr<'a>>,
|
||||
) -> Result<(&'a str, Expr2, Output, Variable), CanonicalizeFieldProblem> {
|
||||
) -> Result<CanonicalField<'a>, CanonicalizeFieldProblem> {
|
||||
use roc_parse::ast::AssignedField::*;
|
||||
|
||||
match field {
|
||||
@ -1089,7 +1134,12 @@ fn canonicalize_field<'a>(
|
||||
let field_var = env.var_store.fresh();
|
||||
let (loc_can_expr, output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region);
|
||||
|
||||
Ok((label.value, loc_can_expr, output, field_var))
|
||||
Ok(CanonicalField::LabelAndValue {
|
||||
label: label.value,
|
||||
value_expr: loc_can_expr,
|
||||
value_output: output,
|
||||
var: field_var,
|
||||
})
|
||||
}
|
||||
|
||||
OptionalValue(label, _, loc_expr) => Err(CanonicalizeFieldProblem::InvalidOptionalValue {
|
||||
@ -1098,8 +1148,13 @@ fn canonicalize_field<'a>(
|
||||
}),
|
||||
|
||||
// A label with no value, e.g. `{ name }` (this is sugar for { name: name })
|
||||
LabelOnly(_) => {
|
||||
panic!("Somehow a LabelOnly record field was not desugared!");
|
||||
LabelOnly(label) => {
|
||||
let field_var = env.var_store.fresh();
|
||||
// TODO return ValidLabel if label points to in scope variable
|
||||
Ok(CanonicalField::InvalidLabelOnly {
|
||||
label: label.value,
|
||||
var: field_var,
|
||||
})
|
||||
}
|
||||
|
||||
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
|
||||
|
@ -423,8 +423,8 @@ impl fmt::Debug for BigTextArea {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_big_sel_text {
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_selection_to_dsl;
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection;
|
||||
use crate::ui::text::caret_w_select::test_caret_w_select::convert_selection_to_dsl;
|
||||
use crate::ui::text::{
|
||||
big_text_area::from_str,
|
||||
big_text_area::BigTextArea,
|
||||
@ -434,7 +434,7 @@ pub mod test_big_sel_text {
|
||||
use crate::ui::ui_error::{OutOfBounds, UIResult};
|
||||
use crate::window::keyboard_input::{no_mods, Modifiers};
|
||||
use snafu::OptionExt;
|
||||
use std::{slice::SliceIndex};
|
||||
use std::slice::SliceIndex;
|
||||
|
||||
fn shift_pressed() -> Modifiers {
|
||||
Modifiers {
|
||||
@ -508,8 +508,7 @@ pub mod test_big_sel_text {
|
||||
}
|
||||
|
||||
let actual_lines = all_lines_vec(&big_text);
|
||||
let dsl_slice =
|
||||
convert_selection_to_dsl(big_text.caret_w_select, actual_lines).unwrap();
|
||||
let dsl_slice = convert_selection_to_dsl(big_text.caret_w_select, actual_lines).unwrap();
|
||||
assert_eq!(dsl_slice, expected_post_lines_str);
|
||||
|
||||
Ok(())
|
||||
@ -632,8 +631,7 @@ pub mod test_big_sel_text {
|
||||
big_text.select_all().unwrap();
|
||||
|
||||
let big_text_lines = all_lines_vec(&big_text);
|
||||
let post_lines_str =
|
||||
convert_selection_to_dsl(big_text.caret_w_select, big_text_lines)?;
|
||||
let post_lines_str = convert_selection_to_dsl(big_text.caret_w_select, big_text_lines)?;
|
||||
|
||||
assert_eq!(post_lines_str, expected_post_lines_str);
|
||||
|
||||
|
@ -114,16 +114,16 @@ pub fn make_caret_rect(
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test_caret_w_select {
|
||||
use crate::ui::ui_error::OutOfBounds;
|
||||
use crate::ui::util::slice_get;
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use crate::ui::text::caret_w_select::CaretWSelect;
|
||||
use crate::ui::text::selection::validate_selection;
|
||||
use crate::ui::text::text_pos::TextPos;
|
||||
use crate::ui::text::caret_w_select::CaretWSelect;
|
||||
use crate::ui::ui_error::OutOfBounds;
|
||||
use crate::ui::ui_error::UIResult;
|
||||
use crate::ui::util::slice_get;
|
||||
use core::cmp::Ordering;
|
||||
use pest::Parser;
|
||||
use std::{collections::HashMap, slice::SliceIndex};
|
||||
use snafu::OptionExt;
|
||||
use std::{collections::HashMap, slice::SliceIndex};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "../tests/selection.pest"]
|
||||
|
Loading…
Reference in New Issue
Block a user