From a4806125954b5e97cc840c23ecc0fb6115b0e5a6 Mon Sep 17 00:00:00 2001 From: kungfooman Date: Wed, 19 Jun 2024 15:57:01 +0200 Subject: [PATCH 1/4] Add unit test: test/typechecking/simple-ObjectPattern-typedef-input.mjs --- test/typechecking.json | 4 ++ .../simple-ObjectPattern-typedef-input.mjs | 30 +++++++++++++++ .../simple-ObjectPattern-typedef-output.mjs | 37 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 test/typechecking/simple-ObjectPattern-typedef-input.mjs create mode 100644 test/typechecking/simple-ObjectPattern-typedef-output.mjs diff --git a/test/typechecking.json b/test/typechecking.json index 73c2e69..7e90709 100644 --- a/test/typechecking.json +++ b/test/typechecking.json @@ -115,6 +115,10 @@ "input": "./test/typechecking/simple-ObjectPattern-input.mjs", "output": "./test/typechecking/simple-ObjectPattern-output.mjs" }, + { + "input": "./test/typechecking/simple-ObjectPattern-typedef-input.mjs", + "output": "./test/typechecking/simple-ObjectPattern-typedef-output.mjs" + }, { "input": "./test/typechecking/template-types-1-input.mjs", "output": "./test/typechecking/template-types-1-output.mjs" diff --git a/test/typechecking/simple-ObjectPattern-typedef-input.mjs b/test/typechecking/simple-ObjectPattern-typedef-input.mjs new file mode 100644 index 0000000..5938849 --- /dev/null +++ b/test/typechecking/simple-ObjectPattern-typedef-input.mjs @@ -0,0 +1,30 @@ +class Tokenizer { + /** + * Loads a pre-trained tokenizer from the given `pretrained_model_name_or_path`. + * + * @param {string} pretrained_model_name_or_path The path to the pre-trained tokenizer. + * @param {PretrainedTokenizerOptions} options Additional options for loading the tokenizer. + * + * @throws {Error} Throws an error if the tokenizer.json or tokenizer_config.json files are not found in the `pretrained_model_name_or_path`. + * @returns {Promise} A new instance of the `PreTrainedTokenizer` class. + */ + static async from_pretrained(pretrained_model_name_or_path, { + progress_callback = null, + config = null, + cache_dir = null, + local_files_only = false, + revision = 'main', + legacy = null, + } = {}) { + const info = await loadTokenizer(pretrained_model_name_or_path, { + progress_callback, + config, + cache_dir, + local_files_only, + revision, + legacy, + }); + // @ts-ignore + return new this(...info); + } +} diff --git a/test/typechecking/simple-ObjectPattern-typedef-output.mjs b/test/typechecking/simple-ObjectPattern-typedef-output.mjs new file mode 100644 index 0000000..0022d8b --- /dev/null +++ b/test/typechecking/simple-ObjectPattern-typedef-output.mjs @@ -0,0 +1,37 @@ +class Tokenizer { + /** + * Loads a pre-trained tokenizer from the given `pretrained_model_name_or_path`. + * + * @param {string} pretrained_model_name_or_path The path to the pre-trained tokenizer. + * @param {PretrainedTokenizerOptions} options Additional options for loading the tokenizer. + * + * @throws {Error} Throws an error if the tokenizer.json or tokenizer_config.json files are not found in the `pretrained_model_name_or_path`. + * @returns {Promise} A new instance of the `PreTrainedTokenizer` class. + */ + static async from_pretrained(pretrained_model_name_or_path, { + progress_callback = null, + config = null, + cache_dir = null, + local_files_only = false, + revision = 'main', + legacy = null, + } = {}) { + if (!inspectType(pretrained_model_name_or_path, "string", 'Tokenizer#from_pretrained', 'pretrained_model_name_or_path')) { + youCanAddABreakpointHere(); + } + if (!inspectType(arguments[1], "PretrainedTokenizerOptions", 'Tokenizer#from_pretrained', 'options')) { + youCanAddABreakpointHere(); + } + const info = await loadTokenizer(pretrained_model_name_or_path, { + progress_callback, + config, + cache_dir, + local_files_only, + revision, + legacy, + }); + // @ts-ignore + return new this(...info); + } +} +registerClass(Tokenizer); From d89353995b9433cd0acc34ba49d3e6d1df8ffe42 Mon Sep 17 00:00:00 2001 From: kungfooman Date: Wed, 19 Jun 2024 16:01:52 +0200 Subject: [PATCH 2/4] Asserter#generateTypeChecks: Handle @typedef's for ObjectPattern + more unit tests + nice names for potential warning --- src-transpiler/Asserter.js | 75 +++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/src-transpiler/Asserter.js b/src-transpiler/Asserter.js index f12c3a8..35ce80f 100644 --- a/src-transpiler/Asserter.js +++ b/src-transpiler/Asserter.js @@ -442,6 +442,7 @@ class Asserter extends Stringifier { //out += `${spaces}/*${spaces} node.type=${node.type}\n${spaces} // ${JSON.stringify(jsdoc)}\n${parent}\n${spaces}*/\n`; for (let name in params) { + let nameFancy = name; const type = params[name]; const hasParam = this.nodeHasParamName(node, name); if (!hasParam) { @@ -480,47 +481,53 @@ class Asserter extends Stringifier { } const t = JSON.stringify(type.elementType, null, 2).replaceAll('\n', '\n' + spaces); if (templates) { - out += `${spaces}if (!inspectTypeWithTemplates(${element.name}, ${t}, '${loc}', '${name}', rtiTemplates)) {\n`; + out += `${spaces}if (!inspectTypeWithTemplates(${element.name}, ${t}, '${loc}', '${nameFancy}', rtiTemplates)) {\n`; } else { - out += `${spaces}if (!inspectType(${element.name}, ${t}, '${loc}', '${name}')) {\n`; + out += `${spaces}if (!inspectType(${element.name}, ${t}, '${loc}', '${nameFancy}')) {\n`; } out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`; } continue; - } else if (param.left.type === 'ObjectPattern' && type.type === 'object') { - // Add a type assertion for each property of the ObjectPattern - for (const property of param.left.properties) { - if (property.key.type !== 'Identifier') { - this.warn('ObjectPattern> Only Identifier case handled right now'); - continue; - } - const keyName = property.key.name; - if (type.type !== 'object' || !type.properties) { - this.warn( - "missing subtype information in JSDoc> in type", - JSON.stringify(type, null, 2), - "for ObjectPattern:", this.toSource(property).trim() - ); - continue; - } - const subType = type.properties[keyName]; - if (!subType) { - this.warn("missing subtype information in JSDoc"); - continue; + } else if (param.left.type === 'ObjectPattern') { + if (type.type === 'object') { + // Add a type assertion for each property of the ObjectPattern + for (const property of param.left.properties) { + if (property.key.type !== 'Identifier') { + this.warn('ObjectPattern> Only Identifier case handled right now'); + continue; + } + const keyName = property.key.name; + if (type.type !== 'object' || !type.properties) { + this.warn( + "missing subtype information in JSDoc> in type", + JSON.stringify(type, null, 2), + "for ObjectPattern:", this.toSource(property).trim() + ); + continue; + } + const subType = type.properties[keyName]; + if (!subType) { + this.warn("missing subtype information in JSDoc"); + continue; + } + const t = JSON.stringify(subType, null, 2).replaceAll('\n', '\n' + spaces); + if (templates) { + out += `${spaces}if (!inspectTypeWithTemplates(${keyName}, ${t}, '${loc}', '${nameFancy}', rtiTemplates)) {\n`; + } else { + out += `${spaces}if (!inspectType(${keyName}, ${t}, '${loc}', '${nameFancy}')) {\n`; + } + out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`; } - const t = JSON.stringify(subType, null, 2).replaceAll('\n', '\n' + spaces); - if (templates) { - out += `${spaces}if (!inspectTypeWithTemplates(${keyName}, ${t}, '${loc}', '${name}', rtiTemplates)) {\n`; - } else { - out += `${spaces}if (!inspectType(${keyName}, ${t}, '${loc}', '${name}')) {\n`; - } - out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`; + continue; + } else if (typeof type === 'string') { + // The case when we have an ObjectPattern with a @typedef + name = `arguments[${paramIndex}]`; } + } else { + this.warn(`generateTypeChecks> ${loc}> todo implement`, + `AssignmentPattern for parameter ${name}`); continue; } - this.warn(`generateTypeChecks> ${loc}> todo implement`, - `AssignmentPattern for parameter ${name}`); - continue; } } else { const loc = this.getName(node); @@ -552,9 +559,9 @@ class Asserter extends Stringifier { first = false; } if (templates) { - out += `${spaces}if (${prevCheck}!inspectTypeWithTemplates(${name}, ${t}, '${loc}', '${name}', rtiTemplates)) {\n`; + out += `${spaces}if (${prevCheck}!inspectTypeWithTemplates(${name}, ${t}, '${loc}', '${nameFancy}', rtiTemplates)) {\n`; } else { - out += `${spaces}if (${prevCheck}!inspectType(${name}, ${t}, '${loc}', '${name}')) {\n`; + out += `${spaces}if (${prevCheck}!inspectType(${name}, ${t}, '${loc}', '${nameFancy}')) {\n`; } out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`; } From af50c4fc015fe4e7077835969dec4bea918ac552 Mon Sep 17 00:00:00 2001 From: kungfooman Date: Wed, 19 Jun 2024 16:04:52 +0200 Subject: [PATCH 3/4] Fix lint --- src-transpiler/Asserter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src-transpiler/Asserter.js b/src-transpiler/Asserter.js index 35ce80f..7fda1ff 100644 --- a/src-transpiler/Asserter.js +++ b/src-transpiler/Asserter.js @@ -442,8 +442,9 @@ class Asserter extends Stringifier { //out += `${spaces}/*${spaces} node.type=${node.type}\n${spaces} // ${JSON.stringify(jsdoc)}\n${parent}\n${spaces}*/\n`; for (let name in params) { - let nameFancy = name; const type = params[name]; + // Copy name for warnings, `name` may become `arguments[${paramIndex}]`. + const nameFancy = name; const hasParam = this.nodeHasParamName(node, name); if (!hasParam) { let testNode = node; From 951c55893036066df6a81814a6b19a62132a91ab Mon Sep 17 00:00:00 2001 From: kungfooman Date: Wed, 19 Jun 2024 16:06:02 +0200 Subject: [PATCH 4/4] Fix unit tests by using fancy/nice JSDoc `@param` name --- test/typechecking/functions-output.mjs | 2 +- test/typechecking/simple-ArrayPattern-output.mjs | 2 +- test/typechecking/simple-ObjectPattern-output.mjs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/typechecking/functions-output.mjs b/test/typechecking/functions-output.mjs index 305a2ab..76b9781 100644 --- a/test/typechecking/functions-output.mjs +++ b/test/typechecking/functions-output.mjs @@ -37,7 +37,7 @@ function fetchSomething(url, { "optional": true } } - }, 'fetchSomething', 'arguments[1]')) { + }, 'fetchSomething', 'options')) { youCanAddABreakpointHere(); } function inner() {} diff --git a/test/typechecking/simple-ArrayPattern-output.mjs b/test/typechecking/simple-ArrayPattern-output.mjs index d8be102..6ba265d 100644 --- a/test/typechecking/simple-ArrayPattern-output.mjs +++ b/test/typechecking/simple-ArrayPattern-output.mjs @@ -9,7 +9,7 @@ function center_to_corners_format([centerX, centerY, width, height]) { "type": "array", "elementType": "number", "optional": false - }, 'center_to_corners_format', 'arguments[0]')) { + }, 'center_to_corners_format', 'arr')) { youCanAddABreakpointHere(); } return [ diff --git a/test/typechecking/simple-ObjectPattern-output.mjs b/test/typechecking/simple-ObjectPattern-output.mjs index 5609591..805048d 100644 --- a/test/typechecking/simple-ObjectPattern-output.mjs +++ b/test/typechecking/simple-ObjectPattern-output.mjs @@ -37,7 +37,7 @@ function fetchSomething(url, { "optional": true } } - }, 'fetchSomething', 'arguments[1]')) { + }, 'fetchSomething', 'options')) { youCanAddABreakpointHere(); } console.log('fetchSomething>', {