Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions integration_test/test_data/handler/restaurants.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
// @Param filter query model.Filter false "In json format"
// @Param extra.field query string false "extra field"
// @Success 200 {object} model.GetRestaurantsResponse
// @OperationId GetRestaurants
// @Router /restaurants [get]
func GetRestaurants() {
}
Expand All @@ -29,6 +30,7 @@ func GetRestaurants() {
// @failure 400 {object} aliasValidationError
// @failure 404 {object} ErrResponse
// @failure 500 {object} ErrResponse
// @OperationId GetPogs
// @route assortment/planogram [get]
func GetPogs() {}

Expand Down
2 changes: 1 addition & 1 deletion integration_test/test_data/handler/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package handler
// @Header model.Headers
// @Param request body model.CreateUserRequest true "Create User Request"
// @Success 200 {object} model.CreateUserResponse
// @OperationId CreateUser
// @Router /user [post]
func CreateUser() {
}

68 changes: 68 additions & 0 deletions integration_test/test_data/oas.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ openapi: 3.0.0
paths:
/restaurants:
get:
operationId: GetRestaurants
description: ' Returns a list of restaurants based on filter request'
parameters:
- $ref: '#/components/parameters/Client-Version'
Expand Down Expand Up @@ -197,6 +198,7 @@ paths:
summary: Get restaurants list
/user:
post:
operationId: CreateUser
description: ' Creates & Returns an User based on the request'
parameters:
- $ref: '#/components/parameters/Client-Version'
Expand All @@ -216,6 +218,72 @@ paths:
$ref: '#/components/schemas/CreateUserResponse'
description: ""
summary: Create User
/assortment/planogram:
get:
operationId: GetPogs
description: Returns planogram based on query params
parameters:
- name: id
in: query
required: true
description: Use as filter.id! Planogram dbKey [comma separated list]
schema:
type: string
- name: locationId
in: query
required: true
description: Use as filter.locationId! Location ID
schema:
type: string
- name: include
in: query
required: false
description: Includes. Can be: position, fixture, liveFlrFixture
schema:
type: string
- name: commodity
in: query
required: false
description: Use as filter.commodity! Commodity
schema:
type: string
- name: commodityGroup
in: query
required: false
description: Use as filter.commodityGroup! Commodity Group
schema:
type: string
- name: isDigitalScreen
in: query
required: false
description: Use as filter.isDigitalScreen! IsDigitalScreen. Can be: true, false
schema:
type: string
responses:
"200":
description: ""
content:
application/json:
schema:
$ref: '#/components/schemas/GetPogsResponse'
"400":
description: ""
content:
application/json:
schema:
$ref: '#/components/schemas/aliasValidationError'
"404":
description: ""
content:
application/json:
schema:
$ref: '#/components/schemas/ErrResponse'
"500":
description: ""
content:
application/json:
schema:
$ref: '#/components/schemas/ErrResponse'
security:
- AuthorizationHeader:
- read
Expand Down
3 changes: 3 additions & 0 deletions integration_test/test_data/spec/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
},
"summary": "Get restaurants list",
"description": " Returns a list of restaurants based on filter request",
"operationId": "GetRestaurants",
"parameters": [
{
"$ref": "#/components/parameters/Client-Version"
Expand Down Expand Up @@ -142,6 +143,7 @@
},
"summary": "Create User",
"description": " Creates \u0026 Returns an User based on the request",
"operationId": "CreateUser",
"parameters": [
{
"$ref": "#/components/parameters/Client-Version"
Expand Down Expand Up @@ -211,6 +213,7 @@
},
"summary": "Get Planograms.",
"description": " Returns planogram based on query params.",
"operationId": "GetPogs",
"parameters": [
{
"name": "id",
Expand Down
3 changes: 3 additions & 0 deletions integration_test/test_data/spec/expected_with_pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
},
"summary": "Get restaurants list",
"description": " Returns a list of restaurants based on filter request",
"operationId": "GetRestaurants",
"parameters": [
{
"$ref": "#/components/parameters/Client-Version"
Expand Down Expand Up @@ -142,6 +143,7 @@
},
"summary": "Create User",
"description": " Creates \u0026 Returns an User based on the request",
"operationId": "CreateUser",
"parameters": [
{
"$ref": "#/components/parameters/Client-Version"
Expand Down Expand Up @@ -211,6 +213,7 @@
},
"summary": "Get Planograms.",
"description": " Returns planogram based on query params.",
"operationId": "GetPogs",
"parameters": [
{
"name": "id",
Expand Down
3 changes: 1 addition & 2 deletions openApi3Schema/oas.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,11 @@ type OperationObject struct {
Tags []string `json:"tags,omitempty"`
Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"`
OperationID string `json:"operationId,omitempty"`
Parameters []ParameterObject `json:"parameters,omitempty"`
RequestBody *RequestBodyObject `json:"requestBody,omitempty"`

// Tags
// ExternalDocs
// OperationID
// Callbacks
// Deprecated
// Security
Expand Down
43 changes: 33 additions & 10 deletions parser/operations/parser.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
package operations

import (
. "github.com/parvez3019/go-swagger3/openApi3Schema"
"github.com/parvez3019/go-swagger3/parser/model"
"github.com/parvez3019/go-swagger3/parser/schema"
"fmt"
"go/ast"
"strings"

"github.com/parvez3019/go-swagger3/openApi3Schema"
"github.com/parvez3019/go-swagger3/parser/model"
"github.com/parvez3019/go-swagger3/parser/schema"
)

type Parser interface {
Parse(pkgPath, pkgName string, astComments []*ast.Comment) error
}

type parser struct {
OpenAPI *OpenAPIObject
OpenAPI *openApi3Schema.OpenAPIObject

model.Utils
schema.Parser
usedOperationIds map[string]struct{} // Track used operation IDs
}

func NewParser(utils model.Utils, api *OpenAPIObject, schemaParser schema.Parser) Parser {
func NewParser(utils model.Utils, api *openApi3Schema.OpenAPIObject, schemaParser schema.Parser) Parser {
return &parser{
Utils: utils,
OpenAPI: api,
Parser: schemaParser,
Utils: utils,
OpenAPI: api,
Parser: schemaParser,
usedOperationIds: make(map[string]struct{}),
}
}

func (p *parser) Parse(pkgPath, pkgName string, astComments []*ast.Comment) error {
operation := &OperationObject{Responses: map[string]*ResponseObject{}}
operation := &openApi3Schema.OperationObject{Responses: map[string]*openApi3Schema.ResponseObject{}}
if !strings.HasPrefix(pkgPath, p.ModulePath) || (p.HandlerPath != "" && !strings.HasPrefix(pkgPath, p.HandlerPath)) {
return nil
}
Expand All @@ -45,7 +49,20 @@ func (p *parser) Parse(pkgPath, pkgName string, astComments []*ast.Comment) erro
return nil
}

func (p *parser) parseOperationFromComment(pkgPath string, pkgName string, comment string, operation *OperationObject) error {
// validateOperationID checks if an operation ID is unique and registers it if it is.
// Returns an error if the operation ID is already used.
func (p *parser) validateOperationID(operationID string) error {
if operationID == "" {
return nil
}
if _, exists := p.usedOperationIds[operationID]; exists {
return fmt.Errorf("operation ID '%s' is not unique", operationID)
}
p.usedOperationIds[operationID] = struct{}{}
return nil
}

func (p *parser) parseOperationFromComment(pkgPath string, pkgName string, comment string, operation *openApi3Schema.OperationObject) error {
attribute := strings.Fields(comment)[0]
switch strings.ToLower(attribute) {
case "@title":
Expand All @@ -62,6 +79,12 @@ func (p *parser) parseOperationFromComment(pkgPath string, pkgName string, comme
p.parseResourceAndTag(comment, attribute, operation)
case "@route", "@router":
return p.parseRouteComment(operation, comment)
case "@operationid":
operationID := strings.TrimSpace(comment[len(attribute):])
if err := p.validateOperationID(operationID); err != nil {
return err
}
operation.OperationID = operationID
}
return nil
}