Skip to content

Commit c55e87c

Browse files
committed
Generate schema for extension pack file
1 parent bc01d73 commit c55e87c

File tree

7 files changed

+111
-62
lines changed

7 files changed

+111
-62
lines changed

extensions/ql-vscode/scripts/generate-schemas.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ const schemas = [
2020
"extension-pack-metadata.schema.json",
2121
),
2222
},
23+
{
24+
path: join(
25+
extensionDirectory,
26+
"src",
27+
"model-editor",
28+
"model-extension-file.ts",
29+
),
30+
type: "ModelExtensionFile",
31+
schemaPath: join(
32+
extensionDirectory,
33+
"src",
34+
"model-editor",
35+
"model-extension-file.schema.json",
36+
),
37+
},
2338
];
2439

2540
async function generateSchemas() {

extensions/ql-vscode/src/model-editor/data-schema.json

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$ref": "#/definitions/ModelExtensionFile",
4+
"definitions": {
5+
"ModelExtensionFile": {
6+
"type": "object",
7+
"properties": {
8+
"extensions": {
9+
"type": "array",
10+
"items": {
11+
"$ref": "#/definitions/ModelExtension"
12+
}
13+
}
14+
},
15+
"required": ["extensions"]
16+
},
17+
"ModelExtension": {
18+
"type": "object",
19+
"properties": {
20+
"addsTo": {
21+
"$ref": "#/definitions/ExtensibleReference"
22+
},
23+
"data": {
24+
"type": "array",
25+
"items": {
26+
"$ref": "#/definitions/DataRow"
27+
}
28+
}
29+
},
30+
"required": ["addsTo", "data"]
31+
},
32+
"ExtensibleReference": {
33+
"type": "object",
34+
"properties": {
35+
"pack": {
36+
"type": "string"
37+
},
38+
"extensible": {
39+
"type": "string"
40+
}
41+
},
42+
"required": ["pack", "extensible"]
43+
},
44+
"DataRow": {
45+
"type": "array",
46+
"items": {
47+
"$ref": "#/definitions/DataTuple"
48+
}
49+
},
50+
"DataTuple": {
51+
"type": ["boolean", "number", "string"]
52+
}
53+
}
54+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type ExtensibleReference = {
2+
pack: string;
3+
extensible: string;
4+
};
5+
6+
export type DataTuple = boolean | number | string;
7+
8+
export type DataRow = DataTuple[];
9+
10+
export type ModelExtension = {
11+
addsTo: ExtensibleReference;
12+
data: DataRow[];
13+
};
14+
15+
export type ModelExtensionFile = {
16+
extensions: ModelExtension[];
17+
};

extensions/ql-vscode/src/model-editor/predicates.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import { ModeledMethod, ModeledMethodType, Provenance } from "./modeled-method";
2+
import { DataTuple } from "./model-extension-file";
23

34
export type ExtensiblePredicateDefinition = {
45
extensiblePredicate: string;
5-
generateMethodDefinition: (method: ModeledMethod) => Tuple[];
6-
readModeledMethod: (row: Tuple[]) => ModeledMethod;
6+
generateMethodDefinition: (method: ModeledMethod) => DataTuple[];
7+
readModeledMethod: (row: DataTuple[]) => ModeledMethod;
78

89
supportedKinds?: string[];
910
};
1011

11-
type Tuple = boolean | number | string;
12-
13-
function readRowToMethod(row: Tuple[]): string {
12+
function readRowToMethod(row: DataTuple[]): string {
1413
return `${row[0]}.${row[1]}#${row[3]}${row[4]}`;
1514
}
1615

extensions/ql-vscode/src/model-editor/yaml.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import {
77
extensiblePredicateDefinitions,
88
} from "./predicates";
99

10-
import * as dataSchemaJson from "./data-schema.json";
10+
import * as modelExtensionFileSchema from "./model-extension-file.schema.json";
1111
import { Mode } from "./shared/mode";
1212
import { assertNever } from "../common/helpers-pure";
13+
import { ModelExtensionFile } from "./model-extension-file";
1314

14-
const ajv = new Ajv({ allErrors: true });
15-
const dataSchemaValidate = ajv.compile(dataSchemaJson);
15+
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true });
16+
const modelExtensionFileSchemaValidate = ajv.compile(modelExtensionFileSchema);
1617

1718
function createDataProperty(
1819
methods: ModeledMethod[],
@@ -211,24 +212,29 @@ export function createFilenameForPackage(
211212
return `${prefix}${packageName}${suffix}.yml`;
212213
}
213214

214-
export function loadDataExtensionYaml(
215-
data: any,
216-
): Record<string, ModeledMethod> | undefined {
217-
dataSchemaValidate(data);
215+
function validateModelExtensionFile(data: unknown): data is ModelExtensionFile {
216+
modelExtensionFileSchemaValidate(data);
218217

219-
if (dataSchemaValidate.errors) {
218+
if (modelExtensionFileSchemaValidate.errors) {
220219
throw new Error(
221-
`Invalid data extension YAML: ${dataSchemaValidate.errors
220+
`Invalid data extension YAML: ${modelExtensionFileSchemaValidate.errors
222221
.map((error) => `${error.instancePath} ${error.message}`)
223222
.join(", ")}`,
224223
);
225224
}
226225

227-
const extensions = data.extensions;
228-
if (!Array.isArray(extensions)) {
226+
return true;
227+
}
228+
229+
export function loadDataExtensionYaml(
230+
data: unknown,
231+
): Record<string, ModeledMethod> | undefined {
232+
if (!validateModelExtensionFile(data)) {
229233
return undefined;
230234
}
231235

236+
const extensions = data.extensions;
237+
232238
const modeledMethods: Record<string, ModeledMethod> = {};
233239

234240
for (const extension of extensions) {

extensions/ql-vscode/test/vscode-tests/no-workspace/model-editor/auto-model-codeml-queries.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { pathExists, readFile } from "fs-extra";
2020
import { load as loadYaml } from "js-yaml";
2121
import { CancellationTokenSource } from "vscode-jsonrpc";
2222
import { QueryOutputDir } from "../../../../src/run-queries-shared";
23+
import { ModelExtensionFile } from "../../../../src/model-editor/model-extension-file";
2324

2425
describe("runAutoModelQueries", () => {
2526
let resolveQueriesSpy: jest.SpiedFunction<
@@ -186,7 +187,9 @@ describe("generateCandidateFilterPack", () => {
186187
const filterFile = join(packDir, "filter.yml");
187188
expect(await pathExists(filterFile)).toBe(true);
188189
// Read the contents of filterFile and parse as yaml
189-
const yaml = await loadYaml(await readFile(filterFile, "utf8"));
190+
const yaml = (await loadYaml(
191+
await readFile(filterFile, "utf8"),
192+
)) as ModelExtensionFile;
190193
const extensions = yaml.extensions;
191194
expect(extensions).toBeInstanceOf(Array);
192195
expect(extensions).toHaveLength(1);

0 commit comments

Comments
 (0)