Fixes an issue where the name range may be incorrect in case there are
multiple attributes and one of them is wrong. Another attribute's name
range could overwrite the previous one as the attr variable is
overwritten in the for loop.
When marshalling, the current file index was not stored. Because of
this, a ';' was inserted multiple times for each file, even if the file
did not change.
When unmarshalling, the fileIdx determined by number of ';' was ignored.
Thus, if there were more than one file, all the positions would still
point to the first file.
Fixes setting the MissingItemRange on the remaining body when a
*hclpack.Body is partially decoded. Otherwise when the remaining body is
decoded with missing fields, the diagnostic cannot point to where they
should be set.
Fixes an issue where a nested block would be decoded incorrectly, the
body of the last decoded block overwrites the previously decoded ones.
This was caused by the block being assigned on the stack in the for
loop; when the block is converted to a *hcl.Block, the pointer to Body
will always point to the same block. This caused decoding a new block to
overwrite the bodies of any previously decoded blocks.
This allows us to round-trip Body to JSON and back without any loss as
long as the expression source codes are always valid UTF-8, and we require
that during expression parsing anyway so that is a fine restriction.
The JSON encoding is a little noisy to read due to the extra annotations
required to be lossless (including source ranges) but still relatively
compact due to the base64-VLQ encoding of the source location information.
This allows the static analysis functions in the main HCL package to dig
through our wrapper to get the native expression object needed for most
analyses.
For example, this allows an expression with a native expression source
type whose source contains valid tuple constructor syntax to be used with
hcl.ExprList.
hclpack can potentially be used as an intermediary to more easily bring
non-HCL input into the HCL API, and so allowing a literal value in JSON
format as an expression type means that such a transcoder doesn't need to
worry about formatting values it encounters using HCL syntax and can
instead just encode directly to JSON, but at the expense of then not being
able to use the full expression/template syntax.
This is a straightforward way to get a hclpack.Body in the common case
where the input is already native syntax source code. Since the native
syntax is unambiguous about structure, the whole structure can be packed
in a single pass with no further information.
In most applications it's possible to fully evaluate configuration at the
beginning and work only with resolved values after that, but in some
unusual cases it's necessary to split parsing and decoding between two
separate processes connected by a pipe or network connection.
hclpack is intended to provide compact wire formats for sending bodies
over the network such that they can be decoded and evaluated and get the
same results. This is not something that can happen fully automatically
because a hcl.Body is an abstract node rather than a physical construct,
and so access to the original source code is required to construct such
a representation, and to interpret any source ranges that emerged from
the final evaluation.