github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/ast/service.go (about)

     1  package ast
     2  
     3  import "fmt"
     4  
     5  // ServiceNode represents a service declaration. Example:
     6  //
     7  //  service Foo {
     8  //    rpc Bar (Baz) returns (Bob);
     9  //    rpc Frobnitz (stream Parts) returns (Gyzmeaux);
    10  //  }
    11  type ServiceNode struct {
    12  	compositeNode
    13  	Keyword    *KeywordNode
    14  	Name       *IdentNode
    15  	OpenBrace  *RuneNode
    16  	Decls      []ServiceElement
    17  	CloseBrace *RuneNode
    18  }
    19  
    20  func (*ServiceNode) fileElement() {}
    21  
    22  // NewServiceNode creates a new *ServiceNode. All arguments must be non-nil.
    23  //  - keyword: The token corresponding to the "service" keyword.
    24  //  - name: The token corresponding to the service's name.
    25  //  - openBrace: The token corresponding to the "{" rune that starts the body.
    26  //  - decls: All declarations inside the service body.
    27  //  - closeBrace: The token corresponding to the "}" rune that ends the body.
    28  func NewServiceNode(keyword *KeywordNode, name *IdentNode, openBrace *RuneNode, decls []ServiceElement, closeBrace *RuneNode) *ServiceNode {
    29  	if keyword == nil {
    30  		panic("keyword is nil")
    31  	}
    32  	if name == nil {
    33  		panic("name is nil")
    34  	}
    35  	if openBrace == nil {
    36  		panic("openBrace is nil")
    37  	}
    38  	if closeBrace == nil {
    39  		panic("closeBrace is nil")
    40  	}
    41  	children := make([]Node, 0, 4+len(decls))
    42  	children = append(children, keyword, name, openBrace)
    43  	for _, decl := range decls {
    44  		children = append(children, decl)
    45  	}
    46  	children = append(children, closeBrace)
    47  
    48  	for _, decl := range decls {
    49  		switch decl := decl.(type) {
    50  		case *OptionNode, *RPCNode, *EmptyDeclNode:
    51  		default:
    52  			panic(fmt.Sprintf("invalid ServiceElement type: %T", decl))
    53  		}
    54  	}
    55  
    56  	return &ServiceNode{
    57  		compositeNode: compositeNode{
    58  			children: children,
    59  		},
    60  		Keyword:    keyword,
    61  		Name:       name,
    62  		OpenBrace:  openBrace,
    63  		Decls:      decls,
    64  		CloseBrace: closeBrace,
    65  	}
    66  }
    67  
    68  // ServiceElement is an interface implemented by all AST nodes that can
    69  // appear in the body of a service declaration.
    70  type ServiceElement interface {
    71  	Node
    72  	serviceElement()
    73  }
    74  
    75  var _ ServiceElement = (*OptionNode)(nil)
    76  var _ ServiceElement = (*RPCNode)(nil)
    77  var _ ServiceElement = (*EmptyDeclNode)(nil)
    78  
    79  // RPCDeclNode is a placeholder interface for AST nodes that represent RPC
    80  // declarations. This allows NoSourceNode to be used in place of *RPCNode
    81  // for some usages.
    82  type RPCDeclNode interface {
    83  	Node
    84  	GetName() Node
    85  	GetInputType() Node
    86  	GetOutputType() Node
    87  }
    88  
    89  var _ RPCDeclNode = (*RPCNode)(nil)
    90  var _ RPCDeclNode = NoSourceNode{}
    91  
    92  // RPCNode represents an RPC declaration. Example:
    93  //
    94  //  rpc Foo (Bar) returns (Baz);
    95  type RPCNode struct {
    96  	compositeNode
    97  	Keyword    *KeywordNode
    98  	Name       *IdentNode
    99  	Input      *RPCTypeNode
   100  	Returns    *KeywordNode
   101  	Output     *RPCTypeNode
   102  	Semicolon  *RuneNode
   103  	OpenBrace  *RuneNode
   104  	Decls      []RPCElement
   105  	CloseBrace *RuneNode
   106  }
   107  
   108  func (n *RPCNode) serviceElement() {}
   109  
   110  // NewRPCNode creates a new *RPCNode with no body. All arguments must be non-nil.
   111  //  - keyword: The token corresponding to the "rpc" keyword.
   112  //  - name: The token corresponding to the RPC's name.
   113  //  - input: The token corresponding to the RPC input message type.
   114  //  - returns: The token corresponding to the "returns" keyword that precedes the output type.
   115  //  - output: The token corresponding to the RPC output message type.
   116  //  - semicolon: The token corresponding to the ";" rune that ends the declaration.
   117  func NewRPCNode(keyword *KeywordNode, name *IdentNode, input *RPCTypeNode, returns *KeywordNode, output *RPCTypeNode, semicolon *RuneNode) *RPCNode {
   118  	if keyword == nil {
   119  		panic("keyword is nil")
   120  	}
   121  	if name == nil {
   122  		panic("name is nil")
   123  	}
   124  	if input == nil {
   125  		panic("input is nil")
   126  	}
   127  	if returns == nil {
   128  		panic("returns is nil")
   129  	}
   130  	if output == nil {
   131  		panic("output is nil")
   132  	}
   133  	if semicolon == nil {
   134  		panic("semicolon is nil")
   135  	}
   136  	children := []Node{keyword, name, input, returns, output, semicolon}
   137  	return &RPCNode{
   138  		compositeNode: compositeNode{
   139  			children: children,
   140  		},
   141  		Keyword:   keyword,
   142  		Name:      name,
   143  		Input:     input,
   144  		Returns:   returns,
   145  		Output:    output,
   146  		Semicolon: semicolon,
   147  	}
   148  }
   149  
   150  // NewRPCNodeWithBody creates a new *RPCNode that includes a body (and possibly
   151  // options). All arguments must be non-nil.
   152  //  - keyword: The token corresponding to the "rpc" keyword.
   153  //  - name: The token corresponding to the RPC's name.
   154  //  - input: The token corresponding to the RPC input message type.
   155  //  - returns: The token corresponding to the "returns" keyword that precedes the output type.
   156  //  - output: The token corresponding to the RPC output message type.
   157  //  - openBrace: The token corresponding to the "{" rune that starts the body.
   158  //  - decls: All declarations inside the RPC body.
   159  //  - closeBrace: The token corresponding to the "}" rune that ends the body.
   160  func NewRPCNodeWithBody(keyword *KeywordNode, name *IdentNode, input *RPCTypeNode, returns *KeywordNode, output *RPCTypeNode, openBrace *RuneNode, decls []RPCElement, closeBrace *RuneNode) *RPCNode {
   161  	if keyword == nil {
   162  		panic("keyword is nil")
   163  	}
   164  	if name == nil {
   165  		panic("name is nil")
   166  	}
   167  	if input == nil {
   168  		panic("input is nil")
   169  	}
   170  	if returns == nil {
   171  		panic("returns is nil")
   172  	}
   173  	if output == nil {
   174  		panic("output is nil")
   175  	}
   176  	if openBrace == nil {
   177  		panic("openBrace is nil")
   178  	}
   179  	if closeBrace == nil {
   180  		panic("closeBrace is nil")
   181  	}
   182  	children := make([]Node, 0, 7+len(decls))
   183  	children = append(children, keyword, name, input, returns, output, openBrace)
   184  	for _, decl := range decls {
   185  		children = append(children, decl)
   186  	}
   187  	children = append(children, closeBrace)
   188  
   189  	for _, decl := range decls {
   190  		switch decl := decl.(type) {
   191  		case *OptionNode, *EmptyDeclNode:
   192  		default:
   193  			panic(fmt.Sprintf("invalid RPCElement type: %T", decl))
   194  		}
   195  	}
   196  
   197  	return &RPCNode{
   198  		compositeNode: compositeNode{
   199  			children: children,
   200  		},
   201  		Keyword:    keyword,
   202  		Name:       name,
   203  		Input:      input,
   204  		Returns:    returns,
   205  		Output:     output,
   206  		OpenBrace:  openBrace,
   207  		Decls:      decls,
   208  		CloseBrace: closeBrace,
   209  	}
   210  }
   211  
   212  func (n *RPCNode) GetName() Node {
   213  	return n.Name
   214  }
   215  
   216  func (n *RPCNode) GetInputType() Node {
   217  	return n.Input.MessageType
   218  }
   219  
   220  func (n *RPCNode) GetOutputType() Node {
   221  	return n.Output.MessageType
   222  }
   223  
   224  // RPCElement is an interface implemented by all AST nodes that can
   225  // appear in the body of an rpc declaration (aka method).
   226  type RPCElement interface {
   227  	Node
   228  	methodElement()
   229  }
   230  
   231  var _ RPCElement = (*OptionNode)(nil)
   232  var _ RPCElement = (*EmptyDeclNode)(nil)
   233  
   234  // RPCTypeNode represents the declaration of a request or response type for an
   235  // RPC. Example:
   236  //
   237  //  (stream foo.Bar)
   238  type RPCTypeNode struct {
   239  	compositeNode
   240  	OpenParen   *RuneNode
   241  	Stream      *KeywordNode
   242  	MessageType IdentValueNode
   243  	CloseParen  *RuneNode
   244  }
   245  
   246  // NewRPCTypeNode creates a new *RPCTypeNode. All arguments must be non-nil
   247  // except stream, which may be nil.
   248  //  - openParen: The token corresponding to the "(" rune that starts the declaration.
   249  //  - stream: The token corresponding to the "stream" keyword or nil if not present.
   250  //  - msgType: The token corresponding to the message type's name.
   251  //  - closeParen: The token corresponding to the ")" rune that ends the declaration.
   252  func NewRPCTypeNode(openParen *RuneNode, stream *KeywordNode, msgType IdentValueNode, closeParen *RuneNode) *RPCTypeNode {
   253  	if openParen == nil {
   254  		panic("openParen is nil")
   255  	}
   256  	if msgType == nil {
   257  		panic("msgType is nil")
   258  	}
   259  	if closeParen == nil {
   260  		panic("closeParen is nil")
   261  	}
   262  	var children []Node
   263  	if stream != nil {
   264  		children = []Node{openParen, stream, msgType, closeParen}
   265  	} else {
   266  		children = []Node{openParen, msgType, closeParen}
   267  	}
   268  
   269  	return &RPCTypeNode{
   270  		compositeNode: compositeNode{
   271  			children: children,
   272  		},
   273  		OpenParen:   openParen,
   274  		Stream:      stream,
   275  		MessageType: msgType,
   276  		CloseParen:  closeParen,
   277  	}
   278  }