in lib/swaggerValidator/semanticValidator.ts [455:551]
private async validateOperation(spec: SwaggerSpec, errors: SemanticErrorDetail[]) {
const visitedOperationId = new Set<string>();
const visitedPathTemplate = new Set<string>();
const url = spec._filePath;
const pathArgs = new Set<string>();
let pathParams: Parameter[] | undefined;
traverseSwagger(spec, {
onPath: (path) => {
pathArgs.clear();
pathParams = path.parameters;
const pathTemplate = path._pathTemplate;
let normalizedPath = pathTemplate;
const argMatches = normalizedPath.match(/\{.*?\}/g);
let idx = 0;
for (const arg of argMatches ?? []) {
if (arg === "{}") {
const meta = getOavErrorMeta("EMPTY_PATH_PARAMETER_DECLARATION", { pathTemplate });
this.addErrorsFromErrorCode(errors, url, meta, path);
} else {
normalizedPath = normalizedPath.replace(arg, `arg${idx}`);
++idx;
pathArgs.add(arg.substr(1, arg.length - 2));
}
}
if (visitedPathTemplate.has(normalizedPath)) {
const meta = getOavErrorMeta("EQUIVALENT_PATH", { pathTemplate });
this.addErrorsFromErrorCode(errors, url, meta, path);
}
visitedPathTemplate.add(normalizedPath);
},
onOperation: (operation) => {
let bodyParam: Parameter | undefined;
const requiredPathArgs = new Set(pathArgs);
const visitedParamName = new Set<string>();
const { operationId, parameters, consumes } = operation;
const mergedParameters = [...(parameters ?? []), ...(pathParams ?? [])];
if (operationId !== undefined) {
if (visitedOperationId.has(operationId)) {
const meta = getOavErrorMeta("DUPLICATE_OPERATIONID", { operationId });
this.addErrorsFromErrorCode(errors, url, meta, operation);
} else {
visitedOperationId.add(operationId);
}
}
for (const p of mergedParameters) {
const param = this.jsonLoader.resolveRefObj(p);
const { name } = param;
if (visitedParamName.has(name)) {
const meta = getOavErrorMeta("DUPLICATE_PARAMETER", { name });
this.addErrorsFromErrorCode(errors, url, meta, operation);
}
visitedParamName.add(name);
if (param.in === "body" || param.in === "formData") {
if (bodyParam !== undefined) {
const meta = getOavErrorMeta(
param.in === bodyParam.in
? "MULTIPLE_BODY_PARAMETERS"
: "INVALID_PARAMETER_COMBINATION",
{}
);
if (
!(
meta.code === "MULTIPLE_BODY_PARAMETERS" &&
param.in === "formData" &&
consumes !== undefined &&
consumes.includes("multipart/form-data")
)
) {
this.addErrorsFromErrorCode(errors, url, meta, operation);
}
}
bodyParam = param;
}
if (param.in === "path") {
if (!requiredPathArgs.has(name)) {
const meta = getOavErrorMeta("MISSING_PATH_PARAMETER_DECLARATION", { name });
this.addErrorsFromErrorCode(errors, url, meta, operation);
}
requiredPathArgs.delete(name);
}
}
for (const name of requiredPathArgs) {
const meta = getOavErrorMeta("MISSING_PATH_PARAMETER_DEFINITION", { name });
this.addErrorsFromErrorCode(errors, url, meta, operation);
}
},
});
}