[maven-plugin] allow for ignore file override (#4597)

* [maven-plugin] allow for ignore file override

The .swagger-codegen-ignore file is beneficial for existing source
directories to provide pattern-based exclusion rules for existing source
to be ignored by swagger codegen. Until now, there's been no utility
other than skipOverwrite to modify the initial generation of code
(either via CLI or maven plugin).

This commit adds support for an ignoreFileOverride option to both the
CLI and the maven plugin.

Example CLI usage:

```
java -jar swagger-codegen.jar generate \
    -i swagger.json -l csharp \
    -o target --ignore-file-override /path/to/ignore-file
```

Example Maven Plugin configuration:

```
    <build>
        <plugins>
            <plugin>
                <groupId>io.swagger</groupId>
                <artifactId>swagger-codegen-maven-plugin</artifactId>
                <version>2.2.2-SNAPSHOT</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/src/main/resources/swagger.yaml</inputSpec>
                            <language>csharp</language>
                            <invokerPackage>io.swagger</invokerPackage>
                            <modelPackage>io.swagger.models</modelPackage>
                            <apiPackage>io.swagger.apis</apiPackage>
                            <ignoreFileOverride>/Users/jim/projects/swagger-codegen/.sample-ignore</ignoreFileOverride>
                            <configOptions>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
```

* [maven-plugin] update new javadocs

* fix bad merge due to missing }
This commit is contained in:
wing328 2017-01-19 23:17:25 +08:00 committed by GitHub
parent 59c189e3c9
commit 029728d851
13 changed files with 158 additions and 25 deletions

View File

@ -121,6 +121,9 @@ public class Generate implements Runnable {
@Option(name = {"--reserved-words-mappings"}, title = "import mappings",
description = "specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used. For example id=identifier")
private String reservedWordsMappings;
@Option(name = {"--ignore-file-override"}, title = "ignore file override location", description = CodegenConstants.IGNORE_FILE_OVERRIDE_DESC)
private String ignoreFileOverride;
@Override
public void run() {
@ -215,6 +218,10 @@ public class Generate implements Runnable {
configurator.setHttpUserAgent(httpUserAgent);
}
if (isNotEmpty(ignoreFileOverride)) {
configurator.setIgnoreFileOverride(ignoreFileOverride);
}
applySystemPropertiesKvp(systemProperties, configurator);
applyInstantiationTypesKvp(instantiationTypes, configurator);
applyImportMappingsKvp(importMappings, configurator);

View File

@ -49,6 +49,7 @@ mvn clean compile
- `useJaxbAnnotations` - enable Jaxb annotations inside the generated models
- `configOptions` - a map of language-specific parameters (see below)
- `configHelp` - dumps the configuration help for the specified library (generates no sources)
- `ignoreFileOverride` - specifies the full path to a `.swagger-codegen-ignore` used for pattern based overrides of generated outputs
### Custom Generator

View File

@ -162,6 +162,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "modelNameSuffix", required = false)
private String modelNameSuffix;
/**
* Sets an optional ignoreFileOverride path
*/
@Parameter(name = "ignoreFileOverride", required = false)
private String ignoreFileOverride;
/**
* A map of language-specific parameters as passed with the -c option to the command line
*/
@ -216,6 +222,10 @@ public class CodeGenMojo extends AbstractMojo {
configurator.setGitRepoId(gitRepoId);
}
if(isNotEmpty(ignoreFileOverride)) {
configurator.setIgnoreFileOverride(ignoreFileOverride);
}
configurator.setLang(language);
configurator.setOutputDir(output.getAbsolutePath());

View File

@ -199,5 +199,8 @@ public interface CodegenConfig {
String getHttpUserAgent();
String getCommonTemplateDir();
void setIgnoreFilePathOverride(String ignoreFileOverride);
String getIgnoreFilePathOverride();
}

View File

@ -153,4 +153,7 @@ public class CodegenConstants {
public static final String NON_PUBLIC_API = "nonPublicApi";
public static final String NON_PUBLIC_API_DESC = "Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.";
public static final String IGNORE_FILE_OVERRIDE = "ignoreFileOverride";
public static final String IGNORE_FILE_OVERRIDE_DESC = "Specifies an override location for the .swagger-codegen-ignore file. Most useful on initial generation.";
}

View File

@ -115,6 +115,8 @@ public class DefaultCodegen {
// Then translated back during JSON encoding and decoding
protected Map<String, String> specialCharReplacements = new HashMap<String, String>();
protected String ignoreFilePathOverride;
public List<CliOption> cliOptions() {
return cliOptions;
}
@ -3454,7 +3456,26 @@ public class DefaultCodegen {
return booleanValue;
}
/**
* Provides an override location, if any is specified, for the .swagger-codegen-ignore.
*
* This is originally intended for the first generation only.
*
* @return a string of the full path to an override ignore file.
*/
public String getIgnoreFilePathOverride() {
return ignoreFilePathOverride;
}
/**
* Sets an override location for the .swagger-codegen.ignore location for the first code generation.
*
* @param ignoreFileOverride The full path to an ignore file
*/
public void setIgnoreFilePathOverride(final String ignoreFileOverride) {
this.ignoreFilePathOverride = ignoreFileOverride;
}
public boolean convertPropertyToBoolean(String propertyKey) {
boolean booleanValue = false;

View File

@ -42,7 +42,21 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
this.swagger = opts.getSwagger();
this.config = opts.getConfig();
this.config.additionalProperties().putAll(opts.getOpts().getProperties());
ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir());
String ignoreFileLocation = this.config.getIgnoreFilePathOverride();
if(ignoreFileLocation != null) {
final File ignoreFile = new File(ignoreFileLocation);
if(ignoreFile.exists() && ignoreFile.canRead()) {
this.ignoreProcessor = new CodegenIgnoreProcessor(ignoreFile);
} else {
LOGGER.warn("Ignore file specified at {} is not valid. This will fall back to an existing ignore file if present in the output directory.", ignoreFileLocation);
}
}
if(this.ignoreProcessor == null) {
this.ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir());
}
return this;
}

