Skip to content

Commit fb2391e

Browse files
committed
Fix infinite looping bug.
1 parent ee902e1 commit fb2391e

File tree

5 files changed

+36
-21
lines changed

5 files changed

+36
-21
lines changed

compute-suppressions.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# - path: "definitions/OperationListResult/type"
2-
# reason: "Common type"
1+
- path: "definitions/OperationListResult/type"
2+
reason: "Common type"
33
- path: "definitions/Operation/properties/display/type"
44
reason: "Common type"

src/definitions.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getRegistryName,
99
} from "./util.js";
1010
import path from "path";
11+
import { DiffClient } from "./diff-client.js";
1112

1213
/** The registry to look up the name within. */
1314
export enum RegistryKind {
@@ -87,10 +88,10 @@ export class DefinitionRegistry {
8788
private providedPaths = new Set<string>();
8889
private referenceStack: string[] = [];
8990
private referenceMap = new Map<string, Set<string>>();
90-
private currentPath: string | undefined;
91-
private args: any;
91+
private currentPath: string[];
92+
private client: DiffClient;
9293

93-
constructor(map: Map<string, OpenAPIV2.Document>, args: any) {
94+
constructor(map: Map<string, OpenAPIV2.Document>, client: DiffClient) {
9495
this.data = {
9596
definitions: new CollectionRegistry(
9697
map,
@@ -116,9 +117,9 @@ export class DefinitionRegistry {
116117
for (const key of map.keys()) {
117118
this.providedPaths.add(path.normalize(key));
118119
}
119-
this.currentPath;
120+
this.currentPath = [];
121+
this.client = client;
120122
this.#gatherDefinitions(map);
121-
this.args = args;
122123
this.#expandReferences();
123124
}
124125

@@ -131,7 +132,6 @@ export class DefinitionRegistry {
131132
if (!refResult) {
132133
return item;
133134
}
134-
// FIXME: Need to proprogate suppressions here too
135135
let match = this.get(refResult);
136136
if (match) {
137137
if (this.referenceStack.includes(refResult.name)) {
@@ -161,7 +161,9 @@ export class DefinitionRegistry {
161161
this.#expandDerivedClasses(item);
162162
this.#expandAllOf(item);
163163
for (const [propName, propValue] of toSorted(Object.entries(item))) {
164+
this.currentPath.push(propName);
164165
expanded[propName] = this.#expand(propValue);
166+
this.currentPath.pop();
165167
}
166168
return expanded;
167169
}
@@ -218,7 +220,10 @@ export class DefinitionRegistry {
218220
const itemVal = item[key];
219221
switch (key) {
220222
case "required":
221-
base[key] = (baseVal ?? []).concat(itemVal ?? []);
223+
const mergedRequired = new Set(
224+
(baseVal ?? []).concat(itemVal ?? [])
225+
);
226+
base[key] = [...mergedRequired];
222227
break;
223228
case "properties":
224229
base[key] = { ...(baseVal ?? {}), ...(itemVal ?? {}) };
@@ -296,10 +301,11 @@ export class DefinitionRegistry {
296301
#expandReferencesForCollection(collection: CollectionRegistry) {
297302
this.referenceStack = [];
298303
for (const [filepath, values] of collection.data.entries()) {
299-
this.currentPath = filepath;
300304
for (const [key, value] of values.entries()) {
305+
this.currentPath.push(key);
301306
let expanded = this.#expand(value, key, filepath);
302307
collection.data.get(filepath)!.set(key, expanded);
308+
this.currentPath.pop();
303309
}
304310
}
305311
// replace $derivedClasses with $anyOf that contains the expansions of the derived classes
@@ -312,10 +318,18 @@ export class DefinitionRegistry {
312318
}
313319

314320
#expandReferences() {
321+
this.currentPath.push("definitions");
315322
this.#expandReferencesForCollection(this.data.definitions);
323+
this.currentPath.pop();
324+
this.currentPath.push("parameters");
316325
this.#expandReferencesForCollection(this.data.parameters);
326+
this.currentPath.pop();
327+
this.currentPath.push("responses");
317328
this.#expandReferencesForCollection(this.data.responses);
329+
this.currentPath.pop();
330+
this.currentPath.push("securityDefinitions");
318331
this.#expandReferencesForCollection(this.data.securityDefinitions);
332+
this.currentPath.pop();
319333
}
320334

321335
/**

src/diff-client.ts

-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { RegistryKind } from "./definitions.js";
1313
import * as fs from "fs";
1414
import path from "path";
1515
import { SuppressionRegistry } from "./suppression.js";
16-
import { HtmlDiffClient } from "./html-diff.js";
1716

1817
export interface DiffClientConfig {
1918
lhs: string | string[];
@@ -53,7 +52,6 @@ export class DiffClient {
5352
const lhsRoot = client.args["lhs-root"]
5453
? path.resolve(client.args["lhs-root"])
5554
: undefined;
56-
5755
let rhsRoot = client.args["rhs-root"]
5856
? path.resolve(client.args["rhs-root"])
5957
: undefined;

src/suppression.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,15 @@ export class SuppressionRegistry {
3939
has(path: string | undefined): boolean {
4040
if (!path) return false;
4141
path = path.trim().toLowerCase();
42-
const value = this.data.has(path);
43-
return value;
42+
return this.data.has(path);
4443
}
4544

4645
propagateSuppression(ref: ReferenceMetadata, basePath: string[] | undefined) {
4746
if (!basePath) throw new Error("basePath is undefined");
4847
const base = basePath.join("/");
4948
const target = `${getRegistryName(ref.registry)}/${ref.name}`.toLowerCase();
50-
if (target == "definitions/operation") {
51-
let test = "best";
52-
}
5349
for (const item of this.data) {
54-
if (item.startsWith(target)) {
50+
if (item === target || item.startsWith(`${target}/`)) {
5551
// create a new string suppression propagating the suppression onto the base path
5652
const newItem = item.replace(target, base);
5753
this.add(newItem);

test/rest-api-diff.test.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,21 @@ it("should propagate suppressions that are expanded while collecting definitions
310310
args: {
311311
suppressions: "test/files/suppressions2.yaml",
312312
},
313-
rules: [],
313+
rules: getApplicableRules({}),
314314
};
315315
const client = await TestableDiffClient.create(config);
316316
client.parse();
317317
client.processDiff();
318-
expect(client.diffResults?.flaggedViolations.length).toBe(0);
319-
expect(client.diffResults?.noViolations.length).toBe(0);
318+
client.buildOutput();
319+
const [lhsParser, rhsParser] = client.getParsers();
320+
expect(lhsParser.getUnresolvedReferences().length).toBe(0);
321+
expect(lhsParser.getUnreferencedTotal()).toBe(0);
322+
expect(rhsParser.getUnresolvedReferences().length).toBe(0);
323+
expect(rhsParser.getUnreferencedTotal()).toBe(0);
320324
expect(client.diffResults?.assumedViolations.length).toBe(0);
325+
expect(client.diffResults?.flaggedViolations.length).toBe(0);
326+
expect(client.diffResults?.suppressedViolations.length).toBe(2);
327+
expect(client.diffResults?.noViolations.length).toBe(2);
321328
});
322329

323330
it("should sort arrays of strings for stable comparison", async () => {

0 commit comments

Comments
 (0)