Skip to content

Commit 63fae2e

Browse files
committed
Handle array tuple notation
1 parent edd55ac commit 63fae2e

File tree

4 files changed

+215
-178
lines changed

4 files changed

+215
-178
lines changed

docs/parameterData.json

Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"paletteLerp": {
131131
"overloads": [
132132
[
133-
null,
133+
"[p5.Color|String|Number|Number[], Number][]",
134134
"Number"
135135
]
136136
]
@@ -844,7 +844,7 @@
844844
"keyIsDown": {
845845
"overloads": [
846846
[
847-
"Number"
847+
"Number|String"
848848
]
849849
]
850850
},
@@ -1324,6 +1324,9 @@
13241324
"Number",
13251325
"Number",
13261326
"Number"
1327+
],
1328+
[
1329+
"p5.Vector"
13271330
]
13281331
]
13291332
},
@@ -2748,6 +2751,33 @@
27482751
]
27492752
]
27502753
},
2754+
"createModel": {
2755+
"overloads": [
2756+
[
2757+
"String",
2758+
"String?",
2759+
"Boolean",
2760+
"function(p5.Geometry)?",
2761+
"function(Event)?"
2762+
],
2763+
[
2764+
"String",
2765+
"String?",
2766+
"function(p5.Geometry)?",
2767+
"function(Event)?"
2768+
],
2769+
[
2770+
"String",
2771+
"String?",
2772+
"Object?",
2773+
"function(p5.Geometry)?",
2774+
"function(Event)?",
2775+
"boolean?",
2776+
"boolean?",
2777+
"boolean?"
2778+
]
2779+
]
2780+
},
27512781
"loadShader": {
27522782
"overloads": [
27532783
[
@@ -2946,7 +2976,7 @@
29462976
"linePerspective": {
29472977
"overloads": [
29482978
[
2949-
"Boolean"
2979+
"boolean"
29502980
],
29512981
[]
29522982
]
@@ -3361,6 +3391,46 @@
33613391
]
33623392
}
33633393
},
3394+
"p5.Geometry": {
3395+
"flipV": {
3396+
"overloads": [
3397+
[]
3398+
]
3399+
},
3400+
"calculateBoundingBox": {
3401+
"overloads": [
3402+
[]
3403+
]
3404+
},
3405+
"clearColors": {
3406+
"overloads": [
3407+
[]
3408+
]
3409+
},
3410+
"flipU": {
3411+
"overloads": [
3412+
[]
3413+
]
3414+
},
3415+
"computeFaces": {
3416+
"overloads": [
3417+
[]
3418+
]
3419+
},
3420+
"computeNormals": {
3421+
"overloads": [
3422+
[
3423+
"FLAT|SMOOTH?",
3424+
"Object?"
3425+
]
3426+
]
3427+
},
3428+
"normalize": {
3429+
"overloads": [
3430+
[]
3431+
]
3432+
}
3433+
},
33643434
"p5.Color": {
33653435
"toString": {
33663436
"overloads": [
@@ -4267,11 +4337,6 @@
42674337
},
42684338
"sub": {
42694339
"overloads": [
4270-
[
4271-
"Number",
4272-
"Number?",
4273-
"Number?"
4274-
],
42754340
[
42764341
"p5.Vector|Number[]"
42774342
],
@@ -4284,9 +4349,6 @@
42844349
},
42854350
"mult": {
42864351
"overloads": [
4287-
[
4288-
"Number"
4289-
],
42904352
[
42914353
"Number",
42924354
"Number",
@@ -4395,18 +4457,6 @@
43954457
]
43964458
]
43974459
},
4398-
"dist": {
4399-
"overloads": [
4400-
[
4401-
"p5.Vector"
4402-
],
4403-
[],
4404-
[
4405-
"p5.Vector",
4406-
"p5.Vector"
4407-
]
4408-
]
4409-
},
44104460
"normalize": {
44114461
"overloads": [
44124462
[],
@@ -4582,6 +4632,15 @@
45824632
"overloads": [
45834633
[]
45844634
]
4635+
},
4636+
"dist": {
4637+
"overloads": [
4638+
[],
4639+
[
4640+
"p5.Vector",
4641+
"p5.Vector"
4642+
]
4643+
]
45854644
}
45864645
},
45874646
"p5.Camera": {
@@ -4758,46 +4817,6 @@
47584817
]
47594818
}
47604819
},
4761-
"p5.Geometry": {
4762-
"calculateBoundingBox": {
4763-
"overloads": [
4764-
[]
4765-
]
4766-
},
4767-
"clearColors": {
4768-
"overloads": [
4769-
[]
4770-
]
4771-
},
4772-
"flipU": {
4773-
"overloads": [
4774-
[]
4775-
]
4776-
},
4777-
"flipV": {
4778-
"overloads": [
4779-
[]
4780-
]
4781-
},
4782-
"computeFaces": {
4783-
"overloads": [
4784-
[]
4785-
]
4786-
},
4787-
"computeNormals": {
4788-
"overloads": [
4789-
[
4790-
"FLAT|SMOOTH?",
4791-
"Object?"
4792-
]
4793-
]
4794-
},
4795-
"normalize": {
4796-
"overloads": [
4797-
[]
4798-
]
4799-
}
4800-
},
48014820
"p5.Shader": {
48024821
"version": {
48034822
"overloads": [

src/color/creating_reading.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ function creatingReading(p5, fn){
15381538
* <a href="/reference/p5/colorMode/">colorMode()</a>.
15391539
*
15401540
* @method paletteLerp
1541-
* @param {Array.<Array.<(p5.Color|String|Number|Number[]), Number>>} colors_stops color stops to interpolate from
1541+
* @param {Array<[(p5.Color|String|Number|Number[]), Number]>} colors_stops color stops to interpolate from
15421542
* @param {Number} amt number to use to interpolate relative to color stops
15431543
* @return {p5.Color} interpolated color.
15441544
*

src/core/friendly_errors/param_validator.js

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,19 @@ function validateParams(p5, fn, lifecycles) {
105105
return { funcName, funcClass };
106106
}
107107

108+
function validBracketNesting(type) {
109+
let level = 0;
110+
for (let i = 0; i < type.length; i++) {
111+
if (type[i] === '[') {
112+
level++;
113+
} else if (type[i] === ']') {
114+
level--;
115+
if (level < 0) return false;
116+
}
117+
}
118+
return level === 0;
119+
}
120+
108121
/**
109122
* This is a helper function that generates Zod schemas for a function based on
110123
* the parameter data from `docs/parameterData.json`.
@@ -139,11 +152,8 @@ function validateParams(p5, fn, lifecycles) {
139152
}
140153

141154
// Returns a schema for a single type, i.e. z.boolean() for `boolean`.
142-
const generateTypeSchema = type => {
143-
if (!type) return z.any();
144-
145-
const isArray = type.endsWith('[]');
146-
const baseType = isArray ? type.slice(0, -2) : type;
155+
const generateTypeSchema = baseType => {
156+
if (!baseType) return z.any();
147157

148158
let typeSchema;
149159

@@ -162,7 +172,7 @@ function validateParams(p5, fn, lifecycles) {
162172
typeSchema = z.function();
163173
}
164174
// All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
165-
else if (baseType.startsWith('p5')) {
175+
else if (/^p5\.[a-zA-Z0-9]+$/.exec(baseType) || baseType === 'p5') {
166176
const className = baseType.substring(baseType.indexOf('.') + 1);
167177
typeSchema = z.instanceof(p5Constructors[className]);
168178
}
@@ -171,7 +181,11 @@ function validateParams(p5, fn, lifecycles) {
171181
typeSchema = schemaMap[baseType];
172182
}
173183
// Tuple types
174-
else if (baseType.startsWith('[') && baseType.endsWith(']')) {
184+
else if (
185+
baseType.startsWith('[') &&
186+
baseType.endsWith(']') &&
187+
validBracketNesting(baseType.slice(1, -1))
188+
) {
175189
typeSchema = z.tuple(
176190
baseType
177191
.slice(1, -1)
@@ -182,21 +196,7 @@ function validateParams(p5, fn, lifecycles) {
182196
// JavaScript classes, e.g. Request
183197
else if (baseType.match(/^[A-Z]/) && baseType in window) {
184198
typeSchema = z.instanceof(window[baseType]);
185-
} else {
186-
throw new Error(`Unsupported type '${type}' in parameter validation. Please report this issue.`);
187199
}
188-
189-
return isArray ? z.array(typeSchema) : typeSchema;
190-
};
191-
192-
// Generate a schema for a single parameter. In the case where a parameter can
193-
// be of multiple types, `generateTypeSchema` is called for each type.
194-
const generateParamSchema = param => {
195-
const isOptional = param?.endsWith('?');
196-
param = param?.replace(/\?$/, '');
197-
198-
let schema;
199-
200200
// Generate a schema for a single parameter that can be of multiple
201201
// types / constants, i.e. `String|Number|Array`.
202202
//
@@ -206,15 +206,28 @@ function validateParams(p5, fn, lifecycles) {
206206
// our constants sometimes have numeric or non-primitive values.
207207
// 2) In some cases, the type can be constants or strings, making z.enum()
208208
// insufficient for the use case.
209-
if (param?.includes('|')) {
210-
const types = param.split('|');
211-
schema = z.union(types
209+
else if (baseType.includes('|') && baseType.split('|').every(t => validBracketNesting(t))) {
210+
const types = baseType.split('|');
211+
typeSchema = z.union(types
212212
.map(t => generateTypeSchema(t))
213213
.filter(s => s !== undefined));
214+
} else if (baseType.endsWith('[]')) {
215+
typeSchema = z.array(generateTypeSchema(baseType.slice(0, -2)));
214216
} else {
215-
schema = generateTypeSchema(param);
217+
throw new Error(`Unsupported type '${baseType}' in parameter validation. Please report this issue.`);
216218
}
217219

220+
return typeSchema;
221+
};
222+
223+
// Generate a schema for a single parameter. In the case where a parameter can
224+
// be of multiple types, `generateTypeSchema` is called for each type.
225+
const generateParamSchema = param => {
226+
const isOptional = param?.endsWith('?');
227+
param = param?.replace(/\?$/, '');
228+
229+
let schema = generateTypeSchema(param);
230+
218231
return isOptional ? schema.optional() : schema;
219232
};
220233

0 commit comments

Comments
 (0)