github.com/AngusLu/go-swagger@v0.28.0/codescan/operations.go (about) 1 package codescan 2 3 import ( 4 "fmt" 5 "go/ast" 6 "regexp" 7 "strings" 8 9 "github.com/go-openapi/spec" 10 ) 11 12 type operationsBuilder struct { 13 ctx *scanCtx 14 path parsedPathContent 15 operations map[string]*spec.Operation 16 } 17 18 func (o *operationsBuilder) Build(tgt *spec.Paths) error { 19 pthObj := tgt.Paths[o.path.Path] 20 21 op := setPathOperation( 22 o.path.Method, o.path.ID, 23 &pthObj, o.operations[o.path.ID]) 24 25 op.Tags = o.path.Tags 26 27 sp := new(yamlSpecScanner) 28 sp.setTitle = func(lines []string) { op.Summary = joinDropLast(lines) } 29 sp.setDescription = func(lines []string) { op.Description = joinDropLast(lines) } 30 31 if err := sp.Parse(o.path.Remaining); err != nil { 32 return fmt.Errorf("operation (%s): %v", op.ID, err) 33 } 34 if err := sp.UnmarshalSpec(op.UnmarshalJSON); err != nil { 35 return fmt.Errorf("operation (%s): %v", op.ID, err) 36 } 37 38 if tgt.Paths == nil { 39 tgt.Paths = make(map[string]spec.PathItem) 40 } 41 42 tgt.Paths[o.path.Path] = pthObj 43 return nil 44 } 45 46 type parsedPathContent struct { 47 Method, Path, ID string 48 Tags []string 49 Remaining *ast.CommentGroup 50 } 51 52 func parsePathAnnotation(annotation *regexp.Regexp, lines []*ast.Comment) (cnt parsedPathContent) { 53 var justMatched bool 54 55 for _, cmt := range lines { 56 txt := cmt.Text 57 for _, line := range strings.Split(txt, "\n") { 58 matches := annotation.FindStringSubmatch(line) 59 if len(matches) > 3 { 60 cnt.Method, cnt.Path, cnt.ID = matches[1], matches[2], matches[len(matches)-1] 61 cnt.Tags = rxSpace.Split(matches[3], -1) 62 if len(matches[3]) == 0 { 63 cnt.Tags = nil 64 } 65 justMatched = true 66 } else if cnt.Method != "" { 67 if cnt.Remaining == nil { 68 cnt.Remaining = new(ast.CommentGroup) 69 } 70 if !justMatched || strings.TrimSpace(rxStripComments.ReplaceAllString(line, "")) != "" { 71 cc := new(ast.Comment) 72 cc.Slash = cmt.Slash 73 cc.Text = line 74 cnt.Remaining.List = append(cnt.Remaining.List, cc) 75 justMatched = false 76 } 77 } 78 } 79 } 80 81 return 82 } 83 84 func setPathOperation(method, id string, pthObj *spec.PathItem, op *spec.Operation) *spec.Operation { 85 if op == nil { 86 op = new(spec.Operation) 87 op.ID = id 88 } 89 90 switch strings.ToUpper(method) { 91 case "GET": 92 if pthObj.Get != nil { 93 if id == pthObj.Get.ID { 94 op = pthObj.Get 95 } else { 96 pthObj.Get = op 97 } 98 } else { 99 pthObj.Get = op 100 } 101 102 case "POST": 103 if pthObj.Post != nil { 104 if id == pthObj.Post.ID { 105 op = pthObj.Post 106 } else { 107 pthObj.Post = op 108 } 109 } else { 110 pthObj.Post = op 111 } 112 113 case "PUT": 114 if pthObj.Put != nil { 115 if id == pthObj.Put.ID { 116 op = pthObj.Put 117 } else { 118 pthObj.Put = op 119 } 120 } else { 121 pthObj.Put = op 122 } 123 124 case "PATCH": 125 if pthObj.Patch != nil { 126 if id == pthObj.Patch.ID { 127 op = pthObj.Patch 128 } else { 129 pthObj.Patch = op 130 } 131 } else { 132 pthObj.Patch = op 133 } 134 135 case "HEAD": 136 if pthObj.Head != nil { 137 if id == pthObj.Head.ID { 138 op = pthObj.Head 139 } else { 140 pthObj.Head = op 141 } 142 } else { 143 pthObj.Head = op 144 } 145 146 case "DELETE": 147 if pthObj.Delete != nil { 148 if id == pthObj.Delete.ID { 149 op = pthObj.Delete 150 } else { 151 pthObj.Delete = op 152 } 153 } else { 154 pthObj.Delete = op 155 } 156 157 case "OPTIONS": 158 if pthObj.Options != nil { 159 if id == pthObj.Options.ID { 160 op = pthObj.Options 161 } else { 162 pthObj.Options = op 163 } 164 } else { 165 pthObj.Options = op 166 } 167 } 168 169 return op 170 }