1+ from collections import defaultdict
12from typing import Tuple , Any , List , Union , Optional
23
34from lark .tree import Meta
78from hcl2 .rule_transformer .rules .token_sequence import IdentifierRule
89
910from hcl2 .rule_transformer .rules .whitespace import NewLineOrCommentRule
11+ from hcl2 .rule_transformer .utils import SerializationOptions
1012
1113
1214class AttributeRule (LarkRule ):
@@ -28,8 +30,8 @@ def identifier(self) -> IdentifierRule:
2830 def expression (self ) -> Expression :
2931 return self ._children [2 ]
3032
31- def serialize (self ) -> Any :
32- return {self .identifier .serialize (): self .expression .serialize ()}
33+ def serialize (self , options : SerializationOptions = SerializationOptions () ) -> Any :
34+ return {self .identifier .serialize (options ): self .expression .serialize (options )}
3335
3436
3537class BodyRule (LarkRule ):
@@ -46,34 +48,51 @@ class BodyRule(LarkRule):
4648 def rule_name () -> str :
4749 return "body"
4850
49- def serialize (self ) -> Any :
51+ def serialize (self , options : SerializationOptions = SerializationOptions () ) -> Any :
5052 blocks : List [BlockRule ] = []
5153 attributes : List [AttributeRule ] = []
5254 comments = []
53-
55+ inline_comments = []
5456 for child in self ._children :
57+
5558 if isinstance (child , BlockRule ):
5659 blocks .append (child )
60+
5761 if isinstance (child , AttributeRule ):
5862 attributes .append (child )
63+ # collect in-line comments from attribute assignments, expressions etc
64+ inline_comments .extend (child .expression .inline_comments ())
65+
5966 if isinstance (child , NewLineOrCommentRule ):
60- child_comments = child .actual_comments ()
67+ child_comments = child .to_list ()
6168 if child_comments :
6269 comments .extend (child_comments )
6370
6471 result = {}
6572
6673 for attribute in attributes :
6774 result .update (
68- {attribute .identifier .serialize (): attribute .expression .serialize ()}
75+ {
76+ attribute .identifier .serialize (
77+ options
78+ ): attribute .expression .serialize (options )
79+ }
6980 )
7081
71- result .update (
72- {block .labels [0 ].serialize (): block .serialize () for block in blocks }
73- )
82+ result_blocks = defaultdict (list )
83+ for block in blocks :
84+ name = block .labels [0 ].serialize (options )
85+ if name in result .keys ():
86+ raise RuntimeError (f"Attribute { name } is already defined." )
87+ result_blocks [name ].append (block .serialize (options ))
88+
89+ result .update (** result_blocks )
7490
75- if comments :
76- result ["__comments__" ] = comments
91+ if options .with_comments :
92+ if comments :
93+ result ["__comments__" ] = comments
94+ if inline_comments :
95+ result ["__inline_comments__" ] = inline_comments
7796
7897 return result
7998
@@ -90,8 +109,8 @@ def rule_name() -> str:
90109 def body (self ) -> BodyRule :
91110 return self ._children [0 ]
92111
93- def serialize (self ) -> Any :
94- return self .body .serialize ()
112+ def serialize (self , options : SerializationOptions = SerializationOptions () ) -> Any :
113+ return self .body .serialize (options )
95114
96115
97116class BlockRule (LarkRule ):
@@ -103,7 +122,7 @@ def rule_name() -> str:
103122 return "block"
104123
105124 def __init__ (self , children , meta : Optional [Meta ] = None ):
106- super ().__init__ (children )
125+ super ().__init__ (children , meta )
107126 * self ._labels , self ._body = children
108127
109128 @property
@@ -114,9 +133,11 @@ def labels(self) -> List[IdentifierRule]:
114133 def body (self ) -> BodyRule :
115134 return self ._body
116135
117- def serialize (self ) -> BodyRule :
118- result = self ._body .serialize ()
136+ def serialize (
137+ self , options : SerializationOptions = SerializationOptions ()
138+ ) -> BodyRule :
139+ result = self ._body .serialize (options )
119140 labels = self ._labels
120141 for label in reversed (labels [1 :]):
121- result = {label .serialize (): result }
142+ result = {label .serialize (options ): result }
122143 return result
0 commit comments