diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b1f73584c49..f5e5daca082 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24785,9 +24785,17 @@ namespace ts { return; } if (!containsArgumentsReference(decl)) { - error(node.name, - Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, - idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); + if (isQualifiedName(node.name)) { + error(node.name, + Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, + entityNameToString(node.name), + entityNameToString(node.name.left)); + } + else { + error(node.name, + Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, + idText(node.name)); + } } else if (findLast(getJSDocTags(decl), isJSDocParameterTag) === node && node.typeExpression && node.typeExpression.type && diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5bcaf448599..4e99c001d80 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4266,6 +4266,10 @@ "category": "Error", "code": 8031 }, + "Qualified name '{0}' is not allowed without a leading '@param {object} {1}'.": { + "category": "Error", + "code": 8032 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.errors.txt b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.errors.txt new file mode 100644 index 00000000000..8ee7b3ba989 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.js(2,20): error TS8032: Qualified name 'xyz.p' is not allowed without a leading '@param {object} xyz'. + + +==== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.js (1 errors) ==== + /** + * @param {number} xyz.p + ~~~~~ +!!! error TS8032: Qualified name 'xyz.p' is not allowed without a leading '@param {object} xyz'. + */ + function g(xyz) { + return xyz.p; + } \ No newline at end of file diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.symbols b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.symbols new file mode 100644 index 00000000000..d8a28a638ff --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.js === +/** + * @param {number} xyz.p + */ +function g(xyz) { +>g : Symbol(g, Decl(paramTagNestedWithoutTopLevelObject.js, 0, 0)) +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject.js, 3, 11)) + + return xyz.p; +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject.js, 3, 11)) +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.types b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.types new file mode 100644 index 00000000000..cc339b84b30 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.js === +/** + * @param {number} xyz.p + */ +function g(xyz) { +>g : (xyz: any) => any +>xyz : any + + return xyz.p; +>xyz.p : any +>xyz : any +>p : any +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.errors.txt b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.errors.txt new file mode 100644 index 00000000000..d3e94e1cff4 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.js(2,20): error TS8032: Qualified name 'xyz.bar' is not allowed without a leading '@param {object} xyz'. + + +==== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.js (1 errors) ==== + /** + * @param {object} xyz.bar + ~~~~~~~ +!!! error TS8032: Qualified name 'xyz.bar' is not allowed without a leading '@param {object} xyz'. + * @param {number} xyz.bar.p + */ + function g(xyz) { + return xyz.bar.p; + } \ No newline at end of file diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.symbols b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.symbols new file mode 100644 index 00000000000..e6acfb7cbc4 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.js === +/** + * @param {object} xyz.bar + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : Symbol(g, Decl(paramTagNestedWithoutTopLevelObject2.js, 0, 0)) +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject2.js, 4, 11)) + + return xyz.bar.p; +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject2.js, 4, 11)) +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.types b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.types new file mode 100644 index 00000000000..2f6598ffa2d --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject2.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.js === +/** + * @param {object} xyz.bar + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : (xyz: any) => any +>xyz : any + + return xyz.bar.p; +>xyz.bar.p : any +>xyz.bar : any +>xyz : any +>bar : any +>p : any +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.errors.txt b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.errors.txt new file mode 100644 index 00000000000..d73f35cfcb2 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.js(3,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + + +==== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.js (1 errors) ==== + /** + * @param {object} xyz + * @param {number} xyz.bar.p + ~~~~~~~~~ +!!! error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + */ + function g(xyz) { + return xyz.bar.p; + } \ No newline at end of file diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.symbols b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.symbols new file mode 100644 index 00000000000..a350edded90 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.js === +/** + * @param {object} xyz + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : Symbol(g, Decl(paramTagNestedWithoutTopLevelObject3.js, 0, 0)) +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject3.js, 4, 11)) + + return xyz.bar.p; +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject3.js, 4, 11)) +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.types b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.types new file mode 100644 index 00000000000..a2bb9ddf329 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject3.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.js === +/** + * @param {object} xyz + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : (xyz: any) => any +>xyz : any + + return xyz.bar.p; +>xyz.bar.p : any +>xyz.bar : any +>xyz : any +>bar : any +>p : any +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.errors.txt b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.errors.txt new file mode 100644 index 00000000000..74ca02ef006 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.js(2,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + + +==== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.js (1 errors) ==== + /** + * @param {number} xyz.bar.p + ~~~~~~~~~ +!!! error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + */ + function g(xyz) { + return xyz.bar.p; + } \ No newline at end of file diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.symbols b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.symbols new file mode 100644 index 00000000000..6f8e1ffa643 --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.js === +/** + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : Symbol(g, Decl(paramTagNestedWithoutTopLevelObject4.js, 0, 0)) +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject4.js, 3, 11)) + + return xyz.bar.p; +>xyz : Symbol(xyz, Decl(paramTagNestedWithoutTopLevelObject4.js, 3, 11)) +} diff --git a/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.types b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.types new file mode 100644 index 00000000000..8b9843bdbee --- /dev/null +++ b/tests/baselines/reference/paramTagNestedWithoutTopLevelObject4.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.js === +/** + * @param {number} xyz.bar.p + */ +function g(xyz) { +>g : (xyz: any) => any +>xyz : any + + return xyz.bar.p; +>xyz.bar.p : any +>xyz.bar : any +>xyz : any +>bar : any +>p : any +} diff --git a/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.ts b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.ts new file mode 100644 index 00000000000..03c79ce9e1c --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject.ts @@ -0,0 +1,11 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: paramTagNestedWithoutTopLevelObject.js + +/** + * @param {number} xyz.p + */ +function g(xyz) { + return xyz.p; +} \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.ts b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.ts new file mode 100644 index 00000000000..a6a68aa0861 --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject2.ts @@ -0,0 +1,12 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: paramTagNestedWithoutTopLevelObject2.js + +/** + * @param {object} xyz.bar + * @param {number} xyz.bar.p + */ +function g(xyz) { + return xyz.bar.p; +} \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.ts b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.ts new file mode 100644 index 00000000000..8307688a0cd --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject3.ts @@ -0,0 +1,12 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: paramTagNestedWithoutTopLevelObject3.js + +/** + * @param {object} xyz + * @param {number} xyz.bar.p + */ +function g(xyz) { + return xyz.bar.p; +} \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.ts b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.ts new file mode 100644 index 00000000000..5840308fa0d --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagNestedWithoutTopLevelObject4.ts @@ -0,0 +1,11 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: paramTagNestedWithoutTopLevelObject4.js + +/** + * @param {number} xyz.bar.p + */ +function g(xyz) { + return xyz.bar.p; +} \ No newline at end of file