Skip to content

How to add an option to a specific language or framework

HugoMario edited this page Jun 28, 2018 · 1 revision

Overview

With Swagger Codegen V3 development a new feature has been added for CLI tool. It's the capability to add an option for a specific language on code generation. This feature is related to #6041 issue.

Adding new options for a language.

swagger-codegen-cli contains a list of options for generate command. You can see this list using this command:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -h

You should see a list like this:

  -h, --help             show this help message and exit
  -v [], --verbose []    verbose mode
  -l, --lang             client language to generate (maybe class name in classpath, required)
  -o, --output           where to write the generated files (current dir by default)
  -i, --input-spec       location of the swagger spec, as URL or file (required)
  -t, --template-dir     folder containing the template files
  --template-version     version of the template used on generation.

  . . .

  --http-user-agent      HTTP user agent, e.g. codegen_csharp_api_client, default to 'Swagger-Codegen/{packageVersion}}/{language}'
  --reserved-words-mappings [ [ ...]]
                         pecifies how a reserved name should be escaped to. Otherwise, the default _<name> is used. For example id=identifier. You can also have multiple occurrences of this option.
  --ignore-file-override
                         Specifies an override location for the .swagger-codegen-ignore file. Most useful on initial generation.
  --remove-operation-id-prefix
                         Remove prefix of operationId, e.g. config_getId => getId
  -u, --url              load arguments from a local file or remote URL. Arguments found will replace any one placed on command.

In order to add a new option and let somebody else use it, we need to follow these steps:

1. Edit or create arguments file:

Each language class is related to an argument file, right now only java and inflector languages have one. Files should be placed on resources main folder for swagger-codegen-generators project, preferably inside resources/arguments folder.

If the file arguments for exists, for example, resources/arguments/inflector, we must edit the file. The file itself is an array on yaml format. This is the current content for inflector

arguments:
  - option: "--model-docs"
    description: "generate models documentation."
    type: "boolean"
  - option: "--api-docs"
    description: "generate apis documentation."
    type: "boolean"
  - option: "--model-tests"
    description: "generate model tests."
    type: "boolean"
  - option: "--api-tests"
    description: "generate apis tests."
    type: "boolean"

So, we can note in example above that an option is a object inside a list, where:

option field is the element used in CLI and it will be listed on command list, for example if we use this command to show options for inflector language:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -l inflector -h

We should get an output like this:

  -h, --help             show this help message and exit
  -v [], --verbose []    verbose mode
  -l, --lang             client language to generate (maybe class name in classpath, required)
  -o, --output           where to write the generated files (current dir by default)
  -i, --input-spec       location of the swagger spec, as URL or file (required)
  -t, --template-dir     folder containing the template files
  --template-version     version of the template used on generation.

  . . .

  --http-user-agent      HTTP user agent, e.g. codegen_csharp_api_client, default to 'Swagger-Codegen/{packageVersion}}/{language}'
  --reserved-words-mappings [ [ ...]]
                         pecifies how a reserved name should be escaped to. Otherwise, the default _<name> is used. For example id=identifier. You can also have multiple occurrences of this option.
  --ignore-file-override
                         Specifies an override location for the .swagger-codegen-ignore file. Most useful on initial generation.
  --remove-operation-id-prefix
                         Remove prefix of operationId, e.g. config_getId => getId
  -u, --url              load arguments from a local file or remote URL. Arguments found will replace any one placed on command.
  --model-docs           generate models documentation.
  --api-docs             generate apis documentation.
  --model-tests          generate model tests.
  --api-tests            generate apis tests.

This way we can see the options for inflector language at bottom of the list.

Now, because currently there are only additional options for two languages (java and inflector) It will be required to create the arguments file if you want to add a new option for a different file.

On this case, the file just need to follow the format shown in previous sample. But there are a couple of things to keep in mind, that will be described in next steps.

2. Override abstract method getArgumentsLocation from DefaultCodegenConfig class.

This is a very simple step, from this method we just need to return the arguments file location, like this example with JavaClientCodegen class.

    @Override
    public String getArgumentsLocation() {
        return "/arguments/java.yaml";
    }

3. Reading options

In order to know if the options were used on CLI tool we need to override the setLanguageArguments method. Let's check this example from JavaInflectorServerCodegen class.

    @Override
    public void setLanguageArguments(List<CodegenArgument> languageArguments) {
        if (languageArguments == null) {
            languageArguments = new ArrayList<>();
        }
        if (!languageArguments.stream()
                .anyMatch(codegenArgument -> CodegenConstants.MODEL_DOCS_OPTION.equalsIgnoreCase(codegenArgument.getOption()) && StringUtils.isNotBlank(codegenArgument.getValue()))) {
            languageArguments.add(new CodegenArgument()
                    .option(CodegenConstants.MODEL_DOCS_OPTION)
                    .type("boolean")
                    .value(Boolean.FALSE.toString()));
        }
        if (!languageArguments.stream()
                .anyMatch(codegenArgument -> CodegenConstants.API_DOCS_OPTION.equalsIgnoreCase(codegenArgument.getOption()) && StringUtils.isNotBlank(codegenArgument.getValue()))) {
            languageArguments.add(new CodegenArgument()
                    .option(CodegenConstants.API_DOCS_OPTION)
                    .type("boolean")
                    .value(Boolean.FALSE.toString()));
        }
        if (!languageArguments.stream()
                .anyMatch(codegenArgument -> CodegenConstants.MODEL_TESTS_OPTION.equalsIgnoreCase(codegenArgument.getOption()) && StringUtils.isNotBlank(codegenArgument.getValue()))) {
            languageArguments.add(new CodegenArgument()
                    .option(CodegenConstants.MODEL_TESTS_OPTION)
                    .type("boolean")
                    .value(Boolean.FALSE.toString()));
        }
        if (!languageArguments.stream()
                .anyMatch(codegenArgument -> CodegenConstants.API_TESTS_OPTION.equalsIgnoreCase(codegenArgument.getOption()) && StringUtils.isNotBlank(codegenArgument.getValue()))) {
            languageArguments.add(new CodegenArgument()
                    .option(CodegenConstants.API_TESTS_OPTION)
                    .type("boolean")
                    .value(Boolean.FALSE.toString()));
        }
        super.setLanguageArguments(languageArguments);
    }

On this example we can note that these options are matched to a list of CodegenArgument objects. We must keep in mind that these CodegenArgument objects are set from CLI options before generation and they are still available on the whole generation process. So we are free to decide when they must be used.