forked from loafle/openapi-generator-original
Merge pull request #2992 from jimschubert/swagger_codegen_ignore_docs
[codegen ignore] Add tests and docs, fix two minor issues
This commit is contained in:
commit
fb68f61a03
38
README.md
38
README.md
@ -408,6 +408,44 @@ java -Dapis -DmodelTests=false {opts}
|
||||
|
||||
When using selective generation, _only_ the templates needed for the specific generation will be used.
|
||||
|
||||
### Ignore file format
|
||||
|
||||
Swagger codegen supports a `.swagger-codegen-ignore` file, similar to `.gitignore` or `.dockerignore` you're probably already familiar with.
|
||||
|
||||
The ignore file allows for better control over overwriting existing files than the `--skip-overwrite` flag. With the ignore file, you can specify individual files or directories can be ignored. This can be useful, for example if you only want a subset of the generated code.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
# Swagger Codegen Ignore
|
||||
# Lines beginning with a # are comments
|
||||
|
||||
# This should match build.sh located anywhere.
|
||||
build.sh
|
||||
|
||||
# Matches build.sh in the root
|
||||
/build.sh
|
||||
|
||||
# Exclude all recursively
|
||||
docs/**
|
||||
|
||||
# Explicitly allow files excluded by other rules
|
||||
!docs/UserApi.md
|
||||
|
||||
# Recursively exclude directories named Api
|
||||
# You can't negate files below this directory.
|
||||
src/**/Api/
|
||||
|
||||
# When this file is nested under /Api (excluded above),
|
||||
# this rule is ignored because parent directory is excluded by previous rule.
|
||||
!src/**/PetApiTests.cs
|
||||
|
||||
# Exclude a single, nested file explicitly
|
||||
src/IO.Swagger.Test/Model/AnimalFarmTests.cs
|
||||
```
|
||||
|
||||
The `.swagger-codegen-ignore` file must exist in the root of the output directory.
|
||||
|
||||
### Customizing the generator
|
||||
|
||||
There are different aspects of customizing the code generator beyond just creating or modifying templates. Each language has a supporting configuration file to handle different type mappings, etc:
|
||||
|
@ -1,20 +1,27 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.*;
|
||||
import java.util.List;
|
||||
|
||||
public class DirectoryRule extends FileRule {
|
||||
|
||||
private PathMatcher matcher = null;
|
||||
private PathMatcher directoryMatcher = null;
|
||||
private PathMatcher contentsMatcher = null;
|
||||
|
||||
DirectoryRule(List<Part> syntax, String definition) {
|
||||
super(syntax, definition);
|
||||
matcher = FileSystems.getDefault().getPathMatcher("glob:**/"+this.getPattern());
|
||||
String pattern = this.getPattern();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("glob:");
|
||||
sb.append(pattern);
|
||||
if(!pattern.endsWith("/")) sb.append("/");
|
||||
directoryMatcher = FileSystems.getDefault().getPathMatcher(sb.toString());
|
||||
sb.append("**");
|
||||
contentsMatcher = FileSystems.getDefault().getPathMatcher(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
return matcher.matches(FileSystems.getDefault().getPath(relativePath));
|
||||
return contentsMatcher.matches(FileSystems.getDefault().getPath(relativePath)) || directoryMatcher.matches(FileSystems.getDefault().getPath(relativePath));
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,13 @@ public class IgnoreLineParser {
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
|
||||
if (sb.length() > 0) {
|
||||
// A MATCH_ANY may commonly follow a filename or some other character. Dump that to results before the MATCH_ANY.
|
||||
parts.add(new Part(Token.TEXT, sb.toString()));
|
||||
sb.delete(0, sb.length());
|
||||
}
|
||||
|
||||
parts.add(new Part(Token.MATCH_ANY));
|
||||
continue;
|
||||
}
|
||||
|
@ -1,21 +1,141 @@
|
||||
package io.swagger.codegen.ignore;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testng.annotations.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class CodegenIgnoreProcessorTest {
|
||||
@Test
|
||||
public void loadCodegenRules() throws Exception {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessorTest.class);
|
||||
|
||||
private Boolean allowed;
|
||||
private final String filename;
|
||||
private final String ignoreDefinition;
|
||||
private final String description;
|
||||
private String outputDir;
|
||||
private File target;
|
||||
private Path temp;
|
||||
|
||||
private CodegenIgnoreProcessorTest(String filename, String ignoreDefinition, String description) throws IOException {
|
||||
this.filename = filename;
|
||||
this.ignoreDefinition = ignoreDefinition;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
CodegenIgnoreProcessorTest allowed() {
|
||||
this.allowed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
CodegenIgnoreProcessorTest ignored() {
|
||||
this.allowed = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void prepareTestFiles() throws IOException {
|
||||
// NOTE: Each test needs its own directory because .swagger-codegen-ignore needs to exist at the root.
|
||||
temp = Files.createTempDirectory(getClass().getSimpleName());
|
||||
this.outputDir = temp.toFile().getAbsolutePath();
|
||||
|
||||
target = new File(this.outputDir, this.filename);
|
||||
|
||||
boolean mkdirs = target.getParentFile().mkdirs();
|
||||
if(!mkdirs) {
|
||||
LOGGER.warn("Failed to create directories for CodegenIgnoreProcessorTest test file. Directory may already exist.");
|
||||
}
|
||||
|
||||
Path created = Files.createFile(target.toPath());
|
||||
if(!created.toFile().exists()) {
|
||||
throw new IOException("Failed to write CodegenIgnoreProcessorTest test file.");
|
||||
}
|
||||
|
||||
// System.out.print(String.format("Created codegen ignore processor test file: %s\n", created.toAbsolutePath()));
|
||||
File ignoreFile = new File(this.outputDir, ".swagger-codegen-ignore");
|
||||
try (FileOutputStream stream = new FileOutputStream(ignoreFile)) {
|
||||
stream.write(this.ignoreDefinition.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() throws IOException {
|
||||
if(temp != null && temp.toFile().exists() && temp.toFile().isDirectory()) {
|
||||
FileUtils.deleteDirectory(temp.toFile());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInclusionRules() throws Exception {
|
||||
public void evaluate() {
|
||||
// Arrange
|
||||
try {
|
||||
// Lazily setup files to avoid conflicts and creation when these tests may not even run.
|
||||
prepareTestFiles();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail("Failed to prepare test files. " + e.getMessage());
|
||||
}
|
||||
CodegenIgnoreProcessor processor = new CodegenIgnoreProcessor(outputDir);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = processor.allowsFile(target);
|
||||
|
||||
// Assert
|
||||
assertEquals(actual, this.allowed, this.description);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionRules() throws Exception {
|
||||
@Factory
|
||||
public static Object[] factoryMethod() throws IOException {
|
||||
return new Object[] {
|
||||
// Matching filenames
|
||||
new CodegenIgnoreProcessorTest("build.sh", "build.sh", "A file when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("src/build.sh", "**/build.sh", "A file when matching nested files should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("Build.sh", "build.sh", "A file when non-matching should allow.").allowed(),
|
||||
new CodegenIgnoreProcessorTest("build.sh", "/build.sh", "A rooted file when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("nested/build.sh", "/build.sh", "A rooted file definition when non-matching should allow.").allowed(),
|
||||
new CodegenIgnoreProcessorTest("src/IO.Swagger.Test/Model/AnimalFarmTests.cs", "src/IO.Swagger.Test/Model/AnimalFarmTests.cs", "A file when matching exactly should ignore.").ignored(),
|
||||
|
||||
// Matching spaces in filenames
|
||||
new CodegenIgnoreProcessorTest("src/properly escaped.txt", "**/properly escaped.txt", "A file when matching nested files with spaces in the name should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("src/improperly escaped.txt", "**/improperly\\ escaped.txt", "A file when matching nested files with spaces in the name (improperly escaped rule) should allow.").allowed(),
|
||||
|
||||
// Match All
|
||||
new CodegenIgnoreProcessorTest("docs/somefile.md", "docs/**", "A recursive file (0 level) when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/somefile.md", "docs/**", "A recursive file (1 level) when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/somefile.md", "docs/**", "A recursive file (n level) when matching should ignore.").ignored(),
|
||||
|
||||
// Match Any
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/somefile.md", "docs/**/somefile.*", "A recursive file with match-any extension when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/somefile.java", "docs/**/*.java", "A recursive file with match-any file name when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/4/somefile.md", "docs/**/*", "A recursive file with match-any file name when matching should ignore.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/4/5/somefile.md", "docs/**/anyfile.*", "A recursive file with match-any extension when non-matching should allow.").allowed(),
|
||||
|
||||
// Directory matches
|
||||
new CodegenIgnoreProcessorTest("docs/1/Users/a", "docs/**/Users/", "A directory rule when matching should be ignored.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/Users1/a", "docs/**/Users/", "A directory rule when non-matching should be allowed.").allowed(),
|
||||
|
||||
// Negation of excluded recursive files
|
||||
new CodegenIgnoreProcessorTest("docs/UserApi.md", "docs/**\n!docs/UserApi.md", "A pattern negating a previous ignore FILE rule should be allowed.").allowed(),
|
||||
|
||||
// Negation of excluded directories
|
||||
new CodegenIgnoreProcessorTest("docs/1/Users/UserApi.md", "docs/**/Users/\n!docs/1/Users/UserApi.md", "A pattern negating a previous ignore DIRECTORY rule should be ignored.").ignored(),
|
||||
|
||||
// Other matches which may not be parsed for correctness, but are free because of PathMatcher
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/Some99File.md", "**/*[0-9]*", "A file when matching against simple regex patterns when matching should be ignored.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/SomeFile.md", "**/*.{java,md}", "A file when matching against grouped subpatterns for extension when matching (md) should be ignored.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/SomeFile.java", "**/*.{java,md}", "A file when matching against grouped subpatterns for extension when matching (java) should be ignored.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/SomeFile.txt", "**/*.{java,md}", "A file when matching against grouped subpatterns for extension when non-matching should be allowed.").allowed(),
|
||||
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/foo.c", "**/*.?", "A file when matching against required single-character extension when matching should be ignored.").ignored(),
|
||||
new CodegenIgnoreProcessorTest("docs/1/2/3/foo.cc", "**/*.?", "A file when matching against required single-character extension when non-matching should be allowed.").allowed()
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user