View File

@ -54,6 +54,7 @@ public class CodegenConfigurator {
private String artifactId;
private String artifactVersion;
private String library;
private String ignoreFileOverride;
private Map<String, String> systemProperties = new HashMap<String, String>();
private Map<String, String> instantiationTypes = new HashMap<String, String>();
private Map<String, String> typeMappings = new HashMap<String, String>();
@ -356,7 +357,16 @@ public class CodegenConfigurator {
public CodegenConfigurator addAdditionalReservedWordMapping(String key, String value) {
this.reservedWordMappings.put(key, value);
return this;
}
}
public String getIgnoreFileOverride() {
return ignoreFileOverride;
}
public CodegenConfigurator setIgnoreFileOverride(final String ignoreFileOverride) {
this.ignoreFileOverride = ignoreFileOverride;
return this;
}
public ClientOptInput toClientOptInput() {
@ -371,6 +381,7 @@ public class CodegenConfigurator {
config.setInputSpec(inputSpec);
config.setOutputDir(outputDir);
config.setSkipOverwrite(skipOverwrite);
config.setIgnoreFilePathOverride(ignoreFileOverride);
config.instantiationTypes().putAll(instantiationTypes);
config.typeMapping().putAll(typeMappings);

View File

@ -8,34 +8,71 @@ import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Presents a processing utility for parsing and evaluating files containing common ignore patterns. (.swagger-codegen-ignore)
*/
public class CodegenIgnoreProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessor.class);
private final String outputPath;
private File ignoreFile = null;
private List<Rule> exclusionRules = new ArrayList<>();
private List<Rule> inclusionRules = new ArrayList<>();
public CodegenIgnoreProcessor(String outputPath) {
this.outputPath = outputPath;
final File directory = new File(outputPath);
if(directory.exists() && directory.isDirectory()){
final File codegenIgnore = new File(directory, ".swagger-codegen-ignore");
if(codegenIgnore.exists() && codegenIgnore.isFile()){
try {
loadCodegenRules(codegenIgnore);
} catch (IOException e) {
LOGGER.error("Could not process .swagger-codegen-ignore.", e.getMessage());
}
} else {
// log info message
LOGGER.info("No .swagger-codegen-ignore file found.");
}
/**
* Loads the default ignore file (.swagger-codegen-ignore) from the specified path.
*
* @param baseDirectory The base directory of the files to be processed. This contains the ignore file.
*/
public CodegenIgnoreProcessor(final String baseDirectory) {
this(baseDirectory, ".swagger-codegen-ignore");
}
/**
* Loads the specified ignore file by name ([ignoreFile]) from the specified path.
*
* @param baseDirectory The base directory of the files to be processed. This contains the ignore file.
* @param ignoreFile The file containing ignore patterns.
*/
@SuppressWarnings("WeakerAccess")
public CodegenIgnoreProcessor(final String baseDirectory, final String ignoreFile) {
final File directory = new File(baseDirectory);
final File targetIgnoreFile = new File(directory, ignoreFile);
if (directory.exists() && directory.isDirectory()) {
loadFromFile(targetIgnoreFile);
} else {
LOGGER.warn("Directory does not exist, or is inaccessible. No file will be evaluated.");
}
}
void loadCodegenRules(File codegenIgnore) throws IOException {
/**
* Constructs an instance of {@link CodegenIgnoreProcessor} from an ignore file defined by {@code targetIgnoreFile}.
*
* @param targetIgnoreFile The ignore file location.
*/
public CodegenIgnoreProcessor(final File targetIgnoreFile) {
loadFromFile(targetIgnoreFile);
}
private void loadFromFile(File targetIgnoreFile) {
if (targetIgnoreFile.exists() && targetIgnoreFile.isFile()) {
try {
loadCodegenRules(targetIgnoreFile);
this.ignoreFile = targetIgnoreFile;
} catch (IOException e) {
LOGGER.error(String.format("Could not process %s.", targetIgnoreFile.getName()), e.getMessage());
}
} else {
// log info message
LOGGER.info(String.format("No %s file found.", targetIgnoreFile.getName()));
}
}
void loadCodegenRules(final File codegenIgnore) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(codegenIgnore))) {
String line;
@ -61,8 +98,17 @@ public class CodegenIgnoreProcessor {
}
}
public boolean allowsFile(File targetFile) {
File file = new File(new File(this.outputPath).toURI().relativize(targetFile.toURI()).getPath());
/**
* Determines whether or not a file defined by {@code toEvaluate} is allowed,
* under the exclusion rules from the ignore file being processed.
*
* @param targetFile The file to check against exclusion rules from the ignore file.
* @return {@code false} if file matches any pattern in the ignore file (disallowed), otherwise {@code true} (allowed).
*/
public boolean allowsFile(final File targetFile) {
if(this.ignoreFile == null) return true;
File file = new File(this.ignoreFile.getParentFile().toURI().relativize(targetFile.toURI()).getPath());
Boolean directoryExcluded = false;
Boolean exclude = false;
if(exclusionRules.size() == 0 && inclusionRules.size() == 0) {
@ -124,10 +170,23 @@ public class CodegenIgnoreProcessor {
return Boolean.FALSE.equals(exclude);
}
/**
* Allows a consumer to manually inspect explicit "inclusion rules". That is, patterns in the ignore file which have been negated.
*
* @return A {@link ImmutableList#copyOf(Collection)} of rules which possibly negate exclusion rules in the ignore file.
*/
public List<Rule> getInclusionRules() {
return ImmutableList.copyOf(inclusionRules);
}
/**
* Allows a consumer to manually inspect all "exclusion rules". That is, patterns in the ignore file which represent
* files and directories to be excluded, unless explicitly overridden by {@link CodegenIgnoreProcessor#getInclusionRules()} rules.
*
* NOTE: Existence in this list doesn't mean a file is excluded. The rule can be overridden by {@link CodegenIgnoreProcessor#getInclusionRules()} rules.
*
* @return A {@link ImmutableList#copyOf(Collection)} of rules which define exclusions by patterns in the ignore file.
*/
public List<Rule> getExclusionRules() {
return ImmutableList.copyOf(exclusionRules);
}

View File

@ -51,6 +51,8 @@ public abstract class Rule {
* Example: **\/*.bak excludes all backup. Adding !/test.bak will include test.bak in the project root.
* <p>
* NOTE: It is not possible to re-include a file if a parent directory of that file is excluded.
*
* @return {@code true} if the rule is negated (inverse), otherwise {@code false} (normal).
*/
public Boolean getNegated() {
return this.syntax != null && this.syntax.size() > 0 && this.syntax.get(0).getToken() == IgnoreLineParser.Token.NEGATE;

View File

@ -295,6 +295,8 @@ public class CodegenConfiguratorTest {
assertEquals(configurator.getDynamicProperties().size(), 1);
assertValueInMap(configurator.getDynamicProperties(), CodegenConstants.LOCAL_VARIABLE_PREFIX, "_");
assertEquals(configurator.getIgnoreFileOverride(), "/path/to/override/.swagger-codegen-ignore");
}
@SuppressWarnings("unused")

View File

@ -49,8 +49,7 @@ public class RubyClientCodegenTest {
ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).swagger(swagger).config(codegenConfig);
DefaultGenerator generator = new DefaultGenerator();
generator.opts(clientOptInput);
List<File> files = generator.generate();
List<File> files = generator.opts(clientOptInput).generate();
boolean apiFileGenerated = false;
for (File file : files) {
if (file.getName().equals("default_api.rb")) {

View File

@ -13,6 +13,7 @@
"artifactId" : "awesome-api",
"artifactVersion" : "1.2.3",
"library" : "jersey2",
"ignoreFileOverride": "/path/to/override/.swagger-codegen-ignore",
"systemProperties" : {
"systemProp1" : "value1"
},