blob: e1eb4dfe08e17ef09b8ca15d2448c83f8d240b0c [file] [log] [blame]
package protoparse
// This file defines all of the nodes in the proto AST.
// SourcePos identifies a location in a proto source file.
type SourcePos struct {
Filename string
Line, Col int
Offset int
}
func unknownPos(filename string) *SourcePos {
return &SourcePos{Filename: filename}
}
// node is the interface implemented by all nodes in the AST
type node interface {
start() *SourcePos
end() *SourcePos
leadingComments() []comment
trailingComments() []comment
}
type terminalNode interface {
node
popLeadingComment() comment
pushTrailingComment(comment)
}
var _ terminalNode = (*basicNode)(nil)
var _ terminalNode = (*stringLiteralNode)(nil)
var _ terminalNode = (*intLiteralNode)(nil)
var _ terminalNode = (*floatLiteralNode)(nil)
var _ terminalNode = (*identNode)(nil)
type fileDecl interface {
node
getSyntax() node
}
var _ fileDecl = (*fileNode)(nil)
var _ fileDecl = (*noSourceNode)(nil)
type optionDecl interface {
node
getName() node
getValue() valueNode
}
var _ optionDecl = (*optionNode)(nil)
var _ optionDecl = (*noSourceNode)(nil)
type fieldDecl interface {
node
fieldLabel() node
fieldName() node
fieldType() node
fieldTag() node
fieldExtendee() node
getGroupKeyword() node
}
var _ fieldDecl = (*fieldNode)(nil)
var _ fieldDecl = (*groupNode)(nil)
var _ fieldDecl = (*mapFieldNode)(nil)
var _ fieldDecl = (*syntheticMapField)(nil)
var _ fieldDecl = (*noSourceNode)(nil)
type rangeDecl interface {
node
rangeStart() node
rangeEnd() node
}
var _ rangeDecl = (*rangeNode)(nil)
var _ rangeDecl = (*noSourceNode)(nil)
type enumValueDecl interface {
node
getName() node
getNumber() node
}
var _ enumValueDecl = (*enumValueNode)(nil)
var _ enumValueDecl = (*noSourceNode)(nil)
type msgDecl interface {
node
messageName() node
}
var _ msgDecl = (*messageNode)(nil)
var _ msgDecl = (*groupNode)(nil)
var _ msgDecl = (*mapFieldNode)(nil)
var _ msgDecl = (*noSourceNode)(nil)
type methodDecl interface {
node
getInputType() node
getOutputType() node
}
var _ methodDecl = (*methodNode)(nil)
var _ methodDecl = (*noSourceNode)(nil)
type posRange struct {
start, end SourcePos
}
type basicNode struct {
posRange
leading []comment
trailing []comment
}
func (n *basicNode) start() *SourcePos {
return &n.posRange.start
}
func (n *basicNode) end() *SourcePos {
return &n.posRange.end
}
func (n *basicNode) leadingComments() []comment {
return n.leading
}
func (n *basicNode) trailingComments() []comment {
return n.trailing
}
func (n *basicNode) popLeadingComment() comment {
c := n.leading[0]
n.leading = n.leading[1:]
return c
}
func (n *basicNode) pushTrailingComment(c comment) {
n.trailing = append(n.trailing, c)
}
type comment struct {
posRange
text string
}
type basicCompositeNode struct {
first node
last node
}
func (n *basicCompositeNode) start() *SourcePos {
return n.first.start()
}
func (n *basicCompositeNode) end() *SourcePos {
return n.last.end()
}
func (n *basicCompositeNode) leadingComments() []comment {
return n.first.leadingComments()
}
func (n *basicCompositeNode) trailingComments() []comment {
return n.last.trailingComments()
}
func (n *basicCompositeNode) setRange(first, last node) {
n.first = first
n.last = last
}
type fileNode struct {
basicCompositeNode
syntax *syntaxNode
decls []*fileElement
// This field is populated after parsing, to make it easier to find
// source locations by import name for constructing link errors.
imports []*importNode
}
func (n *fileNode) getSyntax() node {
return n.syntax
}
type fileElement struct {
// a discriminated union: only one field will be set
imp *importNode
pkg *packageNode
option *optionNode
message *messageNode
enum *enumNode
extend *extendNode
service *serviceNode
empty *basicNode
}
func (n *fileElement) start() *SourcePos {
return n.get().start()
}
func (n *fileElement) end() *SourcePos {
return n.get().end()
}
func (n *fileElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *fileElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *fileElement) get() node {
switch {
case n.imp != nil:
return n.imp
case n.pkg != nil:
return n.pkg
case n.option != nil:
return n.option
case n.message != nil:
return n.message
case n.enum != nil:
return n.enum
case n.extend != nil:
return n.extend
case n.service != nil:
return n.service
default:
return n.empty
}
}
type syntaxNode struct {
basicCompositeNode
syntax *compoundStringNode
}
type importNode struct {
basicCompositeNode
name *compoundStringNode
public bool
weak bool
}
type packageNode struct {
basicCompositeNode
name *compoundIdentNode
}
type identifier string
type identNode struct {
basicNode
val string
}
func (n *identNode) value() interface{} {
return identifier(n.val)
}
type compoundIdentNode struct {
basicCompositeNode
val string
}
func (n *compoundIdentNode) value() interface{} {
return identifier(n.val)
}
type compactOptionsNode struct {
basicCompositeNode
decls []*optionNode
}
func (n *compactOptionsNode) Elements() []*optionNode {
if n == nil {
return nil
}
return n.decls
}
type optionNode struct {
basicCompositeNode
name *optionNameNode
val valueNode
}
func (n *optionNode) getName() node {
return n.name
}
func (n *optionNode) getValue() valueNode {
return n.val
}
type optionNameNode struct {
basicCompositeNode
parts []*optionNamePartNode
}
type optionNamePartNode struct {
basicCompositeNode
text *compoundIdentNode
offset int
length int
isExtension bool
st, en *SourcePos
}
func (n *optionNamePartNode) start() *SourcePos {
if n.isExtension {
return n.basicCompositeNode.start()
}
return n.st
}
func (n *optionNamePartNode) end() *SourcePos {
if n.isExtension {
return n.basicCompositeNode.end()
}
return n.en
}
func (n *optionNamePartNode) setRange(first, last node) {
n.basicCompositeNode.setRange(first, last)
if !n.isExtension {
st := *first.start()
st.Col += n.offset
n.st = &st
en := st
en.Col += n.length
n.en = &en
}
}
type valueNode interface {
node
value() interface{}
}
var _ valueNode = (*identNode)(nil)
var _ valueNode = (*compoundIdentNode)(nil)
var _ valueNode = (*stringLiteralNode)(nil)
var _ valueNode = (*compoundStringNode)(nil)
var _ valueNode = (*intLiteralNode)(nil)
var _ valueNode = (*compoundIntNode)(nil)
var _ valueNode = (*compoundUintNode)(nil)
var _ valueNode = (*floatLiteralNode)(nil)
var _ valueNode = (*compoundFloatNode)(nil)
var _ valueNode = (*boolLiteralNode)(nil)
var _ valueNode = (*sliceLiteralNode)(nil)
var _ valueNode = (*aggregateLiteralNode)(nil)
var _ valueNode = (*noSourceNode)(nil)
type stringLiteralNode struct {
basicNode
val string
}
func (n *stringLiteralNode) value() interface{} {
return n.val
}
type compoundStringNode struct {
basicCompositeNode
val string
}
func (n *compoundStringNode) value() interface{} {
return n.val
}
type intLiteralNode struct {
basicNode
val uint64
}
func (n *intLiteralNode) value() interface{} {
return n.val
}
type compoundUintNode struct {
basicCompositeNode
val uint64
}
func (n *compoundUintNode) value() interface{} {
return n.val
}
type compoundIntNode struct {
basicCompositeNode
val int64
}
func (n *compoundIntNode) value() interface{} {
return n.val
}
type floatLiteralNode struct {
basicNode
val float64
}
func (n *floatLiteralNode) value() interface{} {
return n.val
}
type compoundFloatNode struct {
basicCompositeNode
val float64
}
func (n *compoundFloatNode) value() interface{} {
return n.val
}
type boolLiteralNode struct {
*identNode
val bool
}
func (n *boolLiteralNode) value() interface{} {
return n.val
}
type sliceLiteralNode struct {
basicCompositeNode
elements []valueNode
}
func (n *sliceLiteralNode) value() interface{} {
return n.elements
}
type aggregateLiteralNode struct {
basicCompositeNode
elements []*aggregateEntryNode
}
func (n *aggregateLiteralNode) value() interface{} {
return n.elements
}
type aggregateEntryNode struct {
basicCompositeNode
name *aggregateNameNode
val valueNode
}
type aggregateNameNode struct {
basicCompositeNode
name *compoundIdentNode
isExtension bool
}
func (a *aggregateNameNode) value() string {
if a.isExtension {
return "[" + a.name.val + "]"
} else {
return a.name.val
}
}
type fieldNode struct {
basicCompositeNode
label fieldLabel
fldType *compoundIdentNode
name *identNode
tag *intLiteralNode
options *compactOptionsNode
// This field is populated after parsing, to allow lookup of extendee source
// locations when field extendees cannot be linked. (Otherwise, this is just
// stored as a string in the field descriptors defined inside the extend
// block).
extendee *extendNode
}
func (n *fieldNode) fieldLabel() node {
// proto3 fields and fields inside one-ofs will not have a label and we need
// this check in order to return a nil node -- otherwise we'd return a
// non-nil node that has a nil pointer value in it :/
if n.label.identNode == nil {
return nil
}
return n.label.identNode
}
func (n *fieldNode) fieldName() node {
return n.name
}
func (n *fieldNode) fieldType() node {
return n.fldType
}
func (n *fieldNode) fieldTag() node {
return n.tag
}
func (n *fieldNode) fieldExtendee() node {
if n.extendee != nil {
return n.extendee.extendee
}
return nil
}
func (n *fieldNode) getGroupKeyword() node {
return nil
}
type fieldLabel struct {
*identNode
repeated bool
required bool
}
type groupNode struct {
basicCompositeNode
groupKeyword *identNode
label fieldLabel
name *identNode
tag *intLiteralNode
decls []*messageElement
// This field is populated after parsing, to allow lookup of extendee source
// locations when field extendees cannot be linked. (Otherwise, this is just
// stored as a string in the field descriptors defined inside the extend
// block).
extendee *extendNode
}
func (n *groupNode) fieldLabel() node {
if n.label.identNode == nil {
// return nil interface to indicate absence, not a typed nil
return nil
}
return n.label.identNode
}
func (n *groupNode) fieldName() node {
return n.name
}
func (n *groupNode) fieldType() node {
return n.groupKeyword
}
func (n *groupNode) fieldTag() node {
return n.tag
}
func (n *groupNode) fieldExtendee() node {
if n.extendee != nil {
return n.extendee.extendee
}
return nil
}
func (n *groupNode) getGroupKeyword() node {
return n.groupKeyword
}
func (n *groupNode) messageName() node {
return n.name
}
type oneOfNode struct {
basicCompositeNode
name *identNode
decls []*oneOfElement
}
type oneOfElement struct {
// a discriminated union: only one field will be set
option *optionNode
field *fieldNode
group *groupNode
empty *basicNode
}
func (n *oneOfElement) start() *SourcePos {
return n.get().start()
}
func (n *oneOfElement) end() *SourcePos {
return n.get().end()
}
func (n *oneOfElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *oneOfElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *oneOfElement) get() node {
switch {
case n.option != nil:
return n.option
case n.field != nil:
return n.field
default:
return n.empty
}
}
type mapTypeNode struct {
basicCompositeNode
mapKeyword *identNode
keyType *identNode
valueType *compoundIdentNode
}
type mapFieldNode struct {
basicCompositeNode
mapType *mapTypeNode
name *identNode
tag *intLiteralNode
options *compactOptionsNode
}
func (n *mapFieldNode) fieldLabel() node {
return nil
}
func (n *mapFieldNode) fieldName() node {
return n.name
}
func (n *mapFieldNode) fieldType() node {
return n.mapType
}
func (n *mapFieldNode) fieldTag() node {
return n.tag
}
func (n *mapFieldNode) fieldExtendee() node {
return nil
}
func (n *mapFieldNode) getGroupKeyword() node {
return nil
}
func (n *mapFieldNode) messageName() node {
return n.name
}
func (n *mapFieldNode) keyField() *syntheticMapField {
k := n.mapType.keyType
t := &compoundIdentNode{val: k.val}
t.setRange(k, k)
return newSyntheticMapField(t, 1)
}
func (n *mapFieldNode) valueField() *syntheticMapField {
return newSyntheticMapField(n.mapType.valueType, 2)
}
func newSyntheticMapField(ident *compoundIdentNode, tagNum uint64) *syntheticMapField {
tag := &intLiteralNode{
basicNode: basicNode{
posRange: posRange{start: *ident.start(), end: *ident.end()},
},
val: tagNum,
}
return &syntheticMapField{ident: ident, tag: tag}
}
type syntheticMapField struct {
ident *compoundIdentNode
tag *intLiteralNode
}
func (n *syntheticMapField) start() *SourcePos {
return n.ident.start()
}
func (n *syntheticMapField) end() *SourcePos {
return n.ident.end()
}
func (n *syntheticMapField) leadingComments() []comment {
return nil
}
func (n *syntheticMapField) trailingComments() []comment {
return nil
}
func (n *syntheticMapField) fieldLabel() node {
return n.ident
}
func (n *syntheticMapField) fieldName() node {
return n.ident
}
func (n *syntheticMapField) fieldType() node {
return n.ident
}
func (n *syntheticMapField) fieldTag() node {
return n.tag
}
func (n *syntheticMapField) fieldExtendee() node {
return nil
}
func (n *syntheticMapField) getGroupKeyword() node {
return nil
}
type extensionRangeNode struct {
basicCompositeNode
ranges []*rangeNode
options *compactOptionsNode
}
type rangeNode struct {
basicCompositeNode
stNode, enNode node
st, en int32
}
func (n *rangeNode) rangeStart() node {
return n.stNode
}
func (n *rangeNode) rangeEnd() node {
return n.enNode
}
type reservedNode struct {
basicCompositeNode
ranges []*rangeNode
names []*compoundStringNode
}
type enumNode struct {
basicCompositeNode
name *identNode
decls []*enumElement
}
type enumElement struct {
// a discriminated union: only one field will be set
option *optionNode
value *enumValueNode
reserved *reservedNode
empty *basicNode
}
func (n *enumElement) start() *SourcePos {
return n.get().start()
}
func (n *enumElement) end() *SourcePos {
return n.get().end()
}
func (n *enumElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *enumElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *enumElement) get() node {
switch {
case n.option != nil:
return n.option
case n.value != nil:
return n.value
default:
return n.empty
}
}
type enumValueNode struct {
basicCompositeNode
name *identNode
options *compactOptionsNode
number *compoundIntNode
}
func (n *enumValueNode) getName() node {
return n.name
}
func (n *enumValueNode) getNumber() node {
return n.number
}
type messageNode struct {
basicCompositeNode
name *identNode
decls []*messageElement
}
func (n *messageNode) messageName() node {
return n.name
}
type messageElement struct {
// a discriminated union: only one field will be set
option *optionNode
field *fieldNode
mapField *mapFieldNode
oneOf *oneOfNode
group *groupNode
nested *messageNode
enum *enumNode
extend *extendNode
extensionRange *extensionRangeNode
reserved *reservedNode
empty *basicNode
}
func (n *messageElement) start() *SourcePos {
return n.get().start()
}
func (n *messageElement) end() *SourcePos {
return n.get().end()
}
func (n *messageElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *messageElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *messageElement) get() node {
switch {
case n.option != nil:
return n.option
case n.field != nil:
return n.field
case n.mapField != nil:
return n.mapField
case n.oneOf != nil:
return n.oneOf
case n.group != nil:
return n.group
case n.nested != nil:
return n.nested
case n.enum != nil:
return n.enum
case n.extend != nil:
return n.extend
case n.extensionRange != nil:
return n.extensionRange
case n.reserved != nil:
return n.reserved
default:
return n.empty
}
}
type extendNode struct {
basicCompositeNode
extendee *compoundIdentNode
decls []*extendElement
}
type extendElement struct {
// a discriminated union: only one field will be set
field *fieldNode
group *groupNode
empty *basicNode
}
func (n *extendElement) start() *SourcePos {
return n.get().start()
}
func (n *extendElement) end() *SourcePos {
return n.get().end()
}
func (n *extendElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *extendElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *extendElement) get() node {
switch {
case n.field != nil:
return n.field
case n.group != nil:
return n.group
default:
return n.empty
}
}
type serviceNode struct {
basicCompositeNode
name *identNode
decls []*serviceElement
}
type serviceElement struct {
// a discriminated union: only one field will be set
option *optionNode
rpc *methodNode
empty *basicNode
}
func (n *serviceElement) start() *SourcePos {
return n.get().start()
}
func (n *serviceElement) end() *SourcePos {
return n.get().end()
}
func (n *serviceElement) leadingComments() []comment {
return n.get().leadingComments()
}
func (n *serviceElement) trailingComments() []comment {
return n.get().trailingComments()
}
func (n *serviceElement) get() node {
switch {
case n.option != nil:
return n.option
case n.rpc != nil:
return n.rpc
default:
return n.empty
}
}
type methodNode struct {
basicCompositeNode
name *identNode
input *rpcTypeNode
output *rpcTypeNode
options []*optionNode
}
func (n *methodNode) getInputType() node {
return n.input.msgType
}
func (n *methodNode) getOutputType() node {
return n.output.msgType
}
type rpcTypeNode struct {
basicCompositeNode
msgType *compoundIdentNode
streamKeyword node
}
type noSourceNode struct {
pos *SourcePos
}
func (n noSourceNode) start() *SourcePos {
return n.pos
}
func (n noSourceNode) end() *SourcePos {
return n.pos
}
func (n noSourceNode) leadingComments() []comment {
return nil
}
func (n noSourceNode) trailingComments() []comment {
return nil
}
func (n noSourceNode) getSyntax() node {
return n
}
func (n noSourceNode) getName() node {
return n
}
func (n noSourceNode) getValue() valueNode {
return n
}
func (n noSourceNode) fieldLabel() node {
return n
}
func (n noSourceNode) fieldName() node {
return n
}
func (n noSourceNode) fieldType() node {
return n
}
func (n noSourceNode) fieldTag() node {
return n
}
func (n noSourceNode) fieldExtendee() node {
return n
}
func (n noSourceNode) getGroupKeyword() node {
return n
}
func (n noSourceNode) rangeStart() node {
return n
}
func (n noSourceNode) rangeEnd() node {
return n
}
func (n noSourceNode) getNumber() node {
return n
}
func (n noSourceNode) messageName() node {
return n
}
func (n noSourceNode) getInputType() node {
return n
}
func (n noSourceNode) getOutputType() node {
return n
}
func (n noSourceNode) value() interface{} {
return nil
}