Commit Graph

404 Commits

Author SHA1 Message Date
Martin Atkins
17ff23300f hclwrite: NewEmptyFile function
This completes the minimal functionality for creating a new file from
scratch, rather than modifying an existing one. This is illustrated by
a new test TestRoundupCreate that uses the API to create a new file in a
similar way to how a calling application might.
2018-11-03 20:45:25 +00:00
Martin Atkins
a44a287724 hclwrite: Make File and Tokens implement io.WriterTo
There isn't any strong reason for this -- they don't implement io.Reader
and so can't be used in places where a Reader+WriterTo is expected, like
io.Copy -- but go lint thinks that anything called WriteTo with an
io.Writer argument is an attempt to implement WriterTo and so this just
shuts up the linter.
2018-11-03 20:19:56 +00:00
Martin Atkins
fd915f557d hclwrite: Rename Body.AppendBlock to AppendNewBlock
Since this function implicitly creates a new body, this name is more
appropriate and leaves the name "AppendBlock" open for a later method to
append an _existing_ block, such as when moving a block from one file
to another.
2018-11-03 19:54:56 +00:00
Martin Atkins
379d277e2b hcl/hclsyntax: Fix invalid block parsing test
Invalid blocks now have empty bodies rather than nil bodies, to avoid the
need to callers to specially handle nils here when they are doing analysis
of a partially-invalid file.
2018-11-03 19:49:14 +00:00
Martin Atkins
57c6d75eb8 hclwrite: Body.AppendBlock
This method allows a caller to generate a nested block within a body.
Since a nested block has its own content body, this now allows for deep
structures to be generated.
2018-11-03 09:21:43 -07:00
Martin Atkins
98352801f3 go mod tidy 2018-11-03 09:21:43 -07:00
Martin Atkins
04d1413613 hclwrite: Split Attribute and Block into their own source files
These will grow to have significant logic of their own, so hiding them at
the end of the Body file makes things harder to read.
2018-11-03 09:21:43 -07:00
Martin Atkins
3e4b7e0eb2 hclsyntax: If nested block doesn't parse, produce empty body
Our usual rule for parse errors is to return a valid-but-incomplete object
along with error diagnostics. This was violating that rule by returning
a nil child body, which callers do not expect to deal with.

Instead, we'll return an *empty* body, so that callers who use the partial
result for careful analyses can still process the block header, without
needing to guard against the body being nil.
2018-10-01 14:06:26 -07:00
Martin Atkins
cce5ae6cc5 hclsyntax: Remove hclsyntax.Transform
This was always a bit of an outlier here because the rest of the API is
intentionally designed to encourage treating AST nodes as immutable.

Although the transforming walkers were functionally correct, they were
causing false positives in the race detector if two walks run concurrently.

