moved all crates into seperate folder + related path fixes

This commit is contained in:
Anton-4 2022-07-01 17:37:43 +02:00
parent 12ef03bb86
commit eee85fa45d
No known key found for this signature in database
GPG key ID: C954D6E0F9C0ABFD
1063 changed files with 92 additions and 93 deletions

View file

@ -0,0 +1,124 @@
#![allow(dead_code)]
use snafu::ensure;
use crate::markup_error::{CaretNotFoundSnafu, MarkResult};
#[derive(Debug, Copy, Clone)]
pub struct Caret {
pub offset_col: usize,
}
impl Caret {
pub fn new_attr(offset_col: usize) -> Attribute {
Attribute::Caret {
caret: Caret { offset_col },
}
}
}
#[derive(Debug)]
pub struct SelectionStart {
offset_col: usize,
}
#[derive(Debug)]
pub struct SelectionEnd {
offset_col: usize,
}
// Highlight is used for example when searching for a specific string to highlight all search results in the module
#[derive(Debug)]
pub struct HighlightStart {
offset_col: usize,
}
#[derive(Debug)]
pub struct HighlightEnd {
offset_col: usize,
}
// Underline is used for warnings and errors
#[derive(Debug)]
pub struct UnderlineStart {
offset_col: usize,
}
#[derive(Debug)]
pub struct UnderlineEnd {
offset_col: usize,
}
#[derive(Debug)]
pub enum Attribute {
// Rust does not yet support types for enum variants so we have to do it like this
Caret { caret: Caret },
SelectionStart { selection_start: SelectionStart },
SelectionEnd { selection_end: SelectionEnd },
HighlightStart { highlight_start: HighlightStart },
HighlightEnd { highlight_end: HighlightEnd },
Underline { underline_spec: UnderlineSpec },
}
#[derive(Debug)]
pub enum UnderlineSpec {
Partial { start: usize, end: usize },
Full,
}
#[derive(Debug, Default)]
pub struct Attributes {
pub all: Vec<Attribute>,
}
impl Attributes {
pub fn add(&mut self, attr: Attribute) {
self.all.push(attr);
}
pub fn add_caret(&mut self, offset_col: usize) {
self.all.push(Attribute::Caret {
caret: Caret { offset_col },
});
}
pub fn get_mut_carets(&mut self) -> Vec<&mut Caret> {
let mut carets = Vec::new();
for attr in self.all.iter_mut() {
if let Attribute::Caret { caret } = attr {
carets.push(caret)
}
}
carets
}
pub fn get_carets(&self) -> Vec<Caret> {
let mut carets = Vec::new();
for attr in self.all.iter() {
if let Attribute::Caret { caret } = attr {
carets.push(*caret)
}
}
carets
}
pub fn delete_caret(&mut self, offset_col: usize, node_id: usize) -> MarkResult<()> {
let old_len = self.all.len();
self.all.retain(|attr| {
if let Attribute::Caret { caret } = attr {
caret.offset_col != offset_col
} else {
true
}
});
let new_len = self.all.len();
ensure!(old_len != new_len, CaretNotFoundSnafu { node_id });
Ok(())
}
}

View file

