github.com/jhump/protoreflect@v1.16.0/desc/protoparse/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 GetInputType() Node 85 GetOutputType() Node 86 } 87 88 var _ RPCDeclNode = (*RPCNode)(nil) 89 var _ RPCDeclNode = NoSourceNode{} 90 91 // RPCNode represents an RPC declaration. Example: 92 // 93 // rpc Foo (Bar) returns (Baz); 94 type RPCNode struct { 95 compositeNode 96 Keyword *KeywordNode 97 Name *IdentNode 98 Input *RPCTypeNode 99 Returns *KeywordNode 100 Output *RPCTypeNode 101 Semicolon *RuneNode 102 OpenBrace *RuneNode 103 Decls []RPCElement 104 CloseBrace *RuneNode 105 } 106 107 func (n *RPCNode) serviceElement() {} 108 109 // NewRPCNode creates a new *RPCNode with no body. All arguments must be non-nil. 110 // - keyword: The token corresponding to the "rpc" keyword. 111 // - name: The token corresponding to the RPC's name. 112 // - input: The token corresponding to the RPC input message type. 113 // - returns: The token corresponding to the "returns" keyword that precedes the output type. 114 // - output: The token corresponding to the RPC output message type. 115 // - semicolon: The token corresponding to the ";" rune that ends the declaration. 116 func NewRPCNode(keyword *KeywordNode, name *IdentNode, input *RPCTypeNode, returns *KeywordNode, output *RPCTypeNode, semicolon *RuneNode) *RPCNode { 117 if keyword == nil { 118 panic("keyword is nil") 119 } 120 if name == nil { 121 panic("name is nil") 122 } 123 if input == nil { 124 panic("input is nil") 125 } 126 if returns == nil { 127 panic("returns is nil") 128 } 129 if output == nil { 130 panic("output is nil") 131 } 132 if semicolon == nil { 133 panic("semicolon is nil") 134 } 135 children := []Node{keyword, name, input, returns, output, semicolon} 136 return &RPCNode{ 137 compositeNode: compositeNode{ 138 children: children, 139 }, 140 Keyword: keyword, 141 Name: name, 142 Input: input, 143 Returns: returns, 144 Output: output, 145 Semicolon: semicolon, 146 } 147 } 148 149 // NewRPCNodeWithBody creates a new *RPCNode that includes a body (and possibly 150 // options). All arguments must be non-nil. 151 // - keyword: The token corresponding to the "rpc" keyword. 152 // - name: The token corresponding to the RPC's name. 153 // - input: The token corresponding to the RPC input message type. 154 // - returns: The token corresponding to the "returns" keyword that precedes the output type. 155 // - output: The token corresponding to the RPC output message type. 156 // - openBrace: The token corresponding to the "{" rune that starts the body. 157 // - decls: All declarations inside the RPC body. 158 // - closeBrace: The token corresponding to the "}" rune that ends the body. 159 func NewRPCNodeWithBody(keyword *KeywordNode, name *IdentNode, input *RPCTypeNode, returns *KeywordNode, output *RPCTypeNode, openBrace *RuneNode, decls []RPCElement, closeBrace *RuneNode) *RPCNode { 160 if keyword == nil { 161 panic("keyword is nil") 162 } 163 if name == nil { 164 panic("name is nil") 165 } 166 if input == nil { 167 panic("input is nil") 168 } 169 if returns == nil { 170 panic("returns is nil") 171 } 172 if output == nil { 173 panic("output is nil") 174 } 175 if openBrace == nil { 176 panic("openBrace is nil") 177 } 178 if closeBrace == nil { 179 panic("closeBrace is nil") 180 } 181 children := make([]Node, 0, 7+len(decls)) 182 children = append(children, keyword, name, input, returns, output, openBrace) 183 for _, decl := range decls { 184 children = append(children, decl) 185 } 186 children = append(children, closeBrace) 187 188 for _, decl := range decls { 189 switch decl := decl.(type) { 190 case *OptionNode, *EmptyDeclNode: 191 default: 192 panic(fmt.Sprintf("invalid RPCElement type: %T", decl)) 193 } 194 } 195 196 return &RPCNode{ 197 compositeNode: compositeNode{ 198 children: children, 199 }, 200 Keyword: keyword, 201 Name: name, 202 Input: input, 203 Returns: returns, 204 Output: output, 205 OpenBrace: openBrace, 206 Decls: decls, 207 CloseBrace: closeBrace, 208 } 209 } 210 211 func (n *RPCNode) GetInputType() Node { 212 return n.Input.MessageType 213 } 214 215 func (n *RPCNode) GetOutputType() Node { 216 return n.Output.MessageType 217 } 218 219 // RPCElement is an interface implemented by all AST nodes that can 220 // appear in the body of an rpc declaration (aka method). 221 type RPCElement interface { 222 Node 223 methodElement() 224 } 225 226 var _ RPCElement = (*OptionNode)(nil) 227 var _ RPCElement = (*EmptyDeclNode)(nil) 228 229 // RPCTypeNode represents the declaration of a request or response type for an 230 // RPC. Example: 231 // 232 // (stream foo.Bar) 233 type RPCTypeNode struct { 234 compositeNode 235 OpenParen *RuneNode 236 Stream *KeywordNode 237 MessageType IdentValueNode 238 CloseParen *RuneNode 239 } 240 241 // NewRPCTypeNode creates a new *RPCTypeNode. All arguments must be non-nil 242 // except stream, which may be nil. 243 // - openParen: The token corresponding to the "(" rune that starts the declaration. 244 // - stream: The token corresponding to the "stream" keyword or nil if not present. 245 // - msgType: The token corresponding to the message type's name. 246 // - closeParen: The token corresponding to the ")" rune that ends the declaration. 247 func NewRPCTypeNode(openParen *RuneNode, stream *KeywordNode, msgType IdentValueNode, closeParen *RuneNode) *RPCTypeNode { 248 if openParen == nil { 249 panic("openParen is nil") 250 } 251 if msgType == nil { 252 panic("msgType is nil") 253 } 254 if closeParen == nil { 255 panic("closeParen is nil") 256 } 257 var children []Node 258 if stream != nil { 259 children = []Node{openParen, stream, msgType, closeParen} 260 } else { 261 children = []Node{openParen, msgType, closeParen} 262 } 263 264 return &RPCTypeNode{ 265 compositeNode: compositeNode{ 266 children: children, 267 }, 268 OpenParen: openParen, 269 Stream: stream, 270 MessageType: msgType, 271 CloseParen: closeParen, 272 } 273 }