We may later introduce something similar to this in the hclwrite package,
where the AST nodes are explicitly mutable.
2018-09-26 07:38:54 -07:00
Radek Simko
3f1c5474d4 hclsyntax: Add test for idx'd func outputs 2018-09-25 10:55:40 -07:00
Martin Atkins
983c83c156 hclsyntax: Some tests for Walk
These tests are not yet comprehensive, but at least cover some normal
cases and some cases that have some trickier behavior.
2018-09-25 08:25:42 -07:00
Martin Atkins
e1e97716f5 hclsyntax: RelativeTraversalExpr walkChildNodes implementation
Unlike ScopeTraversalExpr, this node type _does_ have an expression as its
source and so it must include that expression in an AST walk.
2018-09-25 08:25:42 -07:00
Martin Atkins
2933fec4da hclsyntax: Walk must call Walker.Exit before returning 2018-09-25 08:25:42 -07:00
Radek Simko
ffb8e97eb7
Merge pull request #49 from hashicorp/t-hclsyntax-fix
hclsyntax: Add test for 'func()[idx]' syntax
2018-09-21 18:02:03 +01:00
Radek Simko
ef3dcd77da
hclsyntax: Add test for parsing of idx'd function calls 2018-09-21 16:13:21 +01:00
Radek Simko
def7e926c9
hclsyntax: Fix incorrect positions in tests 2018-09-21 12:04:32 +01:00
Martin Atkins
864f97c8ab guide: A section on input file naming conventions 2018-09-05 08:26:29 -07:00
Martin Atkins
dc326dd882 guide: Update the main title to "HCL Config Language Toolkit"
"HCL Configuration Language" will feel redundant to anyone who thinks
they know what "HCL" is supposed to stand for, even though our docs don't
actually expand the abbreviation at all. This new version is also still
redundant with that interpretation, but at least it emphasizes that it's
a toolkit for creating configuration languages rather than a configuration
language in its own right.
2018-09-05 08:16:17 -07:00
Martin Atkins
e78fa0ded2 guide: Guide-type documentation for HCL 2018-09-05 08:10:27 -07:00
Martin Atkins
57c9a676d7 guide: The "Configuration Language Design" section 2018-09-05 08:08:11 -07:00
Martin Atkins
280771fe8a guide: Design Patterns for Complex Systems section 2018-08-31 22:01:43 -07:00
Martin Atkins
495dfc9487 guide: Low-level API section 2018-08-31 07:40:30 -07:00
Martin Atkins
d2e7762e9a guide: Expression Evaluation page content 2018-08-28 08:45:24 -07:00
Martin Atkins
50cdb5d614 guide: Stub out some more of the overall guide outline 2018-08-26 10:28:03 -07:00
Martin Atkins
b737ad87a3 guide: A section on dynamic decoding using hcldec 2018-08-26 10:03:28 -07:00
Martin Atkins
3b190b826e guide: Disable the autoapi extension
This extension isn't working well for Go, so we're not using it for now.
2018-08-25 17:06:04 -07:00
Martin Atkins
33120477c7 guide: When running in Read The Docs, get version from its environment
Git isn't available in the Read The Docs build, but we don't actually need
it there anyway because we are told the version number that Read The Docs
thinks it is building.
2018-08-25 17:01:35 -07:00
Martin Atkins
c6f6feed76 guide: Start of HCL usage guide
This is guide-style documentation to introduce the different parts of HCL,
as a complement to the reference documentation provided in godoc.
2018-08-25 16:36:05 -07:00
Martin Atkins
d754d5a269 hclwrite: Adjust token spacing automatically when writing
Although our underlying parse tree retains all of the token content, it
doesn't necessarily retain all of the spacing information under editing,
and so formatting on save ensures that we'll produce a canonical result
even if some edits have been applied that have changed the expected
alignment of objects, etc.
2018-08-25 12:15:40 -07:00
Martin Atkins
ed8144cda1 hcldec: BlockTupleSpec and BlockObjectSpec
When nested attributes are of type cty.DynamicPseudoType, a block spec
that is backed by a cty collection is annoying to use because it requires
all of the blocks to have homogenous types for such attributes.

These new specs are similar to BlockListSpec and BlockMapSpec
respectively, but permit each nested block result to have its own distinct
type.

In return for this flexibility, we lose the ability to predict the exact
type of the result: these specs must just indicate their type as being
cty.DynamicPseudoType themselves, since we need to know how many blocks
there are and what types are inside them before we can know our final
result type.
2018-08-22 12:31:30 -07:00
Martin Atkins
b82170e941 hcldec: Handle or forbid cty.DynamicPseudoType attributes in nested blocks
Our BlockList, BlockSet, and BlockMap specs all produce cty collection
values, which require all elements to have a homogeneous type. If the
nested spec contained an attribute of type cty.DynamicPseudoType, that
would create the risk of each element having a different type, which would
previously have caused decoding to panic.

Now we either handle this during decode (BlockList, BlockSet) or forbid
it outright (BlockMap) to prevent that crash. BlockMap could _potentially_
also handle this during decode, but that would require a more significant
reorganization of its implementation than I want to take on right now,
and decoding dynamically-typed values inside collections is an edge case
anyway.
2018-08-22 11:52:40 -07:00
Martin Atkins
d6049c2a04 Get ready to be a Go module
However, since this repository is only a temporary home for this module,
the go.mod file carries a warning to that effect. It will move to its more
permanent home as it transitions from experimental to released.
2018-08-17 19:07:38 -07:00
Martin Atkins
c79a9bd509 Beginnings of automated test suite for spec compliance.
The test cases are far from complete, but the mechanism is in place.
2018-08-12 18:23:14 -07:00
Martin Atkins
ef5c50bb09 hcl/spectests: run the spec testsuite as part of "go test"
Although the spec testsuite and associated harness is designed to be
usable by other implementations of HCL not written in Go, it's convenient
to run it as part of our own "go test" test suite here so there isn't
an additional thing to run on each change.

To achieve this, the new package hcl/spectests will build both hcldec and
hclspecsuite from latest source and then run the latter to execute the
test suite, capturing the output and converting it (sloppily) into
testing.T method calls to produce something vaguely reasonable.

Other than the small amount of "parsing" to make it look in the output
like a normal Go test, there's nothing special going on here and so it's
still valid to run the spec suite manually with a build of hcldec from
this codebase, which should produce the same result.
2018-08-12 18:22:10 -07:00
Martin Atkins
12f0f2dbc5 specsuite: a few additional tests for structure
This is still not fully comprehensive, but tests some basic functionality.
2018-08-12 18:18:58 -07:00
Martin Atkins
74466f4d35 cmd/hclspecsuite: show source snippets for errors in .hcldec files 2018-08-12 10:29:13 -07:00
Martin Atkins
a5c0f7fdcc cmd/hclspecsuite: Check for expected diagnostics
When a test file declares one or more expected diagnostics, we check those
instead of checking the result value. The severities and source ranges
must match.

