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
1 change: 1 addition & 0 deletions bin/configs/go-experimental-go-petstore-oas2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-e
templateDir: modules/openapi-generator/src/main/resources/go-experimental
additionalProperties:
packageName: petstore
generateInterfaces: true
1 change: 1 addition & 0 deletions bin/configs/go-experimental-go-petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ additionalProperties:
enumClassPrefix: "true"
packageName: petstore
disallowAdditionalPropertiesIfNotPresent: false
generateInterfaces: true
1 change: 1 addition & 0 deletions bin/configs/go-petstore-withXml.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ additionalProperties:
packageName: petstore
withXml: "true"
withGoCodegenComment: "true"
generateInterfaces: true
1 change: 1 addition & 0 deletions docs/generators/go-experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ sidebar_label: go-experimental
| ------ | ----------- | ------ | ------- |
|disallowAdditionalPropertiesIfNotPresent|Specify the behavior when the 'additionalProperties' keyword is not present in the OAS document. If false: the 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications. If true: when the 'additionalProperties' keyword is not present in a schema, the value of 'additionalProperties' is set to false, i.e. no additional properties are allowed. Note: this mode is not compliant with the JSON schema specification. This is the original openapi-generator behavior.This setting is currently ignored for OAS 2.0 documents: 1) When the 'additionalProperties' keyword is not present in a 2.0 schema, additional properties are NOT allowed. 2) Boolean values of the 'additionalProperties' keyword are ignored. It's as if additional properties are NOT allowed.Note: the root cause are issues #1369 and #1371, which must be resolved in the swagger-parser project.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>when the 'additionalProperties' keyword is not present in a schema, the value of 'additionalProperties' is automatically set to false, i.e. no additional properties are allowed. Note: this mode is not compliant with the JSON schema specification. This is the original openapi-generator behavior.</dd></dl>|true|
|enumClassPrefix|Prefix enum with class name| |false|
|generateInterfaces|Generate interfaces for api classes| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|isGoSubmodule|whether the generated Go module is a submodule| |false|
|packageName|Go package name (convention: lowercase).| |openapi|
Expand Down
1 change: 1 addition & 0 deletions docs/generators/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sidebar_label: go
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|enumClassPrefix|Prefix enum with class name| |false|
|generateInterfaces|Generate interfaces for api classes| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|isGoSubmodule|whether the generated Go module is a submodule| |false|
|packageName|Go package name (convention: lowercase).| |openapi|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
protected boolean withXml = false;
protected boolean enumClassPrefix = false;
protected boolean structPrefix = false;
protected boolean generateInterfaces = false;

protected String packageName = "openapi";
protected Set<String> numberTypes;
Expand Down Expand Up @@ -780,6 +781,10 @@ public void setStructPrefix(boolean structPrefix) {
this.structPrefix = structPrefix;
}

public void setGenerateInterfaces(boolean generateInterfaces) {
this.generateInterfaces = generateInterfaces;
}

