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.
|
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
|
### 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:
|
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;
|
package io.swagger.codegen.ignore.rules;
|
||||||
|
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.*;
|
||||||
import java.nio.file.PathMatcher;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DirectoryRule extends FileRule {
|
public class DirectoryRule extends FileRule {
|
||||||
|
|
||||||
private PathMatcher matcher = null;
|
private PathMatcher directoryMatcher = null;
|
||||||
|
private PathMatcher contentsMatcher = null;
|
||||||
|
|
||||||
DirectoryRule(List<Part> syntax, String definition) {
|
DirectoryRule(List<Part> syntax, String definition) {
|
||||||
super(syntax, 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
|
@Override
|
||||||
public Boolean matches(String relativePath) {
|
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++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} 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));
|
parts.add(new Part(Token.MATCH_ANY));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,141 @@
|
|||||||
package io.swagger.codegen.ignore;
|
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 {
|
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
|
@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
|
@Factory
|
||||||
public void getExclusionRules() throws Exception {
|
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