We don't test the error messages themselves because they are not part of
the specification and may vary between implementations or, in future, be
translated into other languages.
2018-08-12 10:08:27 -07:00
Martin Atkins
767fb36174 cmd/hclspecsuite: Check for traversals when requested 2018-08-12 09:31:28 -07:00
Martin Atkins
95b1859585 cmd/hclspecsuite: Decode expected traversals and diagnostics
These are not used by the test harness yet, but they can now be decoded
from a test spec file.
2018-08-11 20:21:32 -07:00
Martin Atkins
65f9271b86 specsuite: Initial test for top-level attribute handling 2018-08-10 08:57:59 -07:00
Martin Atkins
db04b3dffe specsuites: Tests for comment parsing 2018-08-10 08:51:51 -07:00
Martin Atkins
48039c0368 cmd/hclspecsuite: basic runner functionality for successful cases
The harness can now run tests that decode successfully and compare the
result with a given value. Further work is required in later commits to
deal with other cases, such as tests that intentionally produce errors.
2018-08-10 08:49:43 -07:00
Martin Atkins
0956c193b7 specsuite: Start of the harness for the specification test suite 2018-08-09 19:29:32 -07:00
Martin Atkins
6743a2254b cmd/hcldec: opt-in JSON-formatted diagnostics
By default we generate human-readable diagnostics on the assumption that
the caller is a simple program that is capturing stdin via a pipe and
letting stderr go to the terminal.

More sophisticated callers may wish to analyze the diagnostics themselves
and perhaps present them in a different way, such as via a GUI.
2018-08-09 18:10:14 -07:00
Martin Atkins
609cc35d49 cmd/hcldec: --var-refs option
This option skips the usual decoding step and instead prints out a JSON-
formatted list of the variables that are referenced by the configuration.

In simple cases this is not required, but for more complex use-cases it
can be useful to first analyze the input to see which variables need to
be in the scope, then construct a suitable set of variables before finally
decoding the input. For example, some of the variable values may be
expensive to produce.
2018-08-09 18:10:14 -07:00
Martin Atkins
bb724af7fd hcldec: BlockAttrsSpec spec type
This is the hcldec interface to Body.JustAttributes, producing a map whose
keys are the child attribute names and whose values are the results of
evaluating those expressions.

We can't just expose a JustAttributes-style spec directly here because
it's not really compatible with how hcldec thinks about things, but we
can expose a spec that decodes a specific child block because that can
then compose properly with other specs at the same level without
interfering with their operation.

The primary use for this is to allow the use of the block syntax to define
a map:

    dynamic_stuff {
      foo = "bar"
    }

JustAttributes is normally used in static analysis situations such as
enumerating the contents of a block to decide what to include in the
final EvalContext. That's not really possible with the hcldec model
because both structural decoding and expression evaluation happen
together. Therefore the use of this is pretty limited: it's useful if you
want to be compatible with an existing format based on legacy HCL where a
map was conventionally defined using block syntax, relying on the fact
that HCL did not make a strong distinction between attribute and block
syntax.
2018-08-09 16:53:16 -07:00
Martin Atkins
59bb5c2670 hclwrite: Fix NewExpressionAbsTraversal signature
It is still not implemented, but at least now it is declared with the
correct return type.
2018-08-09 08:47:37 -07:00
Martin Atkins
c8c208e083 hclwrite: Body.SetAttributeValue
For now, this is the only way to set an attribute, and so attributes can
only be set to literal values.

Later this will be generalized so that this is just a helper wrapper
around a "SetAttribute" method that just uses a given expression, which
then helps by constructing the expression from the value first.
2018-08-09 08:44:48 -07:00
Martin Atkins
77c0b55a59 hclwrite: Simplify internal data structures
The original prototype of hclwrite tried to track both the tokens and
the AST as two parallel data structures. This quickly exploded in
complexity, leading to lots of messy code to manage keeping those two
structures in sync.

This new approach melds the two structures together, creating first a
physical token tree (made of "node" objects, and hidden from the caller)
and then attaching the AST nodes to that token tree as additional sidecar
data.

The result is much easier to work with, leading to less code in the parser
and considerably less complex data structures in the parser's tests.

This commit is enough to reach feature parity with the previous prototype,
but it remains a prototype. With a more usable foundation, we'll evolve
this into a more complete implementation in subsequent commits.
2018-08-01 08:46:31 -07:00
Martin Atkins
b21bf61698 hclsyntax: Annotate diags from IndexExpr with source expr information 2018-07-28 15:44:44 -07:00