mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FEATURE: Fix a number of bugs found by adding unit tests :-D
This commit is contained in:
parent
e86827f613
commit
d122fe6e6f
@ -87,18 +87,42 @@ where
|
|||||||
String::from_utf8_lossy(&indent).to_string()
|
String::from_utf8_lossy(&indent).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_bareword(s: &str) -> bool {
|
||||||
|
match s.chars().nth(0) {
|
||||||
|
Some(c) => {
|
||||||
|
if !(c.is_ascii_alphabetic() || c == '_') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
for c in s.chars() {
|
||||||
|
if !c.is_ascii_alphanumeric() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
fn render_list_def(&mut self, def: &ListDef) -> std::io::Result<()> {
|
fn render_list_def(&mut self, def: &ListDef) -> std::io::Result<()> {
|
||||||
write!(self.w, "[\n")?;
|
write!(self.w, "[")?;
|
||||||
self.curr_indent += self.indent;
|
self.curr_indent += self.indent;
|
||||||
// If the element list is just 1 we might be able to collapse the tuple.
|
// If the element list is just 1 we might be able to collapse the tuple.
|
||||||
let indent = self.make_indent();
|
let indent = self.make_indent();
|
||||||
|
let has_fields = def.elems.len() > 0;
|
||||||
|
if has_fields {
|
||||||
|
write!(self.w, "\n")?;
|
||||||
|
}
|
||||||
for e in def.elems.iter() {
|
for e in def.elems.iter() {
|
||||||
// TODO(jwall): Now print out the elements
|
// TODO(jwall): Now print out the elements
|
||||||
write!(self.w, "{}", indent)?;
|
write!(self.w, "{}", indent)?;
|
||||||
self.render_expr(e)?;
|
self.render_expr(e)?;
|
||||||
write!(self.w, "\n")?;
|
write!(self.w, ",\n")?;
|
||||||
}
|
}
|
||||||
self.curr_indent -= self.indent;
|
self.curr_indent -= self.indent;
|
||||||
|
if has_fields {
|
||||||
|
write!(self.w, "{}", self.make_indent())?;
|
||||||
|
}
|
||||||
self.w.write(&[']' as u8])?;
|
self.w.write(&[']' as u8])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -108,14 +132,25 @@ where
|
|||||||
// If the field list is just 1 we might be able to collapse the tuple.
|
// If the field list is just 1 we might be able to collapse the tuple.
|
||||||
self.curr_indent += self.indent;
|
self.curr_indent += self.indent;
|
||||||
let indent = self.make_indent();
|
let indent = self.make_indent();
|
||||||
|
let has_fields = def.len() > 0;
|
||||||
|
if has_fields {
|
||||||
|
write!(self.w, "\n")?;
|
||||||
|
}
|
||||||
for &(ref t, ref expr) in def.iter() {
|
for &(ref t, ref expr) in def.iter() {
|
||||||
write!(self.w, "{}", indent)?;
|
write!(self.w, "{}", indent)?;
|
||||||
// TODO(jwall): Detect if there are strings and render as a quoted string.
|
if Self::is_bareword(&t.fragment) {
|
||||||
write!(&mut self.w, "{} = ", t.fragment)?;
|
write!(&mut self.w, "{} = ", t.fragment)?;
|
||||||
|
} else {
|
||||||
|
write!(self.w, "\"{}\" = ", Self::escape_quotes(&t.fragment))?;
|
||||||
|
}
|
||||||
self.render_expr(expr)?;
|
self.render_expr(expr)?;
|
||||||
write!(&mut self.w, ",")?;
|
write!(&mut self.w, ",")?;
|
||||||
write!(self.w, "\n")?;
|
write!(self.w, "\n")?;
|
||||||
}
|
}
|
||||||
|
self.curr_indent -= self.indent;
|
||||||
|
if has_fields {
|
||||||
|
write!(self.w, "{}", self.make_indent())?;
|
||||||
|
}
|
||||||
self.w.write(&['}' as u8])?;
|
self.w.write(&['}' as u8])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -352,7 +387,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, stmts: Vec<&mut Statement>) {
|
pub fn render(&mut self, stmts: &Vec<Statement>) {
|
||||||
for v in stmts {
|
for v in stmts {
|
||||||
if let Err(e) = self.render_stmt(v) {
|
if let Err(e) = self.render_stmt(v) {
|
||||||
self.err = Some(e);
|
self.err = Some(e);
|
||||||
@ -361,3 +396,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
167
src/ast/printer/test.rs
Normal file
167
src/ast/printer/test.rs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// Copyright 2019 Jeremy Wall
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use crate::ast::printer::*;
|
||||||
|
use crate::iter::OffsetStrIter;
|
||||||
|
use crate::parse::*;
|
||||||
|
|
||||||
|
fn assert_parse(input: &str) -> Vec<Statement> {
|
||||||
|
parse(OffsetStrIter::new(input)).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_value_printing() {
|
||||||
|
let input = "1;";
|
||||||
|
let stmts = assert_parse("1;");
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(0, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_quoted_printing() {
|
||||||
|
let input = "\"foo\";";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(0, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_escaped_quoted_printing() {
|
||||||
|
let input = "\"f\\\\o\\\"o\";";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(0, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_tuple_printing() {
|
||||||
|
let input = "{};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_list_printing() {
|
||||||
|
let input = "[];";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_non_empty_tuple_printing() {
|
||||||
|
let input = "{\n foo = 1,\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_empty_tuple_printing() {
|
||||||
|
let input = "{\n foo = {},\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_nested_empty_tuple_printing() {
|
||||||
|
let input = "[\n {},\n];";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_non_empty_tuple_printing() {
|
||||||
|
let input = "{\n foo = {\n bar = 1,\n },\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_non_empty_list_printing() {
|
||||||
|
let input = "[\n [\n 1,\n ],\n];";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_quoted_field_tuple_printing() {
|
||||||
|
let input = "{\n \"foo\" = {\n bar = 1,\n },\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
String::from_utf8(buffer).unwrap(),
|
||||||
|
format!("{}\n", "{\n foo = {\n bar = 1,\n },\n};")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_special_quoted_field_tuple_printing() {
|
||||||
|
let input = "{\n \"foo bar\" = {\n bar = 1,\n },\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_let_statement_printing() {
|
||||||
|
let input = "let tpl = {\n \"foo bar\" = {\n bar = 1,\n },\n};";
|
||||||
|
let stmts = assert_parse(input);
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let mut printer = AstPrinter::new(2, &mut buffer);
|
||||||
|
printer.render(&stmts);
|
||||||
|
assert!(printer.err.is_none());
|
||||||
|
assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user