org.openapitools.codegen.languages.AbstractGoCodegen Maven / Gradle / Ivy
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.languages;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.io.FilenameUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.*;
public abstract class AbstractGoCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
protected boolean withGoCodegenComment = false;
protected boolean withXml = false;
protected String packageName = "openapi";
public AbstractGoCodegen() {
super();
hideGenerationTimestamp = Boolean.FALSE;
defaultIncludes = new HashSet(
Arrays.asList(
"map",
"array")
);
setReservedWordsLowerCase(
Arrays.asList(
// data type
"string", "bool", "uint", "uint8", "uint16", "uint32", "uint64",
"int", "int8", "int16", "int32", "int64", "float32", "float64",
"complex64", "complex128", "rune", "byte", "uintptr",
"break", "default", "func", "interface", "select",
"case", "defer", "go", "map", "struct",
"chan", "else", "goto", "package", "switch",
"const", "fallthrough", "if", "range", "type",
"continue", "for", "import", "return", "var", "error", "nil")
// Added "error" as it's used so frequently that it may as well be a keyword
);
languageSpecificPrimitives = new HashSet(
Arrays.asList(
"string",
"bool",
"uint",
"uint32",
"uint64",
"int",
"int32",
"int64",
"float32",
"float64",
"complex64",
"complex128",
"rune",
"byte")
);
instantiationTypes.clear();
/*instantiationTypes.put("array", "GoArray");
instantiationTypes.put("map", "GoMap");*/
typeMapping.clear();
typeMapping.put("integer", "int32");
typeMapping.put("long", "int64");
typeMapping.put("number", "float32");
typeMapping.put("float", "float32");
typeMapping.put("double", "float64");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "string");
typeMapping.put("UUID", "string");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "time.Time");
typeMapping.put("password", "string");
typeMapping.put("File", "*os.File");
typeMapping.put("file", "*os.File");
typeMapping.put("binary", "*os.File");
typeMapping.put("ByteArray", "string");
typeMapping.put("object", "map[string]interface{}");
importMapping = new HashMap();
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Go package name (convention: lowercase).")
.defaultValue("openapi"));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
.defaultValue(Boolean.TRUE.toString()));
}
@Override
public void processOpts() {
super.processOpts();
if (StringUtils.isEmpty(System.getenv("GO_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable GO_POST_PROCESS_FILE not defined so Go code may not be properly formatted. To define it, try `export GO_POST_PROCESS_FILE=\"/usr/local/bin/gofmt -w\"` (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
// Can't start with an underscore, as our fields need to start with an
// UppercaseLetter so that Go treats them as public/visible.
// Options?
// - MyName
// - AName
// - TheName
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return org.openapitools.codegen.utils.StringUtils.camelize(name) + '_';
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = sanitizeName(name);
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// camelize (lower first character) the variable name
// pet_id => PetId
name = org.openapitools.codegen.utils.StringUtils.camelize(name);
// for reserved word append _
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as variable name. Renamed to " + escapeReservedWord(name));
name = escapeReservedWord(name);
}
// for reserved word or word starting with number, append _
if (name.matches("^\\d.*"))
name = "Var" + name;
return name;
}
@Override
protected boolean isReservedWord(String word) {
return word != null && reservedWords.contains(word);
}
@Override
public String toParamName(String name) {
// params should be lowerCamelCase. E.g. "person Person", instead of
// "Person Person".
//
name = org.openapitools.codegen.utils.StringUtils.camelize(toVarName(name), true);
// REVISIT: Actually, for idiomatic go, the param name should
// really should just be a letter, e.g. "p Person"), but we'll get
// around to that some other time... Maybe.
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as parameter name. Renamed to " + name + "_");
name = name + "_";
}
return name;
}
@Override
public String toModelName(String name) {
// camelize the model name
// phone_number => PhoneNumber
return org.openapitools.codegen.utils.StringUtils.camelize(toModel(name));
}
@Override
public String toModelFilename(String name) {
name = toModel("model_" + name);
if (name.endsWith("_test")) {
LOGGER.warn(name + ".go with `_test.go` suffix (reserved word) cannot be used as filename. Renamed to " + name + "_.go");
name += "_";
}
return name;
}
public String toModel(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + ("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to "
+ ("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
return org.openapitools.codegen.utils.StringUtils.underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PetApi.go => pet_api.go
name = "api_" + org.openapitools.codegen.utils.StringUtils.underscore(name);
if (name.endsWith("_test")) {
LOGGER.warn(name + ".go with `_test.go` suffix (reserved word) cannot be used as filename. Renamed to " + name + "_.go");
name += "_";
}
return name;
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return "[]" + getTypeDeclaration(inner);
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
return getSchemaType(p) + "[string]" + getTypeDeclaration(inner);
}
//return super.getTypeDeclaration(p);
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String openAPIType = getSchemaType(p);
String ref = p.get$ref();
if (ref != null && !ref.isEmpty()) {
String tryRefV2 = "#/definitions/" + openAPIType;
String tryRefV3 = "#/components/schemas/" + openAPIType;
if (ref.equals(tryRefV2) || ref.equals(tryRefV3)) {
return toModelName(openAPIType);
}
}
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
}
if (typeMapping.containsValue(openAPIType)) {
return openAPIType;
}
if (languageSpecificPrimitives.contains(openAPIType)) {
return openAPIType;
}
return toModelName(openAPIType);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String ref = p.get$ref();
String type = null;
if (ref != null && !ref.isEmpty()) {
type = openAPIType;
} else if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type))
return (type);
} else
type = openAPIType;
return type;
}
@Override
public String toOperationId(String operationId) {
String sanitizedOperationId = sanitizeName(operationId);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(sanitizedOperationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to "
+ org.openapitools.codegen.utils.StringUtils.camelize("call_" + sanitizedOperationId));
sanitizedOperationId = "call_" + sanitizedOperationId;
}
// operationId starts with a number
if (sanitizedOperationId.matches("^\\d.*")) {
LOGGER.warn(operationId + " (starting with a number) cannot be used as method name. Renamed to " + org.openapitools.codegen.utils.StringUtils.camelize("call_" + sanitizedOperationId));
sanitizedOperationId = "call_" + sanitizedOperationId;
}
return org.openapitools.codegen.utils.StringUtils.camelize(sanitizedOperationId);
}
@Override
public Map postProcessOperationsWithModels(Map objs, List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy