From 029728d851e63dc2887e126e1944f61a04d4540a Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 19 Jan 2017 23:17:25 +0800 Subject: [PATCH] [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: ``` io.swagger swagger-codegen-maven-plugin 2.2.2-SNAPSHOT generate ${project.basedir}/src/main/resources/swagger.yaml csharp io.swagger io.swagger.models io.swagger.apis /Users/jim/projects/swagger-codegen/.sample-ignore ``` * [maven-plugin] update new javadocs * fix bad merge due to missing } --- .../java/io/swagger/codegen/cmd/Generate.java | 7 ++ .../swagger-codegen-maven-plugin/README.md | 1 + .../swagger/codegen/plugin/CodeGenMojo.java | 10 ++ .../io/swagger/codegen/CodegenConfig.java | 5 +- .../io/swagger/codegen/CodegenConstants.java | 3 + .../io/swagger/codegen/DefaultCodegen.java | 23 ++++- .../io/swagger/codegen/DefaultGenerator.java | 16 ++- .../codegen/config/CodegenConfigurator.java | 13 ++- .../ignore/CodegenIgnoreProcessor.java | 97 +++++++++++++++---- .../io/swagger/codegen/ignore/rules/Rule.java | 2 + .../config/CodegenConfiguratorTest.java | 2 + .../codegen/ruby/RubyClientCodegenTest.java | 3 +- .../src/test/resources/sampleConfig.json | 1 + 13 files changed, 158 insertions(+), 25 deletions(-) diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java index 482a630c976..01303e64559 100644 --- a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java @@ -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 _ 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); diff --git a/modules/swagger-codegen-maven-plugin/README.md b/modules/swagger-codegen-maven-plugin/README.md index cc54e2ad447..64382be8678 100644 --- a/modules/swagger-codegen-maven-plugin/README.md +++ b/modules/swagger-codegen-maven-plugin/README.md @@ -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 diff --git a/modules/swagger-codegen-maven-plugin/src/main/java/io/swagger/codegen/plugin/CodeGenMojo.java b/modules/swagger-codegen-maven-plugin/src/main/java/io/swagger/codegen/plugin/CodeGenMojo.java index 56472b713d2..5876bc16d2d 100644 --- a/modules/swagger-codegen-maven-plugin/src/main/java/io/swagger/codegen/plugin/CodeGenMojo.java +++ b/modules/swagger-codegen-maven-plugin/src/main/java/io/swagger/codegen/plugin/CodeGenMojo.java @@ -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()); diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConfig.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConfig.java index f48d3f090e6..4ffb9558230 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConfig.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConfig.java @@ -199,5 +199,8 @@ public interface CodegenConfig { String getHttpUserAgent(); String getCommonTemplateDir(); - + + void setIgnoreFilePathOverride(String ignoreFileOverride); + + String getIgnoreFilePathOverride(); } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java index 89a8666d93d..66c1616bc7b 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java @@ -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."; } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index 86a29382fdc..e981569a871 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -115,6 +115,8 @@ public class DefaultCodegen { // Then translated back during JSON encoding and decoding protected Map specialCharReplacements = new HashMap(); + protected String ignoreFilePathOverride; + public List 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; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index 94d1579671e..03433e64580 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -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; } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/config/CodegenConfigurator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/config/CodegenConfigurator.java index 7d95e6d18c2..b21e89711ff 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/config/CodegenConfigurator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/config/CodegenConfigurator.java @@ -54,6 +54,7 @@ public class CodegenConfigurator { private String artifactId; private String artifactVersion; private String library; + private String ignoreFileOverride; private Map systemProperties = new HashMap(); private Map instantiationTypes = new HashMap(); private Map typeMappings = new HashMap(); @@ -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); diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/CodegenIgnoreProcessor.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/CodegenIgnoreProcessor.java index fb25ac82b28..2852c6eed96 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/CodegenIgnoreProcessor.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/CodegenIgnoreProcessor.java @@ -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 exclusionRules = new ArrayList<>(); private List 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 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 getExclusionRules() { return ImmutableList.copyOf(exclusionRules); } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/rules/Rule.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/rules/Rule.java index 137cb071cab..2d2394302f8 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/rules/Rule.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/ignore/rules/Rule.java @@ -51,6 +51,8 @@ public abstract class Rule { * Example: **\/*.bak excludes all backup. Adding !/test.bak will include test.bak in the project root. *

* 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; diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/config/CodegenConfiguratorTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/config/CodegenConfiguratorTest.java index e3de3fdf8af..edffc835de8 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/config/CodegenConfiguratorTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/config/CodegenConfiguratorTest.java @@ -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") diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/ruby/RubyClientCodegenTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/ruby/RubyClientCodegenTest.java index 40b7e8dc55b..bf69f043b54 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/ruby/RubyClientCodegenTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/ruby/RubyClientCodegenTest.java @@ -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 files = generator.generate(); + List files = generator.opts(clientOptInput).generate(); boolean apiFileGenerated = false; for (File file : files) { if (file.getName().equals("default_api.rb")) { diff --git a/modules/swagger-codegen/src/test/resources/sampleConfig.json b/modules/swagger-codegen/src/test/resources/sampleConfig.json index 373665877c4..5c147400d8f 100644 --- a/modules/swagger-codegen/src/test/resources/sampleConfig.json +++ b/modules/swagger-codegen/src/test/resources/sampleConfig.json @@ -13,6 +13,7 @@ "artifactId" : "awesome-api", "artifactVersion" : "1.2.3", "library" : "jersey2", + "ignoreFileOverride": "/path/to/override/.swagger-codegen-ignore", "systemProperties" : { "systemProp1" : "value1" },