Skip to content

Commit

Permalink
Merge pull request #156 from stasm/fix-special-chars-infront
Browse files Browse the repository at this point in the history
(fluent.syntax) Don't drop to newline when serializing patterns starting with special chars
  • Loading branch information
stasm authored Aug 27, 2020
2 parents aa7d65e + 2774242 commit b41a014
Showing 4 changed files with 147 additions and 12 deletions.
33 changes: 22 additions & 11 deletions fluent.syntax/fluent/syntax/serializer.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from . import ast


def indent(content):
def indent_except_first_line(content):
return " ".join(
content.splitlines(True)
)
@@ -18,6 +18,20 @@ def is_select_expr(elem):
isinstance(elem.expression, ast.SelectExpression))


def should_start_on_new_line(pattern):
is_multiline = any(is_select_expr(elem) for elem in pattern.elements) \
or any(includes_new_line(elem) for elem in pattern.elements)

if is_multiline:
first_element = pattern.elements[0]
if isinstance(first_element, ast.TextElement):
first_char = first_element.value[0]
if first_char in ("[", ".", "*"):
return False
return True
return False


class FluentSerializer(object):
"""FluentSerializer converts :class:`.ast.SyntaxNode` objects to unicode strings.
@@ -119,19 +133,16 @@ def serialize_term(term):
def serialize_attribute(attribute):
return "\n .{} ={}".format(
attribute.id.name,
indent(serialize_pattern(attribute.value))
indent_except_first_line(serialize_pattern(attribute.value))
)


def serialize_pattern(pattern):
content = "".join([
serialize_element(elem)
for elem in pattern.elements])
start_on_new_line = any(
includes_new_line(elem) or is_select_expr(elem)
for elem in pattern.elements)
if start_on_new_line:
return '\n {}'.format(indent(content))
content = "".join(serialize_element(elem) for elem in pattern.elements)
content = indent_except_first_line(content)

if should_start_on_new_line(pattern):
return '\n {}'.format(content)

return ' {}'.format(content)

@@ -193,7 +204,7 @@ def serialize_variant(variant):
return "\n{}[{}]{}".format(
" *" if variant.default else " ",
serialize_variant_key(variant.key),
indent(serialize_pattern(variant.value))
indent_except_first_line(serialize_pattern(variant.value))
)


14 changes: 14 additions & 0 deletions fluent.syntax/tests/syntax/fixtures_reference/special_chars.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## OK

bracket-inline = [Value]
dot-inline = .Value
star-inline = *Value
## ERRORS

bracket-newline =
[Value]
dot-newline =
.Value
star-newline =
*Value
82 changes: 82 additions & 0 deletions fluent.syntax/tests/syntax/fixtures_reference/special_chars.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"type": "Resource",
"body": [
{
"type": "GroupComment",
"content": "OK"
},
{
"type": "Message",
"id": {
"type": "Identifier",
"name": "bracket-inline"
},
"value": {
"type": "Pattern",
"elements": [
{
"type": "TextElement",
"value": "[Value]"
}
]
},
"attributes": [],
"comment": null
},
{
"type": "Message",
"id": {
"type": "Identifier",
"name": "dot-inline"
},
"value": {
"type": "Pattern",
"elements": [
{
"type": "TextElement",
"value": ".Value"
}
]
},
"attributes": [],
"comment": null
},
{
"type": "Message",
"id": {
"type": "Identifier",
"name": "star-inline"
},
"value": {
"type": "Pattern",
"elements": [
{
"type": "TextElement",
"value": "*Value"
}
]
},
"attributes": [],
"comment": null
},
{
"type": "GroupComment",
"content": "ERRORS"
},
{
"type": "Junk",
"annotations": [],
"content": "bracket-newline =\n [Value]\n"
},
{
"type": "Junk",
"annotations": [],
"content": "dot-newline =\n .Value\n"
},
{
"type": "Junk",
"annotations": [],
"content": "star-newline =\n *Value\n"
}
]
}
30 changes: 29 additions & 1 deletion fluent.syntax/tests/syntax/test_serializer.py
Original file line number Diff line number Diff line change
@@ -139,12 +139,31 @@ def test_comment_standalone(self):
input = """\
foo = Foo
# A multiline
# A standalone comment
bar = Bar
"""
self.assertEqual(self.pretty_ftl(input), dedent_ftl(input))

def test_multiline_starting_inline(self):
input = """\
foo = Foo
Bar
"""
output = """\
foo =
Foo
Bar
"""
self.assertEqual(self.pretty_ftl(input), dedent_ftl(output))

def test_multiline_starting_inline_with_special_char(self):
input = """\
foo = *Foo
Bar
"""
self.assertEqual(self.pretty_ftl(input), dedent_ftl(input))

def test_multiline_with_placeable(self):
input = """\
foo =
@@ -269,6 +288,15 @@ def test_select_expression_in_inline_value(self):
"""
self.assertEqual(self.pretty_ftl(input), dedent_ftl(output))

def test_select_expression_in_inline_value_starting_with_special_char(self):
input = """\
foo = .Foo { $sel ->
*[a] A
[b] B
}
"""
self.assertEqual(self.pretty_ftl(input), dedent_ftl(input))

def test_select_expression_in_multi_multiline(self):
input = """\
foo =

0 comments on commit b41a014

Please sign in to comment.