c6f6feed76
This is guide-style documentation to introduce the different parts of HCL, as a complement to the reference documentation provided in godoc.
98 lines
3.7 KiB
ReStructuredText
98 lines
3.7 KiB
ReStructuredText
.. _go-diagnostics:
|
|
|
|
Diagnostic Messages
|
|
===================
|
|
|
|
An important concern for any machine language intended for human authoring is
|
|
to produce good error messages when the input is somehow invalid, or has
|
|
other problems.
|
|
|
|
HCL uses *diagnostics* to describe problems in an end-user-oriented manner,
|
|
such that the calling application can render helpful error or warning messages.
|
|
The word "diagnostic" is a general term that covers both errors and warnings,
|
|
where errors are problems that prevent complete processing while warnings are
|
|
possible concerns that do not block processing.
|
|
|
|
HCL deviates from usual Go API practice by returning its own ``hcl.Diagnostics``
|
|
type, instead of Go's own ``error`` type. This allows functions to return
|
|
warnings without accompanying errors while not violating the usual expectation
|
|
that the absense of errors is indicated by a nil ``error``.
|
|
|
|
In order to easily accumulate and return multiple diagnostics at once, the
|
|
usual pattern for functions returning diagnostics is to gather them in a
|
|
local variable and then return it at the end of the function, or possibly
|
|
earlier if the function cannot continue due to the problems.
|
|
|
|
.. code-block:: go
|
|
|
|
func returningDiagnosticsExample() hcl.Diagnostics {
|
|
var diags hcl.Diagnostics
|
|
|
|
// ...
|
|
|
|
// Call a function that may itself produce diagnostics.
|
|
f, moreDiags := parser.LoadHCLFile("example.conf")
|
|
// always append, in case warnings are present
|
|
diags = append(diags, moreDiags...)
|
|
if diags.HasErrors() {
|
|
// If we can't safely continue in the presence of errors here, we
|
|
// can optionally return early.
|
|
return diags
|
|
}
|
|
|
|
// ...
|
|
|
|
return diags
|
|
}
|
|
|
|
A common variant of the above pattern is calling another diagnostics-generating
|
|
function in a loop, using ``continue`` to begin the next iteration when errors
|
|
are detected, but still completing all iterations and returning the union of
|
|
all of the problems encountered along the way.
|
|
|
|
In :ref:`go-parsing`, we saw that the parser can generate diagnostics which
|
|
are related to syntax problems within the loaded file. Further steps to decode
|
|
content from the loaded file can also generate diagnostics related to *semantic*
|
|
problems within the file, such as invalid expressions or type mismatches, and
|
|
so a program using HCL will generally need to accumulate diagnostics across
|
|
these various steps and then render them in the application UI somehow.
|
|
|
|
Rendering Diagnostics in the UI
|
|
-------------------------------
|
|
|
|
The best way to render diagnostics to an end-user will depend a lot on the
|
|
type of application: they might be printed into a terminal, written into a
|
|
log for later review, or even shown in a GUI.
|
|
|
|
HCL leaves the responsibility for rendering diagnostics to the calling
|
|
application, but since rendering to a terminal is a common case for command-line
|
|
tools, the `hcl` package contains a default implementation of this in the
|
|
form of a "diagnostic text writer":
|
|
|
|
.. code-block:: go
|
|
|
|
wr := hcl.NewDiagnosticTextWriter(
|
|
os.Stdout, // writer to send messages to
|
|
parser.Files(), // the parser's file cache, for source snippets
|
|
78, // wrapping width
|
|
true, // generate colored/highlighted output
|
|
)
|
|
wr.WriteDiagnostics(diags)
|
|
|
|
This default implementation of diagnostic rendering includes relevant lines
|
|
of source code for context, like this:
|
|
|
|
::
|
|
|
|
Error: Unsupported block type
|
|
|
|
on example.tf line 4, in resource "aws_instance" "example":
|
|
2: provisionr "local-exec" {
|
|
|
|
Blocks of type "provisionr" are not expected here. Did you mean "provisioner"?
|
|
|
|
If the "color" flag is enabled, the severity will be additionally indicated by
|
|
a text color and the relevant portion of the source code snippet will be
|
|
underlined to draw further attention.
|
|
|