hcl/zclwrite/ast.go
Martin Atkins c88641b147 zclwrite: absorb lead comments into attributes
The native parser's ranges don't include any surrounding comments, so we
need to do a little more work to pick them out of the surrounding token
sequences.

This just takes care of _lead_ comments, which are those that appear as
whole line comments above the item in question. Line comments, which
appear after the item on the same line, will follow in a later commit.
2017-06-08 09:04:27 -07:00

146 lines
3.0 KiB
Go

package zclwrite
import (
"bytes"
"io"
)
type Node interface {
walkChildNodes(w internalWalkFunc)
Tokens() *TokenSeq
}
type internalWalkFunc func(Node)
type File struct {
Name string
SrcBytes []byte
Body *Body
AllTokens *TokenSeq
}
// WriteTo writes the tokens underlying the receiving file to the given writer.
func (f *File) WriteTo(wr io.Writer) (int, error) {
return f.AllTokens.WriteTo(wr)
}
// Bytes returns a buffer containing the source code resulting from the
// tokens underlying the receiving file. If any updates have been made via
// the AST API, these will be reflected in the result.
func (f *File) Bytes() []byte {
buf := &bytes.Buffer{}
f.WriteTo(buf)
return buf.Bytes()
}
// Format makes in-place modifications to the tokens underlying the receiving
// file in order to change the whitespace to be in canonical form.
func (f *File) Format() {
format(f.Body.AllTokens.Tokens())
}
type Body struct {
// Items may contain Attribute, Block and Unstructured instances.
// Items and AllTokens should be updated only by methods of this type,
// since they must be kept synchronized for correct operation.
Items []Node
AllTokens *TokenSeq
// IndentLevel is the number of spaces that should appear at the start
// of lines added within this body.
IndentLevel int
}
func (n *Body) walkChildNodes(w internalWalkFunc) {
for _, item := range n.Items {
w(item)
}
}
func (n *Body) Tokens() *TokenSeq {
return n.AllTokens
}
func (n *Body) AppendItem(node Node) {
n.Items = append(n.Items, node)
n.AppendUnstructuredTokens(node.Tokens())
}
func (n *Body) AppendUnstructuredTokens(seq *TokenSeq) {
if n.AllTokens == nil {
new := make(TokenSeq, 0, 1)
n.AllTokens = &new
}
*(n.AllTokens) = append(*(n.AllTokens), seq)
}
type Attribute struct {
AllTokens *TokenSeq
LeadCommentTokens *TokenSeq
NameTokens *TokenSeq
EqualsTokens *TokenSeq
Expr *Expression
LineCommentTokens *TokenSeq
EOLTokens *TokenSeq
}
func (a *Attribute) walkChildNodes(w internalWalkFunc) {
w(a.Expr)
}
func (n *Attribute) Tokens() *TokenSeq {
return n.AllTokens
}
type Block struct {
AllTokens *TokenSeq
LeadCommentTokens *TokenSeq
TypeTokens *TokenSeq
LabelTokens []*TokenSeq
LabelTokensFlat *TokenSeq
OBraceTokens *TokenSeq
Body *Body
CBraceTokens *TokenSeq
EOLTokens *TokenSeq
}
func (n *Block) walkChildNodes(w internalWalkFunc) {
w(n.Body)
}
func (n *Block) Tokens() *TokenSeq {
return n.AllTokens
}
type Expression struct {
AllTokens *TokenSeq
VarRefs []*VarRef
}
func (n *Expression) walkChildNodes(w internalWalkFunc) {
for _, name := range n.VarRefs {
w(name)
}
}
func (n *Expression) Tokens() *TokenSeq {
return n.AllTokens
}
type VarRef struct {
// Tokens alternate between TokenIdent and TokenDot, with the first
// and last elements always being TokenIdent.
AllTokens *TokenSeq
}
func (n *VarRef) walkChildNodes(w internalWalkFunc) {
// no child nodes of a variable name
}
func (n *VarRef) Tokens() *TokenSeq {
return n.AllTokens
}