closure-compiler
closure-compiler copied to clipboard
Bad type annotation when documenting an optional parameter value
With Closure Compiler v20210106 and the following flags:
--language_in=ECMASCRIPT_NEXT
--compilation_level ADVANCED
--js tmp/wrap.js
This works fine:
/**
* @param {string} str
* @param {string} [prefix=aa]
* @param {string} [suffix=bb]
*/
function wrap1(str, prefix="aa", suffix="bb") {
return prefix + str + suffix;
}
window.wrap1 = wrap1;
However this:
/**
* @param {string} str
* @param {string} [prefix=(]
* @param {string} [suffix=)]
*/
function wrap2(str, prefix="(", suffix=")") {
return prefix + str + suffix;
}
window.wrap2 = wrap2;
produces the following warnings:
tmp/wrap.js:12:27: WARNING - [JSC_TYPE_PARSE_ERROR] Bad type annotation. missing closing ] See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler for more information.
12| * @param {string} [prefix=(]
^
tmp/wrap.js:13:27: WARNING - [JSC_TYPE_PARSE_ERROR] Bad type annotation. missing closing ] See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler for more information.
13| * @param {string} [suffix=)]
^
0 error(s), 2 warning(s), 100.0% typed
It looks like the compiler is confused about the sequence of opening and closing "brackets". However in this case both ( and ) are the default values for prefix and suffix. To verify this theory I've created wrap3 with both prefix and suffix defaulting to ] so as to make it look like the sequence is "complete":
/**
* @param {string} str
* @param {string} [prefix=]]
* @param {string} [suffix=]]
*/
function wrap3(str, prefix="]", suffix="]") {
return prefix + str + suffix;
}
window.wrap3 = wrap3;
The above function generates no warnings or errors.
Complete file:
/**
* @param {string} str
* @param {string} [prefix=aa]
* @param {string} [suffix=bb]
*/
function wrap1(str, prefix="aa", suffix="bb") {
return prefix + str + suffix;
}
/**
* @param {string} str
* @param {string} [prefix=(]
* @param {string} [suffix=)]
*/
function wrap2(str, prefix="(", suffix=")") {
return prefix + str + suffix;
}
/**
* @param {string} str
* @param {string} [prefix=]]
* @param {string} [suffix=]]
*/
function wrap3(str, prefix="]", suffix="]") {
return prefix + str + suffix;
}
window.wrap1 = wrap1;
window.wrap2 = wrap2;
window.wrap3 = wrap3;
Wow. I didn't know the compiler would even allow this syntax of putting the parameter's name in square brackets.
If you also supply the "=default" part AFAICT the compiler completely throws that away.
The only test for this syntax is called testUnsupportedJsDocSyntax1()
https://github.com/google/closure-compiler/blob/3ff3fd061e164dbd825def388d53f3c63d341ed4/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java#L5073
I'm guessing that this [name=defaultValue] syntax is something that exists in the OpenSource JSDoc standard,
which is definitely not the same as the JSDoc that closure-compiler uses.
I think some little effort must have been made to support this bit of that syntax years ago.
Unsurprisingly, there's a bug in it.
I'm guessing that this [name=defaultValue] syntax is something that exists in the OpenSource JSDoc standard,
I believe that's right.
When I run yarn -s jsdoc -X tmp/wrap.js it produces no warnings or errors. In case it helps here's an example of what JSDoc produces:
{
"comment": "/**\n * @param {string} str\n * @param {string} [prefix=(]\n * @param {string} [suffix=)]\n */",
"meta": {
"range": [
267,
346
],
"filename": "wrap.js",
"lineno": 15,
"columnno": 0,
"path": "/workspace/dev/tmp",
"code": {
"id": "astnode100000018",
"name": "wrap2",
"type": "FunctionDeclaration",
"paramnames": [
"str",
"prefix",
"suffix"
]
}
},
"params": [
{
"type": {
"names": [
"string"
]
},
"name": "str"
},
{
"type": {
"names": [
"string"
]
},
"optional": true,
"defaultvalue": "(",
"name": "prefix"
},
{
"type": {
"names": [
"string"
]
},
"optional": true,
"defaultvalue": ")",
"name": "suffix"
}
],
"name": "wrap2",
"longname": "wrap2",
"kind": "function",
"scope": "global"
}