@ -0,0 +1,167 @@
use crate::{
slow_pool::{MarkNodeId, SlowPool},
syntax_highlight::HighlightStyle,
};
use super::{
attribute::Attributes,
nodes::MarkupNode,
nodes::{self, make_nested_mn},
};
pub fn new_equals_mn() -> MarkupNode {
common_text_node(nodes::EQUALS.to_owned(), HighlightStyle::Operator, 0)
}
pub fn new_comma_mn() -> MarkupNode {
common_text_node(nodes::COMMA.to_owned(), HighlightStyle::Operator, 0)
}
pub fn new_dot_mn() -> MarkupNode {
common_text_node(nodes::DOT.to_owned(), HighlightStyle::Operator, 0)
}
pub fn new_blank_mn() -> MarkupNode {
MarkupNode::Blank {
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
}
}
pub fn new_blank_mn_w_nls(nr_of_newlines: usize) -> MarkupNode {
MarkupNode::Blank {
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: nr_of_newlines,
}
}
pub fn new_colon_mn() -> MarkupNode {
new_operator_mn(nodes::COLON.to_owned())
}
pub fn new_operator_mn(content: String) -> MarkupNode {
common_text_node(content, HighlightStyle::Operator, 0)
}
pub fn new_left_accolade_mn() -> MarkupNode {
common_text_node(nodes::LEFT_ACCOLADE.to_owned(), HighlightStyle::Bracket, 0)
}
pub fn new_right_accolade_mn() -> MarkupNode {
common_text_node(nodes::RIGHT_ACCOLADE.to_owned(), HighlightStyle::Bracket, 0)
}
pub fn new_left_square_mn() -> MarkupNode {
common_text_node(nodes::LEFT_SQUARE_BR.to_owned(), HighlightStyle::Bracket, 0)
}
pub fn new_right_square_mn() -> MarkupNode {
common_text_node(
nodes::RIGHT_SQUARE_BR.to_owned(),
HighlightStyle::Bracket,
0,
)
}
pub fn new_func_name_mn(content: String) -> MarkupNode {
common_text_node(content, HighlightStyle::FunctionName, 0)
}
pub fn new_arg_name_mn(content: String) -> MarkupNode {
common_text_node(content, HighlightStyle::FunctionArgName, 0)
}
pub fn new_arrow_mn(newlines_at_end: usize) -> MarkupNode {
common_text_node(
nodes::ARROW.to_owned(),
HighlightStyle::Operator,
newlines_at_end,
)
}
pub fn new_comments_mn(comment: String, newlines_at_end: usize) -> MarkupNode {
common_text_node(comment, HighlightStyle::Comment, newlines_at_end)
}
fn common_text_node(
content: String,
highlight_style: HighlightStyle,
newlines_at_end: usize,
) -> MarkupNode {
MarkupNode::Text {
content,
syn_high_style: highlight_style,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end,
}
}
pub const NEW_LINES_AFTER_DEF: usize = 2;
pub fn new_assign_mn(
val_name_mn_id: MarkNodeId,
equals_mn_id: MarkNodeId,
expr_mark_node_id: MarkNodeId,
) -> MarkupNode {
make_nested_mn(
vec![val_name_mn_id, equals_mn_id, expr_mark_node_id],
NEW_LINES_AFTER_DEF,
)
}
pub fn new_module_name_mn_id(mn_ids: Vec<MarkNodeId>, mark_node_pool: &mut SlowPool) -> MarkNodeId {
if mn_ids.len() == 1 {
*mn_ids.get(0).unwrap() // safe because we checked the length before
} else {
let nested_node = make_nested_mn(mn_ids, 0);
mark_node_pool.add(nested_node)
}
}
pub fn new_module_var_mn(
module_name_id: MarkNodeId,
dot_id: MarkNodeId,
ident_id: MarkNodeId,
) -> MarkupNode {
make_nested_mn(vec![module_name_id, dot_id, ident_id], 0)
}
pub fn if_mn() -> MarkupNode {
keyword_mn("if ")
}
pub fn then_mn() -> MarkupNode {
keyword_mn(" then ")
}
pub fn else_mn() -> MarkupNode {
keyword_mn(" else ")
}
fn keyword_mn(keyword: &str) -> MarkupNode {
common_text_node(keyword.to_owned(), HighlightStyle::Keyword, 0)
}
pub fn new_if_expr_mn(
if_mn_id: MarkNodeId,
cond_expr_mn_id: MarkNodeId,
then_mn_id: MarkNodeId,
then_expr_mn_id: MarkNodeId,
else_mn_id: MarkNodeId,
else_expr_mn_id: MarkNodeId,
) -> MarkupNode {
make_nested_mn(
vec![
if_mn_id,
cond_expr_mn_id,
then_mn_id,
then_expr_mn_id,
else_mn_id,
else_expr_mn_id,
],
1,
)
}

View file

@ -0,0 +1,50 @@
use roc_ast::{
ast_error::ASTResult,
lang::{core::ast::AST, env::Env},
};
use roc_module::symbol::Interns;
use crate::{
markup::{
convert::{from_def2::def2_to_markup, from_header::header_to_markup},
mark_id_ast_id_map::MarkIdAstIdMap,
nodes::set_parent_for_all,
},
slow_pool::{MarkNodeId, SlowPool},
};
pub fn ast_to_mark_nodes<'a>(
env: &mut Env<'a>,
ast: &AST,
mark_node_pool: &mut SlowPool,
interns: &Interns,
) -> ASTResult<(Vec<MarkNodeId>, MarkIdAstIdMap)> {
let mut mark_id_ast_id_map = MarkIdAstIdMap::default();
let mut all_mark_node_ids = vec![header_to_markup(
&ast.header,
mark_node_pool,
&mut mark_id_ast_id_map,
)];
for &def_id in ast.def_ids.iter() {
// for debugging
//println!("{}", def2_to_string(def_id, env.pool));
let def2 = env.pool.get(def_id);
let expr2_markup_id = def2_to_markup(
env,
def2,
def_id,
mark_node_pool,
&mut mark_id_ast_id_map,
interns,
)?;
set_parent_for_all(expr2_markup_id, mark_node_pool);
all_mark_node_ids.push(expr2_markup_id);
}
Ok((all_mark_node_ids, mark_id_ast_id_map))
}

View file