@Override
public String toDefaultValue(Schema schema) {
if (schema.getDefault() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
public static final String WITH_XML = "withXml";
public static final String STRUCT_PREFIX = "structPrefix";
public static final String WITH_AWSV4_SIGNATURE = "withAWSV4Signature";
public static final String GENERATE_INTERFACES = "generateInterfaces";

public GoClientCodegen() {
super();
Expand Down Expand Up @@ -91,6 +92,7 @@ public GoClientCodegen() {
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC));
cliOptions.add(CliOption.newBoolean(STRUCT_PREFIX, "whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts"));
cliOptions.add(CliOption.newBoolean(WITH_AWSV4_SIGNATURE, "whether to include AWS v4 signature support"));
cliOptions.add(CliOption.newBoolean(GENERATE_INTERFACES, "Generate interfaces for api classes"));

// option to change the order of form/body parameter
cliOptions.add(CliOption.newBoolean(
Expand Down Expand Up @@ -164,6 +166,11 @@ public void processOpts() {
setStructPrefix(Boolean.parseBoolean(additionalProperties.get(STRUCT_PREFIX).toString()));
additionalProperties.put(STRUCT_PREFIX, structPrefix);
}

if (additionalProperties.containsKey(GENERATE_INTERFACES)) {
setGenerateInterfaces(Boolean.parseBoolean(additionalProperties.get(GENERATE_INTERFACES).toString()));
additionalProperties.put(GENERATE_INTERFACES, generateInterfaces);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,77 @@ import (
var (
_ _context.Context
)
{{#generateInterfaces}}

type {{classname}} interface {
{{#operation}}

/*
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
{{#notes}}
* {{{unescapedNotes}}}
{{/notes}}
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
* @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
* @return Api{{operationId}}Request
*/
{{{nickname}}}(ctx _context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) Api{{operationId}}Request

/*
* {{nickname}}Execute executes the request{{#returnType}}
* @return {{{.}}}{{/returnType}}
*/
{{nickname}}Execute(r Api{{operationId}}Request) ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error)
{{/operation}}
}
{{/generateInterfaces}}

// {{classname}}Service {{classname}} service
type {{classname}}Service service

{{#operation}}
type api{{operationId}}Request struct {
ctx _context.Context
apiService *{{classname}}Service{{#allParams}}
{{paramName}} {{^isPathParam}}*{{/isPathParam}}{{{dataType}}}{{/allParams}}
}

type Api{{operationId}}Request struct {
ctx _context.Context{{#generateInterfaces}}
ApiService {{classname}}
{{/generateInterfaces}}{{^generateInterfaces}}
ApiService *{{classname}}Service
{{/generateInterfaces}}
{{#allParams}}
{{^isPathParam}}
func (r api{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) api{{operationId}}Request {
{{paramName}} {{^isPathParam}}*{{/isPathParam}}{{{dataType}}}
{{/allParams}}
}
{{#allParams}}{{^isPathParam}}
func (r Api{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) Api{{operationId}}Request {
r.{{paramName}} = &{{paramName}}
return r
}{{/isPathParam}}{{/allParams}}

func (r Api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error) {
return r.ApiService.{{nickname}}Execute(r)
}
{{/isPathParam}}
{{/allParams}}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than requiring callers to call the new backward incompatible *Execute methods in Service directly, I've re-added the original Execute method in *Request, which just redirects the call to the Service's *Execute, in order to maintain backward compatibility.

/*
{{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
{{#notes}}
{{{unescapedNotes}}}
* {{{unescapedNotes}}}
{{/notes}}
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
* @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
@return api{{operationId}}Request
*/
func (a *{{{classname}}}Service) {{{nickname}}}(ctx _context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) api{{operationId}}Request {
return api{{operationId}}Request{
apiService: a,
* @return Api{{operationId}}Request
*/
func (a *{{{classname}}}Service) {{{nickname}}}(ctx _context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) Api{{operationId}}Request {
return Api{{operationId}}Request{
ApiService: a,
ctx: ctx,{{#pathParams}}
{{paramName}}: {{paramName}},{{/pathParams}}
}
}

/*
Execute executes the request
{{#returnType}}
@return {{{.}}}
{{/returnType}}
*/
func (r api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error) {
* Execute executes the request{{#returnType}}
* @return {{{.}}}{{/returnType}}
*/
func (a *{{{classname}}}Service) {{nickname}}Execute(r Api{{operationId}}Request) ({{#returnType}}{{{.}}}, {{/returnType}}*_nethttp.Response, error) {
var (
localVarHTTPMethod = _nethttp.Method{{httpMethod}}
localVarPostBody interface{}
Expand All @@ -69,7 +97,7 @@ func (r api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnT
{{/returnType}}
)

localBasePath, err := r.apiService.client.cfg.ServerURLWithContext(r.ctx, "{{{classname}}}Service.{{{nickname}}}")
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "{{{classname}}}Service.{{{nickname}}}")
if err != nil {
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, GenericOpenAPIError{error: err.Error()}
}
Expand Down Expand Up @@ -271,12 +299,12 @@ func (r api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnT
{{/isKeyInCookie}}
{{/isApiKey}}
{{/authMethods}}
req, err := r.apiService.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
if err != nil {
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, err
}

localVarHTTPResponse, err := r.apiService.client.callAPI(req)
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err
}
Expand All @@ -300,7 +328,7 @@ func (r api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnT
if localVarHTTPResponse.StatusCode == {{{code}}} {
{{/wildcard}}
var v {{{dataType}}}
err = r.apiService.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr.error = err.Error()
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr
Expand All @@ -320,7 +348,7 @@ func (r api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnT
}

{{#returnType}}
err = r.apiService.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr := GenericOpenAPIError{
body: localVarBody,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ type APIClient struct {
{{#apis}}
{{#operations}}

{{#generateInterfaces}}
{{classname}} {{classname}}
{{/generateInterfaces}}
{{^generateInterfaces}}
{{classname}} *{{classname}}Service
{{/generateInterfaces}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
Expand Down
44 changes: 40 additions & 4 deletions modules/openapi-generator/src/main/resources/go/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,40 @@ var (
_ _context.Context
)

{{#generateInterfaces}}
type {{classname}} interface {
{{#operation}}

/*
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
{{#allParams}}
{{#required}}
* @param {{paramName}}{{#description}} {{{.}}}{{/description}}
{{/required}}
{{/allParams}}
{{#hasOptionalParams}}
* @param optional nil or *{{#structPrefix}}{{&classname}}{{/structPrefix}}{{{nickname}}}Opts - Optional Parameters:
{{#allParams}}
{{^required}}
* @param "{{vendorExtensions.x-export-param-name}}" ({{#isPrimitiveType}}{{^isBinary}}optional.{{vendorExtensions.x-optional-data-type}}{{/isBinary}}{{#isBinary}}optional.Interface of {{dataType}}{{/isBinary}}{{/isPrimitiveType}}{{^isPrimitiveType}}optional.Interface of {{dataType}}{{/isPrimitiveType}}) - {{#description}} {{{.}}}{{/description}}
{{/required}}
{{/allParams}}
{{/hasOptionalParams}}
{{#returnType}}
* @return {{{returnType}}}
{{/returnType}}
*/
{{{nickname}}}(ctx _context.Context{{#hasParams}}, {{/hasParams}}{{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}}localVarOptionals *{{#structPrefix}}{{&classname}}{{/structPrefix}}{{{nickname}}}Opts{{/hasOptionalParams}}) ({{#returnType}}{{{returnType}}}, {{/returnType}}*_nethttp.Response, error)
{{/operation}}
}

{{/generateInterfaces}}
// {{classname}}Service {{classname}} service
type {{classname}}Service service
{{#operation}}
Expand All @@ -43,9 +77,11 @@ type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{{nickname}}}Opts struct {

{{/hasOptionalParams}}
/*
{{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
*
{{#notes}}
{{notes}}
* {{notes}}
*
{{/notes}}
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
{{#allParams}}
Expand All @@ -62,9 +98,9 @@ type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{{nickname}}}Opts struct {
{{/allParams}}
{{/hasOptionalParams}}
{{#returnType}}
@return {{{returnType}}}
* @return {{{returnType}}}
{{/returnType}}
*/
*/
func (a *{{{classname}}}Service) {{{nickname}}}(ctx _context.Context{{#hasParams}}, {{/hasParams}}{{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}}localVarOptionals *{{#structPrefix}}{{&classname}}{{/structPrefix}}{{{nickname}}}Opts{{/hasOptionalParams}}) ({{#returnType}}{{{returnType}}}, {{/returnType}}*_nethttp.Response, error) {
var (
localVarHTTPMethod = _nethttp.Method{{httpMethod}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ type APIClient struct {
{{#apis}}
{{#operations}}

{{#generateInterfaces}}
{{classname}} {{classname}}
{{/generateInterfaces}}
{{^generateInterfaces}}
{{classname}} *{{classname}}Service
{{/generateInterfaces}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ protected void verifyOptions() {
verify(clientCodegen).setPackageName(GoClientOptionsProvider.PACKAGE_NAME_VALUE);
verify(clientCodegen).setWithGoCodegenComment(GoClientOptionsProvider.WITH_GO_CODEGEN_COMMENT_VALUE);
verify(clientCodegen).setWithXml(GoClientOptionsProvider.WITH_XML_VALUE);
verify(clientCodegen).setWithXml(GoClientOptionsProvider.ENUM_CLASS_PREFIX_VALUE);
verify(clientCodegen).setEnumClassPrefix(GoClientOptionsProvider.ENUM_CLASS_PREFIX_VALUE);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any reason this repeated the setWithXml from the previous line, so I think this was a bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, apparently this was just previously running this twice:

verify(clientCodegen).setWithXml(true);

verify(clientCodegen).setPrependFormOrBodyParameters(GoClientOptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE);
verify(clientCodegen).setIsGoSubmodule(GoClientOptionsProvider.IS_GO_SUBMODULE_VALUE);
verify(clientCodegen).setStructPrefix(GoClientOptionsProvider.STRUCT_PREFIX_VALUE);
verify(clientCodegen).setWithAWSV4Signature(GoClientOptionsProvider.WITH_AWSV4_SIGNATURE);
verify(clientCodegen).setGenerateInterfaces(GoClientOptionsProvider.GENERATE_INTERFACES_VALUE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class GoClientOptionsProvider implements OptionsProvider {
public static final boolean IS_GO_SUBMODULE_VALUE = true;
public static final boolean STRUCT_PREFIX_VALUE = true;
public static final boolean WITH_AWSV4_SIGNATURE = true;
public static final boolean GENERATE_INTERFACES_VALUE = true;

@Override
public String getLanguage() {
Expand All @@ -52,6 +53,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, "true")
.put(CodegenConstants.IS_GO_SUBMODULE, "true")
.put(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, "true")
.put("generateInterfaces", "true")
.put("structPrefix", "true")
.build();
}
Expand Down
Loading