github.com/jhump/protoreflect@v1.16.0/desc/protoparse/ast/message.go (about)

     1  package ast
     2  
     3  import "fmt"
     4  
     5  // MessageDeclNode is a node in the AST that defines a message type. This
     6  // includes normal message fields as well as implicit messages:
     7  //   - *MessageNode
     8  //   - *GroupNode (the group is a field and inline message type)
     9  //   - *MapFieldNode (map fields implicitly define a MapEntry message type)
    10  //
    11  // This also allows NoSourceNode to be used in place of one of the above
    12  // for some usages.
    13  type MessageDeclNode interface {
    14  	Node
    15  	MessageName() Node
    16  }
    17  
    18  var _ MessageDeclNode = (*MessageNode)(nil)
    19  var _ MessageDeclNode = (*GroupNode)(nil)
    20  var _ MessageDeclNode = (*MapFieldNode)(nil)
    21  var _ MessageDeclNode = NoSourceNode{}
    22  
    23  // MessageNode represents a message declaration. Example:
    24  //
    25  //	message Foo {
    26  //	  string name = 1;
    27  //	  repeated string labels = 2;
    28  //	  bytes extra = 3;
    29  //	}
    30  type MessageNode struct {
    31  	compositeNode
    32  	Keyword *KeywordNode
    33  	Name    *IdentNode
    34  	MessageBody
    35  }
    36  
    37  func (*MessageNode) fileElement() {}
    38  func (*MessageNode) msgElement()  {}
    39  
    40  // NewMessageNode creates a new *MessageNode. All arguments must be non-nil.
    41  //   - keyword: The token corresponding to the "message" keyword.
    42  //   - name: The token corresponding to the field's name.
    43  //   - openBrace: The token corresponding to the "{" rune that starts the body.
    44  //   - decls: All declarations inside the message body.
    45  //   - closeBrace: The token corresponding to the "}" rune that ends the body.
    46  func NewMessageNode(keyword *KeywordNode, name *IdentNode, openBrace *RuneNode, decls []MessageElement, closeBrace *RuneNode) *MessageNode {
    47  	if keyword == nil {
    48  		panic("keyword is nil")
    49  	}
    50  	if name == nil {
    51  		panic("name is nil")
    52  	}
    53  	if openBrace == nil {
    54  		panic("openBrace is nil")
    55  	}
    56  	if closeBrace == nil {
    57  		panic("closeBrace is nil")
    58  	}
    59  	children := make([]Node, 0, 4+len(decls))
    60  	children = append(children, keyword, name, openBrace)
    61  	for _, decl := range decls {
    62  		children = append(children, decl)
    63  	}
    64  	children = append(children, closeBrace)
    65  
    66  	ret := &MessageNode{
    67  		compositeNode: compositeNode{
    68  			children: children,
    69  		},
    70  		Keyword: keyword,
    71  		Name:    name,
    72  	}
    73  	populateMessageBody(&ret.MessageBody, openBrace, decls, closeBrace)
    74  	return ret
    75  }
    76  
    77  func (n *MessageNode) MessageName() Node {
    78  	return n.Name
    79  }
    80  
    81  // MessageBody represents the body of a message. It is used by both
    82  // MessageNodes and GroupNodes.
    83  type MessageBody struct {
    84  	OpenBrace  *RuneNode
    85  	Decls      []MessageElement
    86  	CloseBrace *RuneNode
    87  }
    88  
    89  func populateMessageBody(m *MessageBody, openBrace *RuneNode, decls []MessageElement, closeBrace *RuneNode) {
    90  	m.OpenBrace = openBrace
    91  	m.Decls = decls
    92  	for _, decl := range decls {
    93  		switch decl.(type) {
    94  		case *OptionNode, *FieldNode, *MapFieldNode, *GroupNode, *OneOfNode,
    95  			*MessageNode, *EnumNode, *ExtendNode, *ExtensionRangeNode,
    96  			*ReservedNode, *EmptyDeclNode:
    97  		default:
    98  			panic(fmt.Sprintf("invalid MessageElement type: %T", decl))
    99  		}
   100  	}
   101  	m.CloseBrace = closeBrace
   102  }
   103  
   104  // MessageElement is an interface implemented by all AST nodes that can
   105  // appear in a message body.
   106  type MessageElement interface {
   107  	Node
   108  	msgElement()
   109  }
   110  
   111  var _ MessageElement = (*OptionNode)(nil)
   112  var _ MessageElement = (*FieldNode)(nil)
   113  var _ MessageElement = (*MapFieldNode)(nil)
   114  var _ MessageElement = (*OneOfNode)(nil)
   115  var _ MessageElement = (*GroupNode)(nil)
   116  var _ MessageElement = (*MessageNode)(nil)
   117  var _ MessageElement = (*EnumNode)(nil)
   118  var _ MessageElement = (*ExtendNode)(nil)
   119  var _ MessageElement = (*ExtensionRangeNode)(nil)
   120  var _ MessageElement = (*ReservedNode)(nil)
   121  var _ MessageElement = (*EmptyDeclNode)(nil)
   122  
   123  // ExtendNode represents a declaration of extension fields. Example:
   124  //
   125  //	extend google.protobuf.FieldOptions {
   126  //	  bool redacted = 33333;
   127  //	}
   128  type ExtendNode struct {
   129  	compositeNode
   130  	Keyword    *KeywordNode
   131  	Extendee   IdentValueNode
   132  	OpenBrace  *RuneNode
   133  	Decls      []ExtendElement
   134  	CloseBrace *RuneNode
   135  }
   136  
   137  func (*ExtendNode) fileElement() {}
   138  func (*ExtendNode) msgElement()  {}
   139  
   140  // NewExtendNode creates a new *ExtendNode. All arguments must be non-nil.
   141  //   - keyword: The token corresponding to the "extend" keyword.
   142  //   - extendee: The token corresponding to the name of the extended message.
   143  //   - openBrace: The token corresponding to the "{" rune that starts the body.
   144  //   - decls: All declarations inside the message body.
   145  //   - closeBrace: The token corresponding to the "}" rune that ends the body.
   146  func NewExtendNode(keyword *KeywordNode, extendee IdentValueNode, openBrace *RuneNode, decls []ExtendElement, closeBrace *RuneNode) *ExtendNode {
   147  	if keyword == nil {
   148  		panic("keyword is nil")
   149  	}
   150  	if extendee == nil {
   151  		panic("extendee is nil")
   152  	}
   153  	if openBrace == nil {
   154  		panic("openBrace is nil")
   155  	}
   156  	if closeBrace == nil {
   157  		panic("closeBrace is nil")
   158  	}
   159  	children := make([]Node, 0, 4+len(decls))
   160  	children = append(children, keyword, extendee, openBrace)
   161  	for _, decl := range decls {
   162  		children = append(children, decl)
   163  	}
   164  	children = append(children, closeBrace)
   165  
   166  	ret := &ExtendNode{
   167  		compositeNode: compositeNode{
   168  			children: children,
   169  		},
   170  		Keyword:    keyword,
   171  		Extendee:   extendee,
   172  		OpenBrace:  openBrace,
   173  		Decls:      decls,
   174  		CloseBrace: closeBrace,
   175  	}
   176  	for _, decl := range decls {
   177  		switch decl := decl.(type) {
   178  		case *FieldNode:
   179  			decl.Extendee = ret
   180  		case *GroupNode:
   181  			decl.Extendee = ret
   182  		case *EmptyDeclNode:
   183  		default:
   184  			panic(fmt.Sprintf("invalid ExtendElement type: %T", decl))
   185  		}
   186  	}
   187  	return ret
   188  }
   189  
   190  // ExtendElement is an interface implemented by all AST nodes that can
   191  // appear in the body of an extends declaration.
   192  type ExtendElement interface {
   193  	Node
   194  	extendElement()
   195  }
   196  
   197  var _ ExtendElement = (*FieldNode)(nil)
   198  var _ ExtendElement = (*GroupNode)(nil)
   199  var _ ExtendElement = (*EmptyDeclNode)(nil)