@ -0,0 +1,137 @@
use crate::{
markup::{
common_nodes::new_blank_mn_w_nls,
mark_id_ast_id_map::MarkIdAstIdMap,
nodes::MarkupNode,
top_level_def::{assignment_mark_node, tld_w_comments_mark_node},
},
slow_pool::{MarkNodeId, SlowPool},
};
use super::from_expr2::expr2_to_markup;
use roc_ast::{
ast_error::ASTResult,
lang::{
core::{
ast::ASTNodeId,
def::def2::{Def2, DefId},
},
env::Env,
},
};
use roc_module::symbol::Interns;
pub fn add_node(
mark_node: MarkupNode,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> MarkNodeId {
let mark_node_id = mark_node_pool.add(mark_node);
mark_id_ast_id_map.insert(mark_node_id, ast_node_id);
mark_node_id
}
pub fn def2_to_markup<'a>(
env: &mut Env<'a>,
def2: &Def2,
def2_node_id: DefId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
interns: &Interns,
) -> ASTResult<MarkNodeId> {
let ast_node_id = ASTNodeId::ADefId(def2_node_id);
let mark_node_id = match def2 {
Def2::ValueDef {
identifier_id,
expr_id,
} => {
let expr_mn_id = expr2_to_markup(
env,
env.pool.get(*expr_id),
*expr_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
0,
)?;
let tld_mn = assignment_mark_node(
*identifier_id,
expr_mn_id,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
env,
)?;
add_node(tld_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Def2::Blank => add_node(
new_blank_mn_w_nls(2),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
),
Def2::CommentsBefore { comments, def_id } => {
let inner_def = env.pool.get(*def_id);
let inner_def_mark_node_id = def2_to_markup(
env,
inner_def,
*def_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
)?;
let full_mark_node = tld_w_comments_mark_node(
comments.clone(),
inner_def_mark_node_id,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
true,
)?;
add_node(
full_mark_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)
}
Def2::CommentsAfter { def_id, comments } => {
let inner_def = env.pool.get(*def_id);
let inner_def_mark_node_id = def2_to_markup(
env,
inner_def,
*def_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
)?;
let full_mark_node = tld_w_comments_mark_node(
comments.clone(),
inner_def_mark_node_id,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
false,
)?;
add_node(
full_mark_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)
}
};
Ok(mark_node_id)
}

View file

@ -0,0 +1,497 @@
use crate::{
markup::{
attribute::Attributes,
common_nodes::{
new_arg_name_mn, new_arrow_mn, new_blank_mn, new_colon_mn, new_comma_mn, new_equals_mn,
new_left_accolade_mn, new_left_square_mn, new_operator_mn, new_right_accolade_mn,
new_right_square_mn,
},
mark_id_ast_id_map::MarkIdAstIdMap,
nodes::{
get_string, join_mark_nodes_commas, join_mark_nodes_spaces, new_markup_node, MarkupNode,
},
},
slow_pool::{MarkNodeId, SlowPool},
syntax_highlight::HighlightStyle,
};
use itertools::Itertools;
use roc_ast::{
ast_error::ASTResult,
lang::{
core::{
ast::ASTNodeId,
expr::{
expr2::{Expr2, ExprId},
record_field::RecordField,
},
pattern::{get_identifier_string, Pattern2},
val_def::ValueDef,
},
env::Env,
},
};
use roc_module::{module_err::ModuleResult, symbol::Interns};
use super::from_def2::add_node;
// make Markup Nodes: generate String representation, assign Highlighting Style
pub fn expr2_to_markup<'a>(
env: &Env<'a>,
expr2: &Expr2,
expr2_node_id: ExprId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
interns: &Interns,
indent_level: usize,
) -> ASTResult<MarkNodeId> {
let ast_node_id = ASTNodeId::AExprId(expr2_node_id);
// for debugging
//println!("EXPR2 {:?}", expr2);
let mark_node_id = match expr2 {
Expr2::SmallInt { text, .. }
| Expr2::I128 { text, .. }
| Expr2::U128 { text, .. }
| Expr2::Float { text, .. } => {
let num_str = get_string(env, text);
new_markup_node(
with_indent(indent_level, &num_str),
ast_node_id,
HighlightStyle::Number,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
)
}
Expr2::Str(text) => {
let content = format!("\"{}\"", text.as_str(env.pool));
string_mark_node(
&content,
indent_level,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)
}
Expr2::SmallStr(array_str) => {
let content = format!("\"{}\"", array_str.as_str());
string_mark_node(
&content,
indent_level,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)
}
Expr2::Tag { name, .. } => new_markup_node(
with_indent(indent_level, &get_string(env, name)),
ast_node_id,
HighlightStyle::Type,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
),
Expr2::Call { args, expr_id, .. } => {
let expr = env.pool.get(*expr_id);
let fun_call_mark_id = expr2_to_markup(
env,
expr,
*expr_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
indent_level,
)?;
let arg_expr_ids: Vec<ExprId> =
args.iter(env.pool).map(|(_, arg_id)| *arg_id).collect();
let arg_call_mark_ids: Vec<MarkNodeId> = arg_expr_ids
.iter()
.map(|arg_id| {
let arg_expr = env.pool.get(*arg_id);
expr2_to_markup(
env,
arg_expr,
*arg_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
0,
)
})
.collect::<ASTResult<Vec<MarkNodeId>>>()?;
let mut args_with_sapces =
join_mark_nodes_spaces(arg_call_mark_ids, true, mark_node_pool);
let mut children_ids = vec![fun_call_mark_id];
children_ids.append(&mut args_with_sapces);
let call_node = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(call_node, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Expr2::Var(symbol) => {
let text = symbol.fully_qualified(interns, env.home);
new_markup_node(
text.to_string(),
ast_node_id,
HighlightStyle::Value,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
)
}
Expr2::List { elems, .. } => {
let mut children_ids = vec![add_node(
new_left_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)];
let indexed_node_ids: Vec<(usize, ExprId)> =
elems.iter(env.pool).copied().enumerate().collect();
for (idx, node_id) in indexed_node_ids.iter() {
let sub_expr2 = env.pool.get(*node_id);
children_ids.push(expr2_to_markup(
env,
sub_expr2,
*node_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
indent_level,
)?);
if idx + 1 < elems.len() {
children_ids.push(add_node(
new_comma_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
));
}
}
children_ids.push(add_node(
new_right_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
));
let list_mn = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(list_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Expr2::EmptyRecord => {
let children_ids = vec![
add_node(
new_left_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
),
add_node(
new_right_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
),
];
let record_mn = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(record_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Expr2::Record { fields, .. } => {
let mut children_ids = vec![add_node(
new_left_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
)];
for (idx, field_node_id) in fields.iter_node_ids().enumerate() {
let record_field = env.pool.get(field_node_id);
let field_name = record_field.get_record_field_pool_str();
children_ids.push(new_markup_node(
field_name.as_str(env.pool).to_owned(),
ast_node_id,
HighlightStyle::RecordField,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
));
match record_field {
RecordField::InvalidLabelOnly(_, _) => (),
RecordField::LabelOnly(_, _, _) => (),
RecordField::LabeledValue(_, _, sub_expr2_node_id) => {
children_ids.push(add_node(
new_colon_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
));
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
children_ids.push(expr2_to_markup(
env,
sub_expr2,
*sub_expr2_node_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
indent_level,
)?);
}
}
if idx + 1 < fields.len() {
children_ids.push(add_node(
new_comma_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
));
}
}
children_ids.push(add_node(
new_right_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
));
let record_mn = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(record_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Expr2::Blank => add_node(
new_blank_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
),
Expr2::LetValue {
def_id,
body_id: _,
body_var: _,
} => {
let pattern_id = env.pool.get(*def_id).get_pattern_id();
let pattern2 = env.pool.get(pattern_id);
let val_name = get_identifier_string(pattern2, interns)?;
let val_name_mn = MarkupNode::Text {
content: val_name,
syn_high_style: HighlightStyle::Value,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
let val_name_mn_id =
add_node(val_name_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map);
let equals_mn_id = add_node(
new_equals_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let value_def = env.pool.get(*def_id);
match value_def {
ValueDef::NoAnnotation {
pattern_id: _,
expr_id,
expr_var: _,
} => {
let body_mn_id = expr2_to_markup(
env,
env.pool.get(*expr_id),
*expr_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
indent_level,
)?;
let body_mn = mark_node_pool.get_mut(body_mn_id);
body_mn.add_newline_at_end();
let full_let_mn = MarkupNode::Nested {
children_ids: vec![val_name_mn_id, equals_mn_id, body_mn_id],
parent_id_opt: None,
newlines_at_end: 1,
};
add_node(full_let_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
other => {
unimplemented!(
"I don't know how to convert {:?} into a MarkupNode yet.",
other
)
}
}
}
Expr2::Closure {
function_type: _,
uniq_symbol: _,
recursive: _,
args,
body_id,
extra: _,
} => {
let backslash_mn = new_operator_mn("\\".to_string());
let backslash_mn_id = add_node(
backslash_mn,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let arg_names: Vec<&str> = args
.iter(env.pool)
.map(|(_, arg_node_id)| {
let arg_pattern2 = env.pool.get(*arg_node_id);
match arg_pattern2 {
Pattern2::Identifier(id_symbol) => {
let ident_id = id_symbol.ident_id();
env.ident_ids.get_name_str_res(ident_id)
}
Pattern2::Shadowed { shadowed_ident } => {
Ok(shadowed_ident.as_str(env.pool))
}
other => {
todo!(
"TODO: support the following pattern2 as function arg: {:?}",
other
);
}
}
})
.collect::<ModuleResult<Vec<&str>>>()?;
let arg_mark_nodes = arg_names
.iter()
.map(|arg_name| new_arg_name_mn(arg_name.to_string()))
.collect_vec();
let args_with_commas: Vec<MarkupNode> = join_mark_nodes_commas(arg_mark_nodes);
let mut args_with_commas_ids: Vec<MarkNodeId> = args_with_commas
.into_iter()
.map(|mark_node| {
add_node(mark_node, ast_node_id, mark_node_pool, mark_id_ast_id_map)
})
.collect();
let arrow_mn = new_arrow_mn(1);
let arrow_mn_id = add_node(arrow_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map);
let mut children_ids = vec![backslash_mn_id];
children_ids.append(&mut args_with_commas_ids);
children_ids.push(arrow_mn_id);
let args_mn = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 0,
};
let args_mn_id = add_node(args_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map);
let body_expr = env.pool.get(*body_id);
let body_mn_id = expr2_to_markup(
env,
body_expr,
*body_id,
mark_node_pool,
mark_id_ast_id_map,
interns,
indent_level + 1,
)?;
let function_mn = MarkupNode::Nested {
children_ids: vec![args_mn_id, body_mn_id],
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(function_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
Expr2::RuntimeError() => new_markup_node(
"RunTimeError".to_string(),
ast_node_id,
HighlightStyle::Blank,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
),
rest => todo!("implement expr2_to_markup for {:?}", rest),
};
Ok(mark_node_id)
}
fn with_indent(indent_level: usize, some_str: &str) -> String {
let full_indent = std::iter::repeat(" ").take(indent_level * 4);
let mut full_string: String = full_indent.collect();
full_string.push_str(some_str);
full_string
}
fn string_mark_node(
content: &str,
indent_level: usize,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> MarkNodeId {
new_markup_node(
with_indent(indent_level, content),
ast_node_id,
HighlightStyle::String,
mark_node_pool,
mark_id_ast_id_map,
indent_level,
)
}

View file

@ -0,0 +1,305 @@
use roc_ast::lang::core::{ast::ASTNodeId, header::AppHeader};
use crate::{
markup::{
attribute::Attributes,
common_nodes::{
new_comma_mn, new_left_accolade_mn, new_left_square_mn, new_right_accolade_mn,
new_right_square_mn,
},
mark_id_ast_id_map::MarkIdAstIdMap,
nodes::{set_parent_for_all, MarkupNode},
},
slow_pool::{MarkNodeId, SlowPool},
syntax_highlight::HighlightStyle,
};
use super::from_def2::add_node;
pub fn header_to_markup(
app_header: &AppHeader,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> MarkNodeId {
let expr_id = app_header.ast_node_id;
let ast_node_id = ASTNodeId::AExprId(expr_id);
let app_node_id = header_mn(
"app ".to_owned(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let app_name_node_id = header_val_mn(
app_header.app_name.clone(),
ast_node_id,
HighlightStyle::String,
mark_node_pool,
mark_id_ast_id_map,
);
let full_app_node = MarkupNode::Nested {
children_ids: vec![app_node_id, app_name_node_id],
parent_id_opt: None,
newlines_at_end: 1,
};
let packages_node_id = header_mn(
" packages ".to_owned(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let pack_left_acc_node_id = add_node(
new_left_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let pack_base_node_id = header_val_mn(
"pf: ".to_owned(),
ast_node_id,
HighlightStyle::RecordField,
mark_node_pool,
mark_id_ast_id_map,
);
let pack_val_node_id = header_val_mn(
app_header.packages_base.clone(),
ast_node_id,
HighlightStyle::String,
mark_node_pool,
mark_id_ast_id_map,
);
let pack_right_acc_node_id = add_node(
new_right_accolade_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let full_packages_node = MarkupNode::Nested {
children_ids: vec![
packages_node_id,
pack_left_acc_node_id,
pack_base_node_id,
pack_val_node_id,
pack_right_acc_node_id,
],
parent_id_opt: None,
newlines_at_end: 1,
};
let imports_node_id = header_mn(
" imports ".to_owned(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let imports_left_square_node_id = add_node(
new_left_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let mut import_child_ids: Vec<MarkNodeId> = add_header_mn_list(
&app_header.imports,
ast_node_id,
HighlightStyle::Import,
mark_node_pool,
mark_id_ast_id_map,
);
let imports_right_square_node_id = add_node(
new_right_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let mut full_import_children = vec![imports_node_id, imports_left_square_node_id];
full_import_children.append(&mut import_child_ids);
full_import_children.push(imports_right_square_node_id);
let full_import_node = MarkupNode::Nested {
children_ids: full_import_children,
parent_id_opt: None,
newlines_at_end: 1,
};
let provides_node_id = header_mn(
" provides ".to_owned(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let provides_left_square_node_id = add_node(
new_left_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let mut provides_val_node_ids: Vec<MarkNodeId> = add_header_mn_list(
&app_header.provides,
ast_node_id,
HighlightStyle::Provides,
mark_node_pool,
mark_id_ast_id_map,
);
let provides_right_square_node_id = add_node(
new_right_square_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let provides_end_node_id = header_mn(
" to pf".to_owned(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let mut full_provides_children = vec![provides_node_id, provides_left_square_node_id];
full_provides_children.append(&mut provides_val_node_ids);
full_provides_children.push(provides_right_square_node_id);
full_provides_children.push(provides_end_node_id);
let full_provides_node = MarkupNode::Nested {
children_ids: full_provides_children,
parent_id_opt: None,
newlines_at_end: 1,
};
let full_app_node_id = add_node(
full_app_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let full_packages_node = add_node(
full_packages_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let full_import_node_id = add_node(
full_import_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let full_provides_node_id = add_node(
full_provides_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let header_mark_node = MarkupNode::Nested {
children_ids: vec![
full_app_node_id,
full_packages_node,
full_import_node_id,
full_provides_node_id,
],
parent_id_opt: None,
newlines_at_end: 1,
};
let header_mn_id = add_node(
header_mark_node,
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
set_parent_for_all(header_mn_id, mark_node_pool);
header_mn_id
}
// Used for provides and imports
fn add_header_mn_list(
str_vec: &[String],
ast_node_id: ASTNodeId,
highlight_style: HighlightStyle,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> Vec<MarkNodeId> {
let nr_of_elts = str_vec.len();
str_vec
.iter()
.enumerate()
.flat_map(|(indx, provide_str)| {
let provide_str = header_val_mn(
provide_str.to_owned(),
ast_node_id,
highlight_style,
mark_node_pool,
mark_id_ast_id_map,
);
if indx != nr_of_elts - 1 {
vec![
provide_str,
add_node(
new_comma_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
),
]
} else {
vec![provide_str]
}
})
.collect()
}
fn header_mn(
content: String,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> MarkNodeId {
let mark_node = MarkupNode::Text {
content,
syn_high_style: HighlightStyle::PackageRelated,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(mark_node, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}
fn header_val_mn(
content: String,
ast_node_id: ASTNodeId,
highlight_style: HighlightStyle,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
) -> MarkNodeId {
let mark_node = MarkupNode::Text {
content,
syn_high_style: highlight_style,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(mark_node, ast_node_id, mark_node_pool, mark_id_ast_id_map)
}

View file

@ -0,0 +1,4 @@
pub mod from_ast;
pub mod from_def2;
pub mod from_expr2;
pub mod from_header;

View file

@ -0,0 +1,29 @@
use std::collections::HashMap;
use roc_ast::lang::core::ast::ASTNodeId;
use crate::markup_error::MarkNodeIdWithoutCorrespondingASTNodeIdSnafu;
use crate::{markup_error::MarkResult, slow_pool::MarkNodeId};
/// A hashmap is wrapped to allow for an easy swap out with more performant alternatives
#[derive(Debug, Default)]
pub struct MarkIdAstIdMap {
map: HashMap<MarkNodeId, ASTNodeId>,
}
impl MarkIdAstIdMap {
pub fn insert(&mut self, mn_id: MarkNodeId, ast_id: ASTNodeId) {
self.map.insert(mn_id, ast_id);
}
pub fn get(&self, mn_id: MarkNodeId) -> MarkResult<ASTNodeId> {
match self.map.get(&mn_id) {
Some(ast_node_id) => Ok(*ast_node_id),
None => MarkNodeIdWithoutCorrespondingASTNodeIdSnafu {
node_id: mn_id,
keys_str: format!("{:?}", self.map.keys()),
}
.fail(),
}
}
}

View file

@ -0,0 +1,6 @@
pub mod attribute;
pub mod common_nodes;
pub mod convert;
pub mod mark_id_ast_id_map;
pub mod nodes;
pub mod top_level_def;

View file

@ -0,0 +1,494 @@
use crate::{
markup_error::MarkResult,
slow_pool::{MarkNodeId, SlowPool},
syntax_highlight::HighlightStyle,
};
use super::{
attribute::Attributes, common_nodes::new_comma_mn, convert::from_def2::add_node,
mark_id_ast_id_map::MarkIdAstIdMap,
};
use crate::markup_error::{
ExpectedTextNodeSnafu, NestedNodeMissingChildSnafu, NestedNodeRequiredSnafu,
};
use itertools::Itertools;
use roc_ast::{
lang::{core::ast::ASTNodeId, env::Env},
mem_pool::pool_str::PoolStr,
};
use roc_utils::{index_of, slice_get};
use std::fmt;
#[derive(Debug)]
pub enum MarkupNode {
Nested {
children_ids: Vec<MarkNodeId>,
parent_id_opt: Option<MarkNodeId>,
newlines_at_end: usize,
},
Text {
content: String,
syn_high_style: HighlightStyle,
attributes: Attributes,
parent_id_opt: Option<MarkNodeId>,
newlines_at_end: usize,
},
Blank {
attributes: Attributes,
parent_id_opt: Option<MarkNodeId>,
newlines_at_end: usize,
},
Indent {
indent_level: usize,
parent_id_opt: Option<MarkNodeId>,
},
}
impl MarkupNode {
pub fn get_parent_id_opt(&self) -> Option<MarkNodeId> {
match self {
MarkupNode::Nested { parent_id_opt, .. } => *parent_id_opt,
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt,
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt,
MarkupNode::Indent { parent_id_opt, .. } => *parent_id_opt,
}
}
pub fn get_children_ids(&self) -> Vec<MarkNodeId> {
match self {
MarkupNode::Nested { children_ids, .. } => children_ids.to_vec(),
MarkupNode::Text { .. } => vec![],
MarkupNode::Blank { .. } => vec![],
MarkupNode::Indent { .. } => vec![],
}
}
pub fn get_sibling_ids(&self, mark_node_pool: &SlowPool) -> Vec<MarkNodeId> {
if let Some(parent_id) = self.get_parent_id_opt() {
let parent_node = mark_node_pool.get(parent_id);
parent_node.get_children_ids()
} else {
vec![]
}
}
// return (index of child in list of children, closest ast index of child corresponding to ast node)
pub fn get_child_indices(
&self,
mark_node_id: MarkNodeId,
ast_node_id: ASTNodeId,
mark_id_ast_id_map: &MarkIdAstIdMap,
) -> MarkResult<(usize, usize)> {
match self {
MarkupNode::Nested { children_ids, .. } => {
let mut mark_child_index_opt: Option<usize> = None;
let mut child_ids_with_ast: Vec<MarkNodeId> = Vec::new();
for (indx, &mark_child_id) in children_ids.iter().enumerate() {
if mark_child_id == mark_node_id {
mark_child_index_opt = Some(indx);
}
let child_ast_node_id = mark_id_ast_id_map.get(mark_child_id)?;
// a node that points to the same ast_node as the parent is a ',', '[', ']'
// those are not "real" ast children
if child_ast_node_id != ast_node_id {
child_ids_with_ast.push(mark_child_id)
}
}
if let Some(child_index) = mark_child_index_opt {
if child_index == (children_ids.len() - 1) {
let ast_child_index = child_ids_with_ast.len();
Ok((child_index, ast_child_index))
} else {
// we want to find the index of the closest ast mark node to child_index
let mut indices_in_mark = vec![];
for &c_id in child_ids_with_ast.iter() {
indices_in_mark.push(index_of(c_id, children_ids)?);
}
let mut last_diff = usize::MAX;
let mut best_index = 0;
for index in indices_in_mark.iter() {
let curr_diff =
isize::abs((*index as isize) - (child_index as isize)) as usize;
if curr_diff >= last_diff {
break;
} else {
last_diff = curr_diff;
best_index = *index;
}
}
let closest_ast_child = slice_get(best_index, children_ids)?;
let closest_ast_child_index =
index_of(*closest_ast_child, &child_ids_with_ast)?;
// +1 because we want to insert after ast_child
Ok((child_index, closest_ast_child_index + 1))
}
} else {
NestedNodeMissingChildSnafu {
node_id: mark_node_id,
children_ids: children_ids.clone(),
}
.fail()
}
}
_ => NestedNodeRequiredSnafu {
node_type: self.node_type_as_string(),
}
.fail(),
}
}
pub fn get_content(&self) -> String {
match self {
MarkupNode::Nested { .. } => "".to_owned(),
MarkupNode::Text { content, .. } => content.clone(),
MarkupNode::Blank { .. } => BLANK_PLACEHOLDER.to_owned(),
MarkupNode::Indent { indent_level, .. } => SINGLE_INDENT.repeat(*indent_level),
}
}
// gets content and adds newline from newline_at_end
pub fn get_full_content(&self) -> String {
let mut full_content = self.get_content();
for _ in 0..self.get_newlines_at_end() {
full_content.push('\n')
}
full_content
}
pub fn get_content_mut(&mut self) -> MarkResult<&mut String> {
match self {
MarkupNode::Text { content, .. } => Ok(content),
_ => ExpectedTextNodeSnafu {
function_name: "set_content".to_owned(),
node_type: self.node_type_as_string(),
}
.fail(),
}
}
pub fn is_all_alphanumeric(&self) -> bool {
self.get_content()
.chars()
.all(|chr| chr.is_ascii_alphanumeric())
}
pub fn add_child_at_index(&mut self, index: usize, child_id: MarkNodeId) -> MarkResult<()> {
if let MarkupNode::Nested { children_ids, .. } = self {
children_ids.splice(index..index, vec![child_id]);
} else {
NestedNodeRequiredSnafu {
node_type: self.node_type_as_string(),
}
.fail()?;
}
Ok(())
}
pub fn node_type_as_string(&self) -> String {
let type_str = match self {
MarkupNode::Nested { .. } => "Nested",
MarkupNode::Text { .. } => "Text",
MarkupNode::Blank { .. } => "Blank",
MarkupNode::Indent { .. } => "Indent",
};
type_str.to_owned()
}
pub fn is_blank(&self) -> bool {
matches!(self, MarkupNode::Blank { .. })
}
pub fn is_nested(&self) -> bool {
matches!(self, MarkupNode::Nested { .. })
}
pub fn get_newlines_at_end(&self) -> usize {
match self {
MarkupNode::Nested {
newlines_at_end, ..
} => *newlines_at_end,
MarkupNode::Text {
newlines_at_end, ..
} => *newlines_at_end,
MarkupNode::Blank {
newlines_at_end, ..
} => *newlines_at_end,
MarkupNode::Indent { .. } => 0,
}
}
pub fn add_newline_at_end(&mut self) {
match self {
MarkupNode::Nested {
newlines_at_end, ..
} => *newlines_at_end += 1,
MarkupNode::Text {
newlines_at_end, ..
} => *newlines_at_end += 1,
MarkupNode::Blank {
newlines_at_end, ..
} => *newlines_at_end += 1,
_ => {}
}
}
}
pub fn make_nested_mn(children_ids: Vec<MarkNodeId>, newlines_at_end: usize) -> MarkupNode {
MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end,
}
}
pub fn get_string<'a>(env: &Env<'a>, pool_str: &PoolStr) -> String {
pool_str.as_str(env.pool).to_owned()
}
pub const BLANK_PLACEHOLDER: &str = " ";
pub const LEFT_ACCOLADE: &str = "{ ";
pub const RIGHT_ACCOLADE: &str = " }";
pub const LEFT_SQUARE_BR: &str = "[ ";
pub const RIGHT_SQUARE_BR: &str = " ]";
pub const COLON: &str = ": ";
pub const COMMA: &str = ", ";
pub const DOT: &str = ".";
pub const STRING_QUOTES: &str = "\"\"";
pub const EQUALS: &str = " = ";
pub const ARROW: &str = " -> ";
pub const SINGLE_INDENT: &str = " "; // 4 spaces
pub fn new_markup_node(
text: String,
node_id: ASTNodeId,
highlight_style: HighlightStyle,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
indent_level: usize,
) -> MarkNodeId {
let content_node = MarkupNode::Text {
content: text,
syn_high_style: highlight_style,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
let content_node_id = add_node(content_node, node_id, mark_node_pool, mark_id_ast_id_map);
if indent_level > 0 {
let indent_node = MarkupNode::Indent {
indent_level,
parent_id_opt: None,
};
let indent_node_id = add_node(indent_node, node_id, mark_node_pool, mark_id_ast_id_map);
let nested_node = MarkupNode::Nested {
children_ids: vec![indent_node_id, content_node_id],
parent_id_opt: None,
newlines_at_end: 0,
};
add_node(nested_node, node_id, mark_node_pool, mark_id_ast_id_map)
} else {
content_node_id
}
}
pub fn set_parent_for_all(markup_node_id: MarkNodeId, mark_node_pool: &mut SlowPool) {
let node = mark_node_pool.get(markup_node_id);
if let MarkupNode::Nested {
children_ids,
parent_id_opt: _,
newlines_at_end: _,
} = node
{
// need to clone because of borrowing issues
let children_ids_clone = children_ids.clone();
for child_id in children_ids_clone {
set_parent_for_all_helper(child_id, markup_node_id, mark_node_pool);
}
}
}
pub fn set_parent_for_all_helper(
markup_node_id: MarkNodeId,
parent_node_id: MarkNodeId,
mark_node_pool: &mut SlowPool,
) {
let node = mark_node_pool.get_mut(markup_node_id);
match node {
MarkupNode::Nested {
children_ids,
parent_id_opt,
..
} => {
*parent_id_opt = Some(parent_node_id);
// need to clone because of borrowing issues
let children_ids_clone = children_ids.clone();
for child_id in children_ids_clone {
set_parent_for_all_helper(child_id, markup_node_id, mark_node_pool);
}
}
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
MarkupNode::Indent { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
}
}
impl fmt::Display for MarkupNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} ({}, {})",
self.node_type_as_string(),
self.get_content(),
self.get_newlines_at_end()
)
}
}
pub fn tree_as_string(root_node_id: MarkNodeId, mark_node_pool: &SlowPool) -> String {
let mut full_string = "\n(mark_node_tree)\n".to_owned();
let node = mark_node_pool.get(root_node_id);
full_string.push_str(&format!("{} mn_id {}\n", node, root_node_id));
tree_as_string_helper(node, 1, &mut full_string, mark_node_pool);
full_string
}
fn tree_as_string_helper(
node: &MarkupNode,
level: usize,
tree_string: &mut String,
mark_node_pool: &SlowPool,
) {
for child_id in node.get_children_ids() {
let mut full_str = std::iter::repeat("|--- ")
.take(level)
.collect::<Vec<&str>>()
.join("")
.to_owned();
let child = mark_node_pool.get(child_id);
let child_str = format!("{}", mark_node_pool.get(child_id)).replace('\n', "\\n");
full_str.push_str(&format!("{} mn_id {}\n", child_str, child_id));
tree_string.push_str(&full_str);
tree_as_string_helper(child, level + 1, tree_string, mark_node_pool);
}
}
// return to the the root parent_id of the current node
pub fn get_root_mark_node_id(mark_node_id: MarkNodeId, mark_node_pool: &SlowPool) -> MarkNodeId {
let mut curr_mark_node_id = mark_node_id;
let mut curr_parent_id_opt = mark_node_pool.get(curr_mark_node_id).get_parent_id_opt();
while let Some(curr_parent_id) = curr_parent_id_opt {
curr_mark_node_id = curr_parent_id;
curr_parent_id_opt = mark_node_pool.get(curr_mark_node_id).get_parent_id_opt();
}
curr_mark_node_id
}
// put space mark nodes between each node in mark_nodes
pub fn join_mark_nodes_spaces(
mark_nodes_ids: Vec<MarkNodeId>,
with_prepend: bool,
mark_node_pool: &mut SlowPool,
) -> Vec<MarkNodeId> {
let space_range_max = if with_prepend {
mark_nodes_ids.len()
} else {
mark_nodes_ids.len() - 1
};
let join_nodes: Vec<MarkNodeId> = (0..space_range_max)
.map(|_| {
let space_node = MarkupNode::Text {
content: " ".to_string(),
syn_high_style: HighlightStyle::Blank,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
mark_node_pool.add(space_node)
})
.collect();
if with_prepend {
join_nodes.into_iter().interleave(mark_nodes_ids).collect()
} else {
mark_nodes_ids.into_iter().interleave(join_nodes).collect()
}
}
// put comma mark nodes between each node in mark_nodes
pub fn join_mark_nodes_commas(mark_nodes: Vec<MarkupNode>) -> Vec<MarkupNode> {
let join_nodes: Vec<MarkupNode> = (0..(mark_nodes.len() - 1))
.map(|_| new_comma_mn())
.collect();
mark_nodes.into_iter().interleave(join_nodes).collect()
}
pub fn mark_nodes_to_string(markup_node_ids: &[MarkNodeId], mark_node_pool: &SlowPool) -> String {
let mut all_code_string = String::new();
for mark_node_id in markup_node_ids.iter() {
node_to_string_w_children(*mark_node_id, &mut all_code_string, mark_node_pool)
}
all_code_string
}
pub fn node_to_string_w_children(
node_id: MarkNodeId,
str_buffer: &mut String,
mark_node_pool: &SlowPool,
) {
let node = mark_node_pool.get(node_id);
if node.is_nested() {
for child_id in node.get_children_ids() {
node_to_string_w_children(child_id, str_buffer, mark_node_pool);
}
for _ in 0..node.get_newlines_at_end() {
str_buffer.push('\n')
}
} else {
let node_content_str = node.get_full_content();
str_buffer.push_str(&node_content_str);
}
}

View file

@ -0,0 +1,84 @@
use roc_ast::{
ast_error::ASTResult,
lang::{core::ast::ASTNodeId, env::Env},
};
use roc_module::symbol::IdentId;
use crate::{
markup::{
attribute::Attributes,
common_nodes::{new_comments_mn, new_equals_mn},
nodes::MarkupNode,
},
slow_pool::{MarkNodeId, SlowPool},
syntax_highlight::HighlightStyle,
};
use super::{
common_nodes::new_assign_mn, convert::from_def2::add_node, mark_id_ast_id_map::MarkIdAstIdMap,
};
// represents for example: `main = "Hello, World!"`
pub fn assignment_mark_node<'a>(
identifier_id: IdentId,
expr_mark_node_id: MarkNodeId,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
env: &Env<'a>,
) -> ASTResult<MarkupNode> {
let val_name = env.ident_ids.get_name_str_res(identifier_id)?;
let val_name_mn = MarkupNode::Text {
content: val_name.to_owned(),
syn_high_style: HighlightStyle::Value,
attributes: Attributes::default(),
parent_id_opt: None,
newlines_at_end: 0,
};
let val_name_mn_id = add_node(val_name_mn, ast_node_id, mark_node_pool, mark_id_ast_id_map);
let equals_mn_id = add_node(
new_equals_mn(),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
Ok(new_assign_mn(
val_name_mn_id,
equals_mn_id,
expr_mark_node_id,
))
}
pub fn tld_w_comments_mark_node(
comments: String,
def_mark_node_id: MarkNodeId,
ast_node_id: ASTNodeId,
mark_node_pool: &mut SlowPool,
mark_id_ast_id_map: &mut MarkIdAstIdMap,
comments_before: bool,
) -> ASTResult<MarkupNode> {
let comment_mn_id = add_node(
new_comments_mn(comments, 1),
ast_node_id,
mark_node_pool,
mark_id_ast_id_map,
);
let children_ids = if comments_before {
vec![comment_mn_id, def_mark_node_id]
} else {
vec![def_mark_node_id, comment_mn_id]
};
let tld_w_comment_node = MarkupNode::Nested {
children_ids,
parent_id_opt: None,
newlines_at_end: 2,
};
Ok(tld_w_comment_node)
}