github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/hack/plugins/formatter.go (about) 1 /* 2 Part of this file is copied from https://github.com/vektah/gqlparser/blob/master/formatter/formatter.go. 3 Below you can find its licence. 4 5 Copyright (c) 2018 Adam Scarr 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in all 15 copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 SOFTWARE. 24 */ 25 package plugins 26 27 import ( 28 "fmt" 29 "io" 30 "sort" 31 "strings" 32 33 "github.com/vektah/gqlparser/v2/ast" 34 ) 35 36 // Formatter missing godoc 37 type Formatter interface { 38 FormatSchema(schema *ast.Schema) 39 } 40 41 // NewFormatter missing godoc 42 func NewFormatter(w io.Writer) Formatter { 43 return &formatter{writer: w} 44 } 45 46 type formatter struct { 47 writer io.Writer 48 49 indent int 50 emitBuiltin bool 51 52 padNext bool 53 lineHead bool 54 } 55 56 func (f *formatter) writeString(s string) { 57 _, err := f.writer.Write([]byte(s)) 58 if err != nil { 59 panic(err) 60 } 61 } 62 63 func (f *formatter) WriteIndent() *formatter { 64 if f.lineHead { 65 f.writeString(strings.Repeat("\t", f.indent)) 66 } 67 f.lineHead = false 68 f.padNext = false 69 70 return f 71 } 72 73 // WriteNewline missing godoc 74 func (f *formatter) WriteNewline() *formatter { 75 f.writeString("\n") 76 f.lineHead = true 77 f.padNext = false 78 79 return f 80 } 81 82 // WriteWord missing godoc 83 func (f *formatter) WriteWord(word string) *formatter { 84 if f.lineHead { 85 f.WriteIndent() 86 } 87 if f.padNext { 88 f.writeString(" ") 89 } 90 f.writeString(strings.TrimSpace(word)) 91 f.padNext = true 92 93 return f 94 } 95 96 // WriteString missing godoc 97 func (f *formatter) WriteString(s string) *formatter { 98 if f.lineHead { 99 f.WriteIndent() 100 } 101 if f.padNext { 102 f.writeString(" ") 103 } 104 f.writeString(s) 105 f.padNext = false 106 107 return f 108 } 109 110 // WriteDescription missing godoc 111 func (f *formatter) WriteDescription(s string) *formatter { 112 if s == "" { 113 return f 114 } 115 116 f.WriteString(`"""`).WriteNewline() 117 118 ss := strings.Split(s, "\n") 119 for _, s := range ss { 120 f.WriteString(s).WriteNewline() 121 } 122 123 f.WriteString(`"""`).WriteNewline() 124 125 return f 126 } 127 128 // IncrementIndent missing godoc 129 func (f *formatter) IncrementIndent() { 130 f.indent++ 131 } 132 133 // DecrementIndent missing godoc 134 func (f *formatter) DecrementIndent() { 135 f.indent-- 136 } 137 138 // NoPadding missing godoc 139 func (f *formatter) NoPadding() *formatter { 140 f.padNext = false 141 142 return f 143 } 144 145 // NeedPadding missing godoc 146 func (f *formatter) NeedPadding() *formatter { 147 f.padNext = true 148 149 return f 150 } 151 152 // FormatSchema missing godoc 153 func (f *formatter) FormatSchema(schema *ast.Schema) { 154 if schema == nil { 155 return 156 } 157 158 var inSchema bool 159 startSchema := func() { 160 if !inSchema { 161 inSchema = true 162 163 f.WriteWord("schema").WriteString("{").WriteNewline() 164 f.IncrementIndent() 165 } 166 } 167 if schema.Query != nil && schema.Query.Name != "Query" { 168 startSchema() 169 f.WriteWord("query").NoPadding().WriteString(":").NeedPadding() 170 f.WriteWord(schema.Query.Name).WriteNewline() 171 } 172 if schema.Mutation != nil && schema.Mutation.Name != "Mutation" { 173 startSchema() 174 f.WriteWord("mutation").NoPadding().WriteString(":").NeedPadding() 175 f.WriteWord(schema.Mutation.Name).WriteNewline() 176 } 177 if schema.Subscription != nil && schema.Subscription.Name != "Subscription" { 178 startSchema() 179 f.WriteWord("subscription").NoPadding().WriteString(":").NeedPadding() 180 f.WriteWord(schema.Subscription.Name).WriteNewline() 181 } 182 if inSchema { 183 f.DecrementIndent() 184 f.WriteString("}").WriteNewline() 185 } 186 187 directiveNames := make([]string, 0, len(schema.Directives)) 188 for name := range schema.Directives { 189 directiveNames = append(directiveNames, name) 190 } 191 sort.Strings(directiveNames) 192 for _, name := range directiveNames { 193 f.FormatDirectiveDefinition(schema.Directives[name]) 194 } 195 196 var dl OrderedDefinitionList 197 for _, v := range schema.Types { 198 dl = append(dl, *v) 199 } 200 201 sort.Sort(dl) 202 203 for _, t := range dl { 204 f.FormatDefinition(&t, false) 205 } 206 } 207 208 // FormatFieldList missing godoc 209 func (f *formatter) FormatFieldList(fieldList ast.FieldList) { 210 if len(fieldList) == 0 { 211 return 212 } 213 214 f.WriteString("{").WriteNewline() 215 f.IncrementIndent() 216 217 for _, field := range fieldList { 218 f.FormatFieldDefinition(field) 219 } 220 221 f.DecrementIndent() 222 f.WriteString("}") 223 } 224 225 // FormatFieldDefinition missing godoc 226 func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) { 227 if !f.emitBuiltin && strings.HasPrefix(field.Name, "__") { 228 return 229 } 230 231 f.WriteDescription(field.Description) 232 233 f.WriteWord(field.Name).NoPadding() 234 f.FormatArgumentDefinitionList(field.Arguments) 235 f.NoPadding().WriteString(":").NeedPadding() 236 f.FormatType(field.Type) 237 238 if field.DefaultValue != nil { 239 f.WriteWord("=") 240 f.FormatValue(field.DefaultValue) 241 } 242 243 f.FormatDirectiveList(field.Directives) 244 245 f.WriteNewline() 246 } 247 248 // FormatArgumentDefinitionList missing godoc 249 func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionList) { 250 if len(lists) == 0 { 251 return 252 } 253 254 f.WriteString("(") 255 for idx, arg := range lists { 256 f.FormatArgumentDefinition(arg) 257 258 if idx != len(lists)-1 { 259 f.NoPadding().WriteWord(",") 260 } 261 } 262 f.NoPadding().WriteString(")").NeedPadding() 263 } 264 265 // FormatArgumentDefinition missing godoc 266 func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) { 267 f.WriteDescription(def.Description) 268 269 f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding() 270 f.FormatType(def.Type) 271 272 if def.DefaultValue != nil { 273 f.WriteWord("=") 274 f.FormatValue(def.DefaultValue) 275 } 276 277 f.FormatDirectiveList(def.Directives) 278 } 279 280 // FormatDirectiveLocation missing godoc 281 func (f *formatter) FormatDirectiveLocation(location ast.DirectiveLocation) { 282 f.WriteWord(string(location)) 283 } 284 285 // FormatDirectiveDefinitionList missing godoc 286 func (f *formatter) FormatDirectiveDefinitionList(lists ast.DirectiveDefinitionList) { 287 if len(lists) == 0 { 288 return 289 } 290 291 for _, dec := range lists { 292 f.FormatDirectiveDefinition(dec) 293 } 294 } 295 296 // FormatDirectiveDefinition missing godoc 297 func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) { 298 if !f.emitBuiltin { 299 if def.Position.Src.BuiltIn { 300 return 301 } 302 } 303 304 f.WriteDescription(def.Description) 305 f.WriteWord("directive").WriteString("@").WriteWord(def.Name) 306 307 if len(def.Arguments) != 0 { 308 f.NoPadding() 309 f.FormatArgumentDefinitionList(def.Arguments) 310 } 311 312 if len(def.Locations) != 0 { 313 f.WriteWord("on") 314 315 for idx, dirLoc := range def.Locations { 316 f.FormatDirectiveLocation(dirLoc) 317 318 if idx != len(def.Locations)-1 { 319 f.WriteWord("|") 320 } 321 } 322 } 323 324 f.WriteNewline() 325 } 326 327 // FormatDefinition missing godoc 328 func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) { 329 if !f.emitBuiltin && def.BuiltIn { 330 return 331 } 332 333 f.WriteDescription(def.Description) 334 335 if extend { 336 f.WriteWord("extend") 337 } 338 339 switch def.Kind { 340 case ast.Scalar: 341 f.WriteWord("scalar").WriteWord(def.Name) 342 343 case ast.Object: 344 f.WriteWord("type").WriteWord(def.Name) 345 346 case ast.Interface: 347 f.WriteWord("interface").WriteWord(def.Name) 348 349 case ast.Union: 350 f.WriteWord("union").WriteWord(def.Name) 351 352 case ast.Enum: 353 f.WriteWord("enum").WriteWord(def.Name) 354 355 case ast.InputObject: 356 f.WriteWord("input").WriteWord(def.Name) 357 } 358 359 f.FormatDirectiveList(def.Directives) 360 361 if len(def.Types) != 0 { 362 f.WriteWord("=").WriteWord(strings.Join(def.Types, " | ")) 363 } 364 365 if len(def.Interfaces) != 0 { 366 f.WriteWord("implements").WriteWord(strings.Join(def.Interfaces, ", ")) 367 } 368 369 f.FormatFieldList(def.Fields) 370 371 f.FormatEnumValueList(def.EnumValues) 372 373 f.WriteNewline() 374 f.WriteNewline() 375 } 376 377 // FormatEnumValueList missing godoc 378 func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) { 379 if len(lists) == 0 { 380 return 381 } 382 383 f.WriteString("{").WriteNewline() 384 f.IncrementIndent() 385 386 for _, v := range lists { 387 f.FormatEnumValueDefinition(v) 388 } 389 390 f.DecrementIndent() 391 f.WriteString("}") 392 } 393 394 // FormatEnumValueDefinition missing godoc 395 func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) { 396 f.WriteDescription(def.Description) 397 398 f.WriteWord(def.Name) 399 f.FormatDirectiveList(def.Directives) 400 401 f.WriteNewline() 402 } 403 404 // FormatDirectiveList missing godoc 405 func (f *formatter) FormatDirectiveList(lists ast.DirectiveList) { 406 if len(lists) == 0 { 407 return 408 } 409 410 for _, dir := range lists { 411 f.FormatDirective(dir) 412 } 413 } 414 415 // FormatDirective missing godoc 416 func (f *formatter) FormatDirective(dir *ast.Directive) { 417 f.WriteString("@").WriteWord(dir.Name) 418 f.FormatArgumentList(dir.Arguments) 419 } 420 421 // FormatArgumentList missing godoc 422 func (f *formatter) FormatArgumentList(lists ast.ArgumentList) { 423 if len(lists) == 0 { 424 return 425 } 426 f.NoPadding().WriteString("(") 427 for idx, arg := range lists { 428 f.FormatArgument(arg) 429 430 if idx != len(lists)-1 { 431 f.NoPadding().WriteWord(",") 432 } 433 } 434 f.WriteString(")").NeedPadding() 435 } 436 437 // FormatArgument missing godoc 438 func (f *formatter) FormatArgument(arg *ast.Argument) { 439 f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding() 440 f.WriteString(arg.Value.String()) 441 } 442 443 // FormatSelectionSet missing godoc 444 func (f *formatter) FormatSelectionSet(sets ast.SelectionSet) { 445 if len(sets) == 0 { 446 return 447 } 448 449 f.WriteString("{").WriteNewline() 450 f.IncrementIndent() 451 452 for _, sel := range sets { 453 f.FormatSelection(sel) 454 } 455 456 f.DecrementIndent() 457 f.WriteString("}") 458 } 459 460 // FormatSelection missing godoc 461 func (f *formatter) FormatSelection(selection ast.Selection) { 462 switch v := selection.(type) { 463 case *ast.Field: 464 f.FormatField(v) 465 466 case *ast.FragmentSpread: 467 f.FormatFragmentSpread(v) 468 469 case *ast.InlineFragment: 470 f.FormatInlineFragment(v) 471 472 default: 473 panic(fmt.Errorf("unknown Selection type: %T", selection)) 474 } 475 476 f.WriteNewline() 477 } 478 479 // FormatField missing godoc 480 func (f *formatter) FormatField(field *ast.Field) { 481 if field.Alias != "" && field.Alias != field.Name { 482 f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding() 483 } 484 f.WriteWord(field.Name) 485 486 if len(field.Arguments) != 0 { 487 f.NoPadding() 488 f.FormatArgumentList(field.Arguments) 489 f.NeedPadding() 490 } 491 492 f.FormatDirectiveList(field.Directives) 493 494 f.FormatSelectionSet(field.SelectionSet) 495 } 496 497 // FormatFragmentSpread missing godoc 498 func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) { 499 f.WriteWord("...").WriteWord(spread.Name) 500 501 f.FormatDirectiveList(spread.Directives) 502 } 503 504 // FormatInlineFragment missing godoc 505 func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) { 506 f.WriteWord("...") 507 if inline.TypeCondition != "" { 508 f.WriteWord("on").WriteWord(inline.TypeCondition) 509 } 510 511 f.FormatDirectiveList(inline.Directives) 512 513 f.FormatSelectionSet(inline.SelectionSet) 514 } 515 516 // FormatType missing godoc 517 func (f *formatter) FormatType(t *ast.Type) { 518 f.WriteWord(t.String()) 519 } 520 521 // FormatValue missing godoc 522 func (f *formatter) FormatValue(value *ast.Value) { 523 f.WriteString(value.String()) 524 }