blob: 2499917d46fb0055003e985aa0fec17042238b74 [file] [log] [blame]
package protoparse
import "fmt"
// This file defines all of the nodes in the proto AST.
// ErrorWithSourcePos is an error about a proto source file includes information
// about the location in the file that caused the error.
type ErrorWithSourcePos struct {
Underlying error
Pos *SourcePos
}
// Error implements the error interface
func (e ErrorWithSourcePos) Error() string {
if e.Pos.Line <= 0 || e.Pos.Col <= 0 {
return fmt.Sprintf("%s: %v", e.Pos.Filename, e.Underlying)
}
return fmt.Sprintf("%s:%d:%d: %v", e.Pos.Filename, e.Pos.Line, e.Pos.Col, e.Underlying)
}
// 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}
}
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
reservedNames() []*stringLiteralNode
}
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
// These fields are populated after parsing, to make it easier to find them
// without searching decls. The parse result has a map of descriptors to
// nodes which makes the other declarations easily discoverable. But these
// elements do not map to descriptors -- they are just stored as strings in
// the file descriptor.
imports []*importNode
pkg *packageNode
}
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 *stringLiteralNode
}
type importNode struct {
basicCompositeNode
name *stringLiteralNode
public bool
weak bool
}
type packageNode struct {
basicCompositeNode
name *identNode
}
type identifier string
type identKind int
const (
identSimpleName identKind = iota
identQualified
identTypeName
)
type identNode struct {
basicNode
val string
kind identKind
}
func (n *identNode) value() interface{} {
return identifier(n.val)
}
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 *identNode
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 = (*stringLiteralNode)(nil)
var _ valueNode = (*intLiteralNode)(nil)
var _ valueNode = (*negativeIntLiteralNode)(nil)
var _ valueNode = (*floatLiteralNode)(nil)
var _ valueNode = (*boolLiteralNode)(nil)
var _ valueNode = (*sliceLiteralNode)(nil)
var _ valueNode = (*aggregateLiteralNode)(nil)
var _ valueNode = (*noSourceNode)(nil)
type stringLiteralNode struct {
basicCompositeNode
val string
}
func (n *stringLiteralNode) value() interface{} {
return n.val
}
func (n *stringLiteralNode) popLeadingComment() *comment {
return n.first.(terminalNode).popLeadingComment()
}
func (n *stringLiteralNode) pushTrailingComment(c *comment) {
n.last.(terminalNode).pushTrailingComment(c)
}
type intLiteralNode struct {
basicNode
val uint64
}
func (n *intLiteralNode) value() interface{} {
return n.val
}
type negativeIntLiteralNode struct {
basicCompositeNode
val int64
}
func (n *negativeIntLiteralNode) value() interface{} {
return n.val
}
type floatLiteralNode struct {
basicCompositeNode
val float64
}
func (n *floatLiteralNode) value() interface{} {
return n.val
}
func (n *floatLiteralNode) popLeadingComment() *comment {
return n.first.(terminalNode).popLeadingComment()
}
func (n *floatLiteralNode) pushTrailingComment(c *comment) {
n.last.(terminalNode).pushTrailingComment(c)
}
type boolLiteralNode struct {
basicNode
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 *identNode
isExtension bool
}
func (a *aggregateNameNode) value() string {
if a.isExtension {
return "[" + a.name.val + "]"
} else {
return a.name.val
}
}
type fieldNode struct {
basicCompositeNode
label *labelNode
fldType *identNode
name *identNode
tag *intLiteralNode
options []*optionNode
// 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 == nil {
return nil
}
return n.label
}
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 labelNode struct {
basicNode
repeated bool
required bool
}
type groupNode struct {
basicCompositeNode
groupKeyword *identNode
label *labelNode
name *identNode
tag *intLiteralNode
decls []*messageElement
// This field is populated after parsing, to make it easier to find them
// without searching decls. The parse result has a map of descriptors to
// nodes which makes the other declarations easily discoverable. But these
// elements do not map to descriptors -- they are just stored as strings in
// the message descriptor.
reserved []*stringLiteralNode
// 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 {
return n.label
}
func (n *groupNode) fieldName() node {
return n.name
}
func (n *groupNode) fieldType() node {
return n.name
}
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
}
func (n *groupNode) reservedNames() []*stringLiteralNode {
return n.reserved
}
type oneOfNode struct {
basicCompositeNode
name *identNode
decls []*oneOfElement
}
type oneOfElement struct {
// a discriminated union: only one field will be set
option *optionNode
field *fieldNode
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 mapFieldNode struct {
basicCompositeNode
mapKeyword *identNode
keyType *identNode
valueType *identNode
name *identNode
tag *intLiteralNode
options []*optionNode
}
func (n *mapFieldNode) fieldLabel() node {
return n.mapKeyword
}
func (n *mapFieldNode) fieldName() node {
return n.name
}
func (n *mapFieldNode) fieldType() node {
return n.mapKeyword
}
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) reservedNames() []*stringLiteralNode {
return nil
}
func (n *mapFieldNode) keyField() *syntheticMapField {
tag := &intLiteralNode{
basicNode: basicNode{
posRange: posRange{start: n.keyType.start(), end: n.keyType.end()},
},
val: 1,
}
return &syntheticMapField{ident: n.keyType, tag: tag}
}
func (n *mapFieldNode) valueField() *syntheticMapField {
tag := &intLiteralNode{
basicNode: basicNode{
posRange: posRange{start: n.valueType.start(), end: n.valueType.end()},
},
val: 2,
}
return &syntheticMapField{ident: n.valueType, tag: tag}
}
type syntheticMapField struct {
ident *identNode
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 []*optionNode
}
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 []*stringLiteralNode
}
type enumNode struct {
basicCompositeNode
name *identNode
decls []*enumElement
// This field is populated after parsing, to make it easier to find them
// without searching decls. The parse result has a map of descriptors to
// nodes which makes the other declarations easily discoverable. But these
// elements do not map to descriptors -- they are just stored as strings in
// the message descriptor.
reserved []*stringLiteralNode
}
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 []*optionNode
// only one of these two will be set:
numberP *intLiteralNode // positive numeric value
numberN *negativeIntLiteralNode // negative numeric value
}
func (n *enumValueNode) getName() node {
return n.name
}
func (n *enumValueNode) getNumber() node {
if n.numberP != nil {
return n.numberP
}
return n.numberN
}
type messageNode struct {
basicCompositeNode
name *identNode
decls []*messageElement
// This field is populated after parsing, to make it easier to find them
// without searching decls. The parse result has a map of descriptors to
// nodes which makes the other declarations easily discoverable. But these
// elements do not map to descriptors -- they are just stored as strings in
// the message descriptor.
reserved []*stringLiteralNode
}
func (n *messageNode) messageName() node {
return n.name
}
func (n *messageNode) reservedNames() []*stringLiteralNode {
return n.reserved
}
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 *identNode
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 *identNode
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) reservedNames() []*stringLiteralNode {
return nil
}
func (n noSourceNode) getInputType() node {
return n
}
func (n noSourceNode) getOutputType() node {
return n
}
func (n noSourceNode) value() interface{} {
return nil
}