forked from loafle/openapi-generator-original
Merge pull request #2899 from jimschubert/feature/codegen-ignore
Feature/codegen ignore
This commit is contained in:
commit
624e8ae41f
@ -99,6 +99,16 @@ public abstract class AbstractGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public String readResourceContents(String resourceFilePath) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Scanner scanner = new Scanner(this.getClass().getResourceAsStream(getCPResourcePath(resourceFilePath)), "UTF-8");
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
sb.append(line).append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean embeddedTemplateExists(String name) {
|
||||
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
|
||||
}
|
||||
|
@ -184,4 +184,5 @@ public interface CodegenConfig {
|
||||
|
||||
String getHttpUserAgent();
|
||||
|
||||
String getCommonTemplateDir();
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ public class DefaultCodegen {
|
||||
protected Map<String, String> modelDocTemplateFiles = new HashMap<String, String>();
|
||||
protected String templateDir;
|
||||
protected String embeddedTemplateDir;
|
||||
protected String commonTemplateDir = "_common";
|
||||
protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
|
||||
protected Map<String, Object> vendorExtensions = new HashMap<String, Object>();
|
||||
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
|
||||
@ -441,6 +442,14 @@ public class DefaultCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
public String getCommonTemplateDir() {
|
||||
return this.commonTemplateDir;
|
||||
}
|
||||
|
||||
public void setCommonTemplateDir(String commonTemplateDir) {
|
||||
this.commonTemplateDir = commonTemplateDir;
|
||||
}
|
||||
|
||||
public Map<String, String> apiDocTemplateFiles() {
|
||||
return apiDocTemplateFiles;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package io.swagger.codegen;
|
||||
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import com.samskivert.mustache.Template;
|
||||
import io.swagger.codegen.ignore.CodegenIgnoreProcessor;
|
||||
import io.swagger.models.*;
|
||||
import io.swagger.models.auth.OAuth2Definition;
|
||||
import io.swagger.models.auth.SecuritySchemeDefinition;
|
||||
@ -24,6 +25,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
protected CodegenConfig config;
|
||||
protected ClientOptInput opts;
|
||||
protected Swagger swagger;
|
||||
protected CodegenIgnoreProcessor ignoreProcessor;
|
||||
|
||||
@Override
|
||||
public Generator opts(ClientOptInput opts) {
|
||||
@ -31,8 +33,11 @@ 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());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -197,7 +202,6 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
String basePath = hostBuilder.toString();
|
||||
String basePathWithoutHost = swagger.getBasePath();
|
||||
|
||||
|
||||
// resolve inline models
|
||||
InlineModelResolver inlineModelResolver = new InlineModelResolver();
|
||||
inlineModelResolver.flatten(swagger);
|
||||
@ -305,19 +309,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
LOGGER.info("Skipped overwriting " + filename);
|
||||
continue;
|
||||
}
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
|
||||
File written = processTemplateToFile(models, templateName, filename);
|
||||
if(written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
writeToFile(filename, tmpl.execute(models));
|
||||
files.add(new File(filename));
|
||||
}
|
||||
|
||||
if(generateModelTests) {
|
||||
@ -330,19 +326,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
LOGGER.info("File exists. Skipped overwriting " + filename);
|
||||
continue;
|
||||
}
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
|
||||
File written = processTemplateToFile(models, templateName, filename);
|
||||
if (written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
writeToFile(filename, tmpl.execute(models));
|
||||
files.add(new File(filename));
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,19 +343,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
LOGGER.info("Skipped overwriting " + filename);
|
||||
continue;
|
||||
}
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
|
||||
File written = processTemplateToFile(models, templateName, filename);
|
||||
if (written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
writeToFile(filename, tmpl.execute(models));
|
||||
files.add(new File(filename));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -443,20 +423,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
continue;
|
||||
}
|
||||
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
File written = processTemplateToFile(operation, templateName, filename);
|
||||
if(written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
|
||||
writeToFile(filename, tmpl.execute(operation));
|
||||
files.add(new File(filename));
|
||||
}
|
||||
|
||||
if(generateApiTests) {
|
||||
@ -468,22 +438,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
LOGGER.info("File exists. Skipped overwriting " + filename);
|
||||
continue;
|
||||
}
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
|
||||
writeToFile(filename, tmpl.execute(operation));
|
||||
files.add(new File(filename));
|
||||
File written = processTemplateToFile(operation, templateName, filename);
|
||||
if (written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(generateApiDocumentation) {
|
||||
// to generate api documentation files
|
||||
@ -494,20 +456,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
continue;
|
||||
}
|
||||
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
File written = processTemplateToFile(operation, templateName, filename);
|
||||
if (written != null) {
|
||||
files.add(written);
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
|
||||
writeToFile(filename, tmpl.execute(operation));
|
||||
files.add(new File(filename));
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,6 +542,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
}
|
||||
}
|
||||
if(shouldGenerate) {
|
||||
if(ignoreProcessor.allowsFile(new File(outputFilename))) {
|
||||
if (templateFile.endsWith("mustache")) {
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
@ -627,16 +580,57 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
}
|
||||
files.add(outputFile);
|
||||
}
|
||||
} else {
|
||||
LOGGER.info("Skipped generation of " + outputFilename + " due to rule in .swagger-codegen-ignore");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not generate supporting file '" + support + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Consider .swagger-codegen-ignore a supporting file
|
||||
// Output .swagger-codegen-ignore if it doesn't exist and wasn't explicitly created by a generator
|
||||
final String swaggerCodegenIgnore = ".swagger-codegen-ignore";
|
||||
String ignoreFileNameTarget = config.outputFolder() + File.separator + swaggerCodegenIgnore;
|
||||
File ignoreFile = new File(ignoreFileNameTarget);
|
||||
if(!ignoreFile.exists()) {
|
||||
String ignoreFileNameSource = File.separator + config.getCommonTemplateDir() + File.separator + swaggerCodegenIgnore;
|
||||
String ignoreFileContents = readResourceContents(ignoreFileNameSource);
|
||||
try {
|
||||
writeToFile(ignoreFileNameTarget, ignoreFileContents);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not generate supporting file '" + swaggerCodegenIgnore + "'", e);
|
||||
}
|
||||
files.add(ignoreFile);
|
||||
}
|
||||
}
|
||||
config.processSwagger(swagger);
|
||||
return files;
|
||||
}
|
||||
|
||||
private File processTemplateToFile(Map<String, Object> templateData, String templateName, String outputFilename) throws IOException {
|
||||
if(ignoreProcessor.allowsFile(new File(outputFilename.replaceAll("//", "/")))) {
|
||||
String templateFile = getFullTemplateFile(config, templateName);
|
||||
String template = readTemplate(templateFile);
|
||||
Template tmpl = Mustache.compiler()
|
||||
.withLoader(new Mustache.TemplateLoader() {
|
||||
@Override
|
||||
public Reader getTemplate(String name) {
|
||||
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
|
||||
}
|
||||
})
|
||||
.defaultValue("")
|
||||
.compile(template);
|
||||
|
||||
writeToFile(outputFilename, tmpl.execute(templateData));
|
||||
return new File(outputFilename);
|
||||
}
|
||||
|
||||
LOGGER.info("Skipped generation of " + outputFilename + " due to rule in .swagger-codegen-ignore");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void processMimeTypes(List<String> mimeTypeList, Map<String, Object> operation, String source) {
|
||||
if (mimeTypeList != null && mimeTypeList.size() > 0) {
|
||||
List<Map<String, String>> c = new ArrayList<Map<String, String>>();
|
||||
|
@ -0,0 +1,134 @@
|
||||
package io.swagger.codegen.ignore;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.swagger.codegen.ignore.rules.DirectoryRule;
|
||||
import io.swagger.codegen.ignore.rules.Rule;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CodegenIgnoreProcessor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessor.class);
|
||||
private final String outputPath;
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadCodegenRules(File codegenIgnore) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(codegenIgnore))) {
|
||||
String line;
|
||||
|
||||
// NOTE: Comments that start with a : (e.g. //:) are pulled from git documentation for .gitignore
|
||||
// see: https://github.com/git/git/blob/90f7b16b3adc78d4bbabbd426fb69aa78c714f71/Documentation/gitignore.txt
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if(
|
||||
//: A blank line matches no files, so it can serve as a separator for readability.
|
||||
line.length() == 0
|
||||
) continue;
|
||||
|
||||
Rule rule = Rule.create(line);
|
||||
|
||||
// rule could be null here if it's a COMMENT, for example
|
||||
if(rule != null) {
|
||||
if (Boolean.TRUE.equals(rule.getNegated())) {
|
||||
inclusionRules.add(rule);
|
||||
} else {
|
||||
exclusionRules.add(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean allowsFile(File targetFile) {
|
||||
File file = new File(new File(this.outputPath).toURI().relativize(targetFile.toURI()).getPath());
|
||||
Boolean directoryExcluded = false;
|
||||
Boolean exclude = false;
|
||||
if(exclusionRules.size() == 0 && inclusionRules.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: We *must* process all exclusion rules
|
||||
for (int i = 0; i < exclusionRules.size(); i++) {
|
||||
Rule current = exclusionRules.get(i);
|
||||
Rule.Operation op = current.evaluate(file.getPath());
|
||||
|
||||
switch (op){
|
||||
case EXCLUDE:
|
||||
exclude = true;
|
||||
|
||||
// Include rule can't override rules that exclude a file by some parent directory.
|
||||
if(current instanceof DirectoryRule) {
|
||||
directoryExcluded = true;
|
||||
}
|
||||
break;
|
||||
case INCLUDE:
|
||||
// This won't happen here.
|
||||
break;
|
||||
case NOOP:
|
||||
break;
|
||||
case EXCLUDE_AND_TERMINATE:
|
||||
i = exclusionRules.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(exclude) {
|
||||
// Only need to process inclusion rules if we've been excluded
|
||||
for (int i = 0; exclude && i < inclusionRules.size(); i++) {
|
||||
Rule current = inclusionRules.get(i);
|
||||
Rule.Operation op = current.evaluate(file.getPath());
|
||||
|
||||
// At this point exclude=true means the file should be ignored.
|
||||
// op == INCLUDE means we have to flip that flag.
|
||||
if(op.equals(Rule.Operation.INCLUDE)) {
|
||||
if(current instanceof DirectoryRule && directoryExcluded) {
|
||||
// e.g
|
||||
// baz/
|
||||
// !foo/bar/baz/
|
||||
// NOTE: Possibly surprising side effect:
|
||||
// foo/bar/baz/
|
||||
// !bar/
|
||||
exclude = false;
|
||||
} else if (!directoryExcluded) {
|
||||
// e.g.
|
||||
// **/*.log
|
||||
// !ISSUE_1234.log
|
||||
exclude = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Boolean.FALSE.equals(exclude);
|
||||
}
|
||||
|
||||
public List<Rule> getInclusionRules() {
|
||||
return ImmutableList.copyOf(inclusionRules);
|
||||
}
|
||||
|
||||
public List<Rule> getExclusionRules() {
|
||||
return ImmutableList.copyOf(exclusionRules);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.List;
|
||||
|
||||
public class DirectoryRule extends FileRule {
|
||||
|
||||
private PathMatcher matcher = null;
|
||||
|
||||
DirectoryRule(List<Part> syntax, String definition) {
|
||||
super(syntax, definition);
|
||||
matcher = FileSystems.getDefault().getPathMatcher("glob:**/"+this.getPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
return matcher.matches(FileSystems.getDefault().getPath(relativePath));
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An ignore rule which matches everything.
|
||||
*/
|
||||
public class EverythingRule extends Rule {
|
||||
EverythingRule(List<Part> syntax, String definition) {
|
||||
super(syntax, definition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Operation getExcludeOperation(){ return Operation.EXCLUDE_AND_TERMINATE; }
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.List;
|
||||
|
||||
public class FileRule extends Rule {
|
||||
|
||||
private PathMatcher matcher = null;
|
||||
|
||||
FileRule(List<Part> syntax, String definition) {
|
||||
super(syntax, definition);
|
||||
matcher = FileSystems.getDefault().getPathMatcher("glob:"+this.getPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
return matcher.matches(FileSystems.getDefault().getPath(relativePath));
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IgnoreLineParser {
|
||||
enum Token {
|
||||
MATCH_ALL("**"),
|
||||
MATCH_ANY("*"),
|
||||
ESCAPED_EXCLAMATION("\\!"),
|
||||
ESCAPED_SPACE("\\ "),
|
||||
PATH_DELIM("/"),
|
||||
NEGATE("!"),
|
||||
TEXT(null),
|
||||
DIRECTORY_MARKER("/"),
|
||||
ROOTED_MARKER("/"),
|
||||
COMMENT(null);
|
||||
|
||||
private String pattern;
|
||||
|
||||
Token(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Comments that start with a : (e.g. //:) are pulled from git documentation for .gitignore
|
||||
// see: https://github.com/git/git/blob/90f7b16b3adc78d4bbabbd426fb69aa78c714f71/Documentation/gitignore.txt
|
||||
static List<Part> parse(String text) throws ParserException {
|
||||
List<Part> parts = new ArrayList<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String current = null;
|
||||
String next = null;
|
||||
|
||||
char[] characters = text.toCharArray();
|
||||
for (int i = 0, totalLength = characters.length; i < totalLength; i++) {
|
||||
char character = characters[i];
|
||||
current = String.valueOf(character);
|
||||
next = i < totalLength - 1 ? String.valueOf(characters[i + 1]) : null;
|
||||
|
||||
if (i == 0) {
|
||||
if ("#".equals(current)) {
|
||||
//: A line starting with # serves as a comment.
|
||||
parts.add(new Part(Token.COMMENT, text));
|
||||
i = totalLength; // rather than early return
|
||||
continue;
|
||||
} else if ("!".equals(current)) {
|
||||
if (i == totalLength - 1) {
|
||||
throw new ParserException("Negation with no negated pattern.");
|
||||
} else {
|
||||
parts.add(new Part(Token.NEGATE));
|
||||
continue;
|
||||
}
|
||||
} else if ("\\".equals(current) && "#".equals(next)) {
|
||||
//: Put a backslash ("`\`") in front of the first hash for patterns
|
||||
//: that begin with a hash.
|
||||
// NOTE: Just push forward and drop the escape character. Falls through to TEXT token.
|
||||
current = next;
|
||||
next = null;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (Token.MATCH_ANY.pattern.equals(current)) {
|
||||
|
||||
if (Token.MATCH_ANY.pattern.equals(next)) {
|
||||
// peek ahead for invalid pattern. Slightly inefficient, but acceptable.
|
||||
if ((i+2 < totalLength - 1) &&
|
||||
String.valueOf(characters[i+2]).equals(Token.MATCH_ANY.pattern)) {
|
||||
// It doesn't matter where we are in the pattern, *** is invalid.
|
||||
throw new ParserException("The pattern *** is invalid.");
|
||||
}
|
||||
|
||||
parts.add(new Part(Token.MATCH_ALL));
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
parts.add(new Part(Token.MATCH_ANY));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0 && Token.ROOTED_MARKER.pattern.equals(current)) {
|
||||
parts.add(new Part(Token.ROOTED_MARKER));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("\\".equals(current) && " ".equals(next)) {
|
||||
parts.add(new Part(Token.ESCAPED_SPACE));
|
||||
i++;
|
||||
continue;
|
||||
} else if ("\\".equals(current) && "!".equals(next)) {
|
||||
parts.add(new Part(Token.ESCAPED_EXCLAMATION));
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Token.PATH_DELIM.pattern.equals(current)) {
|
||||
if (i != totalLength - 1) {
|
||||
if (sb.length() > 0) {
|
||||
parts.add(new Part(Token.TEXT, sb.toString()));
|
||||
sb.delete(0, sb.length());
|
||||
}
|
||||
|
||||
parts.add(new Part(Token.PATH_DELIM));
|
||||
if(Token.PATH_DELIM.pattern.equals(next)) {
|
||||
// ignore doubled path delims. NOTE: doesn't do full lookahead, so /// will result in //
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
} else if (i == totalLength - 1) {
|
||||
parts.add(new Part(Token.TEXT, sb.toString()));
|
||||
sb.delete(0, sb.length());
|
||||
|
||||
parts.add(new Part(Token.DIRECTORY_MARKER));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(current);
|
||||
}
|
||||
|
||||
if (sb.length() > 0) {
|
||||
// NOTE: All spaces escaped spaces are a special token, ESCAPED_SPACE
|
||||
//: Trailing spaces are ignored unless they are quoted with backslash ("`\`")
|
||||
parts.add(new Part(Token.TEXT, sb.toString().trim()));
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InvalidRule extends Rule {
|
||||
private final String reason;
|
||||
|
||||
InvalidRule(List<Part> syntax, String definition, String reason) {
|
||||
super(syntax, definition);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation evaluate(String relativePath) {
|
||||
return Operation.NOOP;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
public class ParserException extends Exception {
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message. The
|
||||
* cause is not initialized, and may subsequently be initialized by
|
||||
* a call to {@link #initCause}.
|
||||
*
|
||||
* @param message the detail message. The detail message is saved for
|
||||
* later retrieval by the {@link #getMessage()} method.
|
||||
*/
|
||||
public ParserException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
class Part {
|
||||
private final IgnoreLineParser.Token token;
|
||||
private final String value;
|
||||
|
||||
public Part(IgnoreLineParser.Token token, String value) {
|
||||
this.token = token;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Part(IgnoreLineParser.Token token) {
|
||||
this.token = token;
|
||||
this.value = token.getPattern();
|
||||
}
|
||||
|
||||
public IgnoreLineParser.Token getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A special case rule which matches files only if they're located
|
||||
* in the same directory as the .swagger-codegen-ignore file.
|
||||
*/
|
||||
public class RootedFileRule extends Rule {
|
||||
private String definedFilename = null;
|
||||
private String definedExtension = null;
|
||||
|
||||
RootedFileRule(List<Part> syntax, String definition) {
|
||||
super(syntax, definition);
|
||||
|
||||
int separatorIndex = definition.lastIndexOf(".");
|
||||
definedFilename = getFilenamePart(definition, separatorIndex);
|
||||
definedExtension = getExtensionPart(definition, separatorIndex);
|
||||
}
|
||||
|
||||
private String getFilenamePart(final String input, int stopIndex){
|
||||
return input.substring('/' == input.charAt(0) ? 1 : 0, stopIndex > 0 ? stopIndex : input.length());
|
||||
}
|
||||
|
||||
private String getExtensionPart(final String input, int stopIndex) {
|
||||
return input.substring(stopIndex > 0 ? stopIndex+1: input.length(), input.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean matches(String relativePath) {
|
||||
// NOTE: Windows-style separator isn't supported, so File.pathSeparator would be incorrect here.
|
||||
// NOTE: lastIndexOf rather than contains because /file.txt is acceptable while path/file.txt is not.
|
||||
// relativePath will be passed by CodegenIgnoreProcessor and is relative to .codegen-ignore.
|
||||
boolean isSingleFile = relativePath.lastIndexOf("/") <= 0;
|
||||
|
||||
if(isSingleFile) {
|
||||
int separatorIndex = relativePath.lastIndexOf(".");
|
||||
final String filename = getFilenamePart(relativePath, separatorIndex);
|
||||
final String extension = getExtensionPart(relativePath, separatorIndex);
|
||||
boolean extensionMatches = definedExtension.equals(extension) || definedExtension.equals(IgnoreLineParser.Token.MATCH_ANY.getPattern());
|
||||
|
||||
if(extensionMatches && definedFilename.contains(IgnoreLineParser.Token.MATCH_ANY.getPattern())) {
|
||||
// TODO: Evaluate any other escape requirements here.
|
||||
Pattern regex = Pattern.compile(
|
||||
definedFilename
|
||||
.replaceAll(Pattern.quote("."), "\\\\Q.\\\\E")
|
||||
.replaceAll(Pattern.quote("*"), ".*?") // non-greedy match on 0+ any character
|
||||
);
|
||||
return regex.matcher(filename).matches();
|
||||
}
|
||||
|
||||
return extensionMatches && definedFilename.equals(filename);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Rule {
|
||||
|
||||
public enum Operation {EXCLUDE, INCLUDE, NOOP, EXCLUDE_AND_TERMINATE}
|
||||
|
||||
// The original rule
|
||||
private final String definition;
|
||||
|
||||
private final List<Part> syntax;
|
||||
|
||||
Rule(List<Part> syntax, String definition) {
|
||||
this.syntax = syntax;
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public abstract Boolean matches(String relativePath);
|
||||
|
||||
public String getDefinition() {
|
||||
return this.definition;
|
||||
}
|
||||
|
||||
protected String getPattern() {
|
||||
if(syntax == null) return this.definition;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < syntax.size(); i++) {
|
||||
Part current = syntax.get(i);
|
||||
|
||||
switch(current.getToken()){
|
||||
case MATCH_ALL:
|
||||
case MATCH_ANY:
|
||||
case ESCAPED_EXCLAMATION:
|
||||
case ESCAPED_SPACE:
|
||||
case PATH_DELIM:
|
||||
case TEXT:
|
||||
case DIRECTORY_MARKER:
|
||||
sb.append(current.getValue());
|
||||
break;
|
||||
case NEGATE:
|
||||
case ROOTED_MARKER:
|
||||
case COMMENT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the rule should be negated. !foo means foo should be removed from previous matches.
|
||||
* 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.
|
||||
*/
|
||||
public Boolean getNegated() {
|
||||
return this.syntax != null && this.syntax.size() > 0 && this.syntax.get(0).getToken() == IgnoreLineParser.Token.NEGATE;
|
||||
}
|
||||
|
||||
public Operation evaluate(String relativePath) {
|
||||
if (Boolean.TRUE.equals(matches(relativePath))) {
|
||||
if(Boolean.TRUE.equals(this.getNegated())) {
|
||||
return this.getIncludeOperation();
|
||||
}
|
||||
return this.getExcludeOperation();
|
||||
}
|
||||
return Operation.NOOP;
|
||||
}
|
||||
|
||||
protected Operation getIncludeOperation(){ return Operation.INCLUDE; }
|
||||
protected Operation getExcludeOperation(){ return Operation.EXCLUDE; }
|
||||
|
||||
public static Rule create(String definition) {
|
||||
// NOTE: Comments that start with a : (e.g. //:) are pulled from git documentation for .gitignore
|
||||
// see: https://github.com/git/git/blob/90f7b16b3adc78d4bbabbd426fb69aa78c714f71/Documentation/gitignore.txt
|
||||
Rule rule = null;
|
||||
if (definition.equals(".")) {
|
||||
return new InvalidRule(null, definition, "Pattern '.' is invalid.");
|
||||
} else if (definition.equals("!.")) {
|
||||
return new InvalidRule(null, definition, "Pattern '!.' is invalid.");
|
||||
} else if (definition.startsWith("..")) {
|
||||
return new InvalidRule(null, definition, "Pattern '..' is invalid.");
|
||||
}
|
||||
|
||||
try {
|
||||
List<Part> result = IgnoreLineParser.parse(definition);
|
||||
|
||||
Boolean directoryOnly = null;
|
||||
if (result.size() == 0) {
|
||||
return rule;
|
||||
} else if (result.size() == 1) {
|
||||
// single-character filename only
|
||||
Part part = result.get(0);
|
||||
if (IgnoreLineParser.Token.MATCH_ANY.equals(part.getToken())) {
|
||||
rule = new RootedFileRule(result, definition);
|
||||
} else {
|
||||
rule = new FileRule(result, definition);
|
||||
}
|
||||
} else {
|
||||
IgnoreLineParser.Token head = result.get(0).getToken();
|
||||
|
||||
//: An optional prefix "`!`" which negates the pattern; any
|
||||
//: matching file excluded by a previous pattern will become
|
||||
//: included again. It is not possible to re-include a file if a parent
|
||||
//: directory of that file is excluded. Git doesn't list excluded
|
||||
//: directories for performance reasons, so any patterns on contained
|
||||
//: files have no effect, no matter where they are defined.
|
||||
//: Put a backslash ("`\`") in front of the first "`!`" for patterns
|
||||
//: that begin with a literal "`!`", for example, "`\!important!.txt`".
|
||||
// see this.getNegated();
|
||||
|
||||
//: If the pattern ends with a slash, it is removed for the
|
||||
//: purpose of the following description, but it would only find
|
||||
//: a match with a directory. In other words, `foo/` will match a
|
||||
//: directory `foo` and paths underneath it, but will not match a
|
||||
//: regular file or a symbolic link `foo` (this is consistent
|
||||
//: with the way how pathspec works in general in Git).
|
||||
directoryOnly = IgnoreLineParser.Token.DIRECTORY_MARKER.equals(result.get(result.size() - 1).getToken());
|
||||
|
||||
if (directoryOnly) {
|
||||
rule = new DirectoryRule(result, definition);
|
||||
} else if (IgnoreLineParser.Token.PATH_DELIM.equals(head)) {
|
||||
//: A leading slash matches the beginning of the pathname.
|
||||
//: For example, "/{asterisk}.c" matches "cat-file.c" but not
|
||||
//: "mozilla-sha1/sha1.c".
|
||||
rule = new RootedFileRule(result, definition);
|
||||
} else {
|
||||
// case 1
|
||||
//: If the pattern does not contain a slash '/', Git treats it as
|
||||
//: a shell glob pattern and checks for a match against the
|
||||
//: pathname relative to the location of the `.gitignore` file
|
||||
//: (relative to the toplevel of the work tree if not from a
|
||||
//: `.gitignore` file).
|
||||
|
||||
// case 2
|
||||
//: Otherwise, Git treats the pattern as a shell glob suitable
|
||||
//: for consumption by fnmatch(3) with the FNM_PATHNAME flag:
|
||||
//: wildcards in the pattern will not match a / in the pathname.
|
||||
//: For example, "Documentation/{asterisk}.html" matches
|
||||
//: "Documentation/git.html" but not "Documentation/ppc/ppc.html"
|
||||
//: or "tools/perf/Documentation/perf.html".
|
||||
|
||||
|
||||
// case 3
|
||||
//: Two consecutive asterisks ("`**`") in patterns matched against
|
||||
//: full pathname may have special meaning:
|
||||
//:
|
||||
//: - A leading "`**`" followed by a slash means match in all
|
||||
//: directories. For example, "`**/foo`" matches file or directory
|
||||
//: "`foo`" anywhere, the same as pattern "`foo`". "`**/foo/bar`"
|
||||
//: matches file or directory "`bar`" anywhere that is directly
|
||||
//: under directory "`foo`".
|
||||
//:
|
||||
//: - A trailing "`/**`" matches everything inside. For example,
|
||||
//: "`abc/**`" matches all files inside directory "`abc`", relative
|
||||
//: to the location of the `.gitignore` file, with infinite depth.
|
||||
//:
|
||||
//: - A slash followed by two consecutive asterisks then a slash
|
||||
//: matches zero or more directories. For example, "`a/**/b`"
|
||||
//: matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
|
||||
//:
|
||||
//: - Other consecutive asterisks are considered invalid.
|
||||
rule = new FileRule(result, definition);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (ParserException e) {
|
||||
e.printStackTrace();
|
||||
return new InvalidRule(null, definition, e.getMessage());
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
# Swagger Codegen Ignore
|
||||
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# Thsi matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
@ -0,0 +1,21 @@
|
||||
package io.swagger.codegen.ignore;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class CodegenIgnoreProcessorTest {
|
||||
@Test
|
||||
public void loadCodegenRules() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInclusionRules() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getExclusionRules() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class FileRuleTest {
|
||||
@Test
|
||||
public void testMatchComplex() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "path/to/**/complex/*.txt";
|
||||
final String relativePath = "path/to/some/nested/complex/xyzzy.txt";
|
||||
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "path"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "to"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ALL),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "complex"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".txt")
|
||||
);
|
||||
|
||||
Rule rule = new FileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchComplex() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "path/to/**/complex/*.txt";
|
||||
final String relativePath = "path/to/some/nested/invalid/xyzzy.txt";
|
||||
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "path"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "to"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ALL),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "complex"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".txt")
|
||||
);
|
||||
|
||||
Rule rule = new FileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class IgnoreLineParserTest {
|
||||
private IgnoreLineParser.Token verifyInputToSingleToken(final String input, IgnoreLineParser.Token token) throws ParserException {
|
||||
// Act
|
||||
List<Part> result = IgnoreLineParser.parse(input);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(result.size(), 1);
|
||||
IgnoreLineParser.Token actual = result.get(0).getToken();
|
||||
assertEquals(actual, token);
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMatchAll() throws Exception {
|
||||
verifyInputToSingleToken("**", IgnoreLineParser.Token.MATCH_ALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMatchAny() throws Exception {
|
||||
verifyInputToSingleToken("*", IgnoreLineParser.Token.MATCH_ANY);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ParserException.class,
|
||||
expectedExceptionsMessageRegExp = "Negation with no negated pattern\\.")
|
||||
public void parseNegate() throws Exception {
|
||||
verifyInputToSingleToken("!", IgnoreLineParser.Token.NEGATE);
|
||||
|
||||
// Assert
|
||||
fail("Expected simple pattern '!' to throw a ParserException.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseComment() throws Exception {
|
||||
// Arrange
|
||||
final String input = "# This is a comment";
|
||||
Part actual = null;
|
||||
|
||||
// Act
|
||||
List<Part> result = IgnoreLineParser.parse(input);
|
||||
|
||||
// Assert
|
||||
assertEquals(result.size(), 1);
|
||||
actual = result.get(0);
|
||||
assertEquals(actual.getToken(), IgnoreLineParser.Token.COMMENT);
|
||||
assertEquals(actual.getValue(), input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseEscapedExclamation() throws Exception {
|
||||
final String input = "\\!";
|
||||
verifyInputToSingleToken(input, IgnoreLineParser.Token.ESCAPED_EXCLAMATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseEscapedSpace() throws Exception {
|
||||
final String input = "\\ ";
|
||||
verifyInputToSingleToken(input, IgnoreLineParser.Token.ESCAPED_SPACE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseDirectoryMarker() throws Exception {
|
||||
// Arrange
|
||||
final String input = "foo/";
|
||||
Part actual = null;
|
||||
|
||||
// Act
|
||||
List<Part> result = IgnoreLineParser.parse(input);
|
||||
|
||||
// Assert
|
||||
assertEquals(result.size(), 2);
|
||||
actual = result.get(0);
|
||||
assertEquals(actual.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(actual.getValue(), "foo");
|
||||
actual = result.get(1);
|
||||
assertEquals(actual.getToken(), IgnoreLineParser.Token.DIRECTORY_MARKER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseRooted() throws Exception {
|
||||
// Arrange
|
||||
final String input = "/abcd";
|
||||
Part actual = null;
|
||||
|
||||
// Act
|
||||
List<Part> result = IgnoreLineParser.parse(input);
|
||||
|
||||
// Assert
|
||||
assertEquals(result.size(), 2);
|
||||
actual = result.get(0);
|
||||
assertEquals(actual.getToken(), IgnoreLineParser.Token.ROOTED_MARKER);
|
||||
actual = result.get(1);
|
||||
assertEquals(actual.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(actual.getValue(), "abcd");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseComplex() throws Exception {
|
||||
// Arrange
|
||||
final String input = "**/abcd/**/foo/bar/sample.txt";
|
||||
Part current = null;
|
||||
|
||||
// Act
|
||||
Queue<Part> result = new LinkedList<>(IgnoreLineParser.parse(input));
|
||||
|
||||
// Assert
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.MATCH_ALL);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.PATH_DELIM);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(current.getValue(), "abcd");
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.PATH_DELIM);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.MATCH_ALL);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.PATH_DELIM);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(current.getValue(), "foo");
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.PATH_DELIM);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(current.getValue(), "bar");
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.PATH_DELIM);
|
||||
current = result.remove();
|
||||
assertEquals(current.getToken(), IgnoreLineParser.Token.TEXT);
|
||||
assertEquals(current.getValue(), "sample.txt");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ParserException.class,
|
||||
expectedExceptionsMessageRegExp = "The pattern \\*\\*\\* is invalid\\.")
|
||||
public void parseTripleStarPattern() throws Exception {
|
||||
// Arrange
|
||||
final String input = "should/throw/***/anywhere";
|
||||
|
||||
// Act
|
||||
List<Part> result = IgnoreLineParser.parse(input);
|
||||
|
||||
// Assert
|
||||
fail("Expected pattern containing '***' to throw a ParserException.");
|
||||
}
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
package io.swagger.codegen.ignore.rules;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class RootedFileRuleTest {
|
||||
@Test
|
||||
public void testMatchFilenameOnly() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo";
|
||||
final String relativePath = "foo";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchFilenameOnly() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo";
|
||||
final String relativePath = "bar";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchFilenameAndExtension() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo.txt";
|
||||
final String relativePath = "foo.txt";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchFilenameAndExtension() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo.txt";
|
||||
final String relativePath = "bar.baz";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchFilenameWithGlob() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*";
|
||||
final String relativePath = "foobarbaz";
|
||||
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY)
|
||||
);
|
||||
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchFilenameWithGlob() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*";
|
||||
final String relativePath = "boobarbaz";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY)
|
||||
);
|
||||
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchFilenameAndExtensionWithFilenameGlob() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*.txt";
|
||||
final String relativePath = "foobarbaz.txt";
|
||||
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".txt")
|
||||
);
|
||||
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchFilenameAndExtensionWithFilenameGlob() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*qux.txt";
|
||||
final String relativePath = "foobarbaz.txt";
|
||||
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "qux.txt")
|
||||
);
|
||||
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchFilenameAndExtensionWithExtensionGlob() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo.*";
|
||||
final String relativePath = "foo.bak";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo."),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY)
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchFilenameAndExtensionWithMultiplePeriods() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*.xyzzy.txt";
|
||||
final String relativePath = "foo.bar.baz.xyzzy.txt";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".xyzzy.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchFilenameAndExtensionWithMultiplePeriods() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/foo*.xyzzy.txt";
|
||||
final String relativePath = "foo.bar.baz.qux.txt";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".xyzzy.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchWithoutLeadingForwardSlash() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "foo*.xyzzy.txt";
|
||||
final String relativePath = "foo.bar.baz.xyzzy.txt";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "foo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".xyzzy.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertTrue(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesOnlyRooted() throws Exception {
|
||||
// Arrange
|
||||
final String definition = "/path/to/some/foo*.xyzzy.txt";
|
||||
final String relativePath = "foo.bar.baz.xyzzy.txt";
|
||||
final List<Part> syntax = Arrays.asList(
|
||||
new Part(IgnoreLineParser.Token.ROOTED_MARKER),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "path"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "to"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "some"),
|
||||
new Part(IgnoreLineParser.Token.PATH_DELIM),
|
||||
new Part(IgnoreLineParser.Token.TEXT, "oo"),
|
||||
new Part(IgnoreLineParser.Token.MATCH_ANY),
|
||||
new Part(IgnoreLineParser.Token.TEXT, ".xyzzy.txt")
|
||||
);
|
||||
Rule rule = new RootedFileRule(syntax, definition);
|
||||
Boolean actual = null;
|
||||
|
||||
// Act
|
||||
actual = rule.matches(relativePath);
|
||||
|
||||
// Assert
|
||||
assertFalse(actual);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user