diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 75b2f72d53..7068c27992 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -727,6 +727,7 @@ type Checker struct { unknownSignature *Signature resolvingSignature *Signature silentNeverSignature *Signature + cachedArgumentsReferenced map[*ast.Node]bool enumNumberIndexInfo *IndexInfo anyBaseTypeIndexInfo *IndexInfo patternAmbientModules []*ast.PatternAmbientModule @@ -1000,6 +1001,7 @@ func NewChecker(program Program) *Checker { c.unknownSignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.errorType, nil, 0) c.resolvingSignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.anyType, nil, 0) c.silentNeverSignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.silentNeverType, nil, 0) + c.cachedArgumentsReferenced = make(map[*ast.Node]bool) c.enumNumberIndexInfo = &IndexInfo{keyType: c.numberType, valueType: c.stringType, isReadonly: true} c.anyBaseTypeIndexInfo = &IndexInfo{keyType: c.stringType, valueType: c.anyType, isReadonly: false} c.emptyStringType = c.getStringLiteralType("") @@ -2554,6 +2556,7 @@ func (c *Checker) checkSignatureDeclaration(node *ast.Node) { c.checkGrammarFunctionLikeDeclaration(node) } c.checkTypeParameters(node.TypeParameters()) + c.checkUnmatchedJSDocParameters(node) c.checkSourceElements(node.Parameters()) returnTypeNode := node.Type() if returnTypeNode != nil { @@ -30520,6 +30523,43 @@ func (c *Checker) getRegularTypeOfExpression(expr *ast.Node) *Type { return c.getRegularTypeOfLiteralType(c.getTypeOfExpression(expr)) } +func (c *Checker) containsArgumentsReference(node *ast.Node) bool { + if node.Body() == nil { + return false + } + + if containsArguments, ok := c.cachedArgumentsReferenced[node]; ok { + return containsArguments + } + + var visit func(node *ast.Node) bool + visit = func(node *ast.Node) bool { + if node == nil { + return false + } + switch node.Kind { + case ast.KindIdentifier: + return node.Text() == c.argumentsSymbol.Name && c.IsArgumentsSymbol(c.getResolvedSymbol(node)) + case ast.KindPropertyDeclaration, ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor: + if ast.IsComputedPropertyName(node.Name()) { + return visit(node.Name()) + } + case ast.KindPropertyAccessExpression, ast.KindElementAccessExpression: + return visit(node.Expression()) + case ast.KindPropertyAssignment: + return visit(node.AsPropertyAssignment().Initializer) + } + if nodeStartsNewLexicalEnvironment(node) || ast.IsPartOfTypeNode(node) { + return false + } + return node.ForEachChild(visit) + } + + containsArguments := visit(node.Body()) + c.cachedArgumentsReferenced[node] = containsArguments + return containsArguments +} + func (c *Checker) GetTypeAtLocation(node *ast.Node) *Type { return c.getTypeOfNode(node) } diff --git a/internal/checker/jsdoc.go b/internal/checker/jsdoc.go new file mode 100644 index 0000000000..641c953e0e --- /dev/null +++ b/internal/checker/jsdoc.go @@ -0,0 +1,97 @@ +package checker + +import ( + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/collections" + "github.com/microsoft/typescript-go/internal/diagnostics" +) + +func (c *Checker) checkUnmatchedJSDocParameters(node *ast.Node) { + var jsdocParameters []*ast.Node + for _, tag := range getAllJSDocTags(node) { + if tag.Kind == ast.KindJSDocParameterTag { + name := tag.AsJSDocParameterOrPropertyTag().Name() + if ast.IsIdentifier(name) && len(name.Text()) == 0 { + continue + } + jsdocParameters = append(jsdocParameters, tag) + } + } + + if len(jsdocParameters) == 0 { + return + } + + isJs := ast.IsInJSFile(node) + parameters := collections.Set[string]{} + excludedParameters := collections.Set[int]{} + + for i, param := range node.Parameters() { + name := param.AsParameterDeclaration().Name() + if ast.IsIdentifier(name) { + parameters.Add(name.Text()) + } + if ast.IsBindingPattern(name) { + excludedParameters.Add(i) + } + } + if c.containsArgumentsReference(node) { + if isJs { + lastJSDocParamIndex := len(jsdocParameters) - 1 + lastJSDocParam := jsdocParameters[lastJSDocParamIndex].AsJSDocParameterOrPropertyTag() + if lastJSDocParam == nil || !ast.IsIdentifier(lastJSDocParam.Name()) { + return + } + if excludedParameters.Has(lastJSDocParamIndex) || parameters.Has(lastJSDocParam.Name().Text()) { + return + } + if lastJSDocParam.TypeExpression == nil || lastJSDocParam.TypeExpression.Type() == nil { + return + } + if c.isArrayType(c.getTypeFromTypeNode(lastJSDocParam.TypeExpression.Type())) { + return + } + c.error(lastJSDocParam.Name(), diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, lastJSDocParam.Name().Text()) + } + } else { + for index, tag := range jsdocParameters { + name := tag.AsJSDocParameterOrPropertyTag().Name() + isNameFirst := tag.AsJSDocParameterOrPropertyTag().IsNameFirst + + if excludedParameters.Has(index) || (ast.IsIdentifier(name) && parameters.Has(name.Text())) { + continue + } + + if ast.IsQualifiedName(name) { + if isJs { + c.error(name, diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, + entityNameToString(name), + entityNameToString(name.AsQualifiedName().Left), + ) + } + } else { + if !isNameFirst { + c.errorOrSuggestion(isJs, name, + diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, + name.Text(), + ) + } + } + } + } +} + +func getAllJSDocTags(node *ast.Node) []*ast.Node { + if node == nil { + return nil + } + jsdocs := node.JSDoc(nil) + if len(jsdocs) == 0 { + return nil + } + lastJSDoc := jsdocs[len(jsdocs)-1].AsJSDoc() + if lastJSDoc.Tags == nil { + return nil + } + return lastJSDoc.Tags.Nodes +} diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index 08b7ab1300..db5bab57f6 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -1952,3 +1952,12 @@ func ValueToString(value any) string { } panic("unhandled value type in valueToString") } + +func nodeStartsNewLexicalEnvironment(node *ast.Node) bool { + switch node.Kind { + case ast.KindConstructor, ast.KindFunctionExpression, ast.KindFunctionDeclaration, ast.KindArrowFunction, + ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindModuleDeclaration, ast.KindSourceFile: + return true + } + return false +} diff --git a/testdata/baselines/reference/submodule/compiler/jsdocParamTagInvalid.errors.txt b/testdata/baselines/reference/submodule/compiler/jsdocParamTagInvalid.errors.txt new file mode 100644 index 0000000000..08111e0dff --- /dev/null +++ b/testdata/baselines/reference/submodule/compiler/jsdocParamTagInvalid.errors.txt @@ -0,0 +1,9 @@ +/a.js(1,21): error TS8024: JSDoc '@param' tag has name 'colour', but there is no parameter with that name. + + +==== /a.js (1 errors) ==== + /** @param {string} colour */ + ~~~~~~ +!!! error TS8024: JSDoc '@param' tag has name 'colour', but there is no parameter with that name. + function f(color) {} + \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/jsdocParamTag2.errors.txt b/testdata/baselines/reference/submodule/conformance/jsdocParamTag2.errors.txt new file mode 100644 index 0000000000..f796c7c463 --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/jsdocParamTag2.errors.txt @@ -0,0 +1,80 @@ +0.js(70,20): error TS8024: JSDoc '@param' tag has name 'y', but there is no parameter with that name. + + +==== 0.js (1 errors) ==== + // Object literal syntax + /** + * @param {{a: string, b: string}} obj + * @param {string} x + */ + function good1({a, b}, x) {} + /** + * @param {{a: string, b: string}} obj + * @param {{c: number, d: number}} OBJECTION + */ + function good2({a, b}, {c, d}) {} + /** + * @param {number} x + * @param {{a: string, b: string}} obj + * @param {string} y + */ + function good3(x, {a, b}, y) {} + /** + * @param {{a: string, b: string}} obj + */ + function good4({a, b}) {} + + // nested object syntax + /** + * @param {Object} obj + * @param {string} obj.a - this is like the saddest way to specify a type + * @param {string} obj.b - but it sure does allow a lot of documentation + * @param {string} x + */ + function good5({a, b}, x) {} + /** + * @param {Object} obj + * @param {string} obj.a + * @param {string} obj.b - but it sure does allow a lot of documentation + * @param {Object} OBJECTION - documentation here too + * @param {string} OBJECTION.c + * @param {string} OBJECTION.d - meh + */ + function good6({a, b}, {c, d}) {} + /** + * @param {number} x + * @param {Object} obj + * @param {string} obj.a + * @param {string} obj.b + * @param {string} y + */ + function good7(x, {a, b}, y) {} + /** + * @param {Object} obj + * @param {string} obj.a + * @param {string} obj.b + */ + function good8({a, b}) {} + + /** + * @param {{ a: string }} argument + */ + function good9({ a }) { + console.log(arguments, a); + } + + /** + * @param {object} obj - this type gets ignored + * @param {string} obj.a + * @param {string} obj.b - and x's type gets used for both parameters + * @param {string} x + */ + function bad1(x, {a, b}) {} + /** + * @param {string} y - here, y's type gets ignored but obj's is fine + ~ +!!! error TS8024: JSDoc '@param' tag has name 'y', but there is no parameter with that name. + * @param {{a: string, b: string}} obj + */ + function bad2(x, {a, b}) {} + \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/jsdocParamTagTypeLiteral.errors.txt b/testdata/baselines/reference/submodule/conformance/jsdocParamTagTypeLiteral.errors.txt new file mode 100644 index 0000000000..7a62f459cb --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/jsdocParamTagTypeLiteral.errors.txt @@ -0,0 +1,78 @@ +0.js(3,20): error TS8024: JSDoc '@param' tag has name 'unrelated', but there is no parameter with that name. + + +==== 0.js (1 errors) ==== + /** + * @param {Object} notSpecial + * @param {string} unrelated - not actually related because it's not notSpecial.unrelated + ~~~~~~~~~ +!!! error TS8024: JSDoc '@param' tag has name 'unrelated', but there is no parameter with that name. + */ + function normal(notSpecial) { + notSpecial; // should just be 'Object' + } + normal(12); + + /** + * @param {Object} opts1 doc1 + * @param {string} opts1.x doc2 + * @param {string=} opts1.y doc3 + * @param {string} [opts1.z] doc4 + * @param {string} [opts1.w="hi"] doc5 + */ + function foo1(opts1) { + opts1.x; + } + + foo1({x: 'abc'}); + + /** + * @param {Object[]} opts2 + * @param {string} opts2[].anotherX + * @param {string=} opts2[].anotherY + */ + function foo2(/** @param opts2 bad idea theatre! */opts2) { + opts2[0].anotherX; + } + + foo2([{anotherX: "world"}]); + + /** + * @param {object} opts3 + * @param {string} opts3.x + */ + function foo3(opts3) { + opts3.x; + } + foo3({x: 'abc'}); + + /** + * @param {object[]} opts4 + * @param {string} opts4[].x + * @param {string=} opts4[].y + * @param {string} [opts4[].z] + * @param {string} [opts4[].w="hi"] + */ + function foo4(opts4) { + opts4[0].x; + } + + foo4([{ x: 'hi' }]); + + /** + * @param {object[]} opts5 - Let's test out some multiple nesting levels + * @param {string} opts5[].help - (This one is just normal) + * @param {object} opts5[].what - Look at us go! Here's the first nest! + * @param {string} opts5[].what.a - (Another normal one) + * @param {Object[]} opts5[].what.bad - Now we're nesting inside a nested type + * @param {string} opts5[].what.bad[].idea - I don't think you can get back out of this level... + * @param {boolean} opts5[].what.bad[].oh - Oh ... that's how you do it. + * @param {number} opts5[].unnest - Here we are almost all the way back at the beginning. + */ + function foo5(opts5) { + opts5[0].what.bad[0].idea; + opts5[0].unnest; + } + + foo5([{ help: "help", what: { a: 'a', bad: [{ idea: 'idea', oh: false }] }, unnest: 1 }]); + \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject.errors.txt b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject.errors.txt new file mode 100644 index 0000000000..0e39341eb7 --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject.errors.txt @@ -0,0 +1,12 @@ +paramTagNestedWithoutTopLevelObject.js(2,20): error TS8032: Qualified name 'xyz.p' is not allowed without a leading '@param {object} xyz'. + + +==== 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/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt new file mode 100644 index 0000000000..5d9862ad0d --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt @@ -0,0 +1,13 @@ +paramTagNestedWithoutTopLevelObject2.js(2,20): error TS8032: Qualified name 'xyz.bar' is not allowed without a leading '@param {object} xyz'. + + +==== 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/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt index 5d76f62a2f..2694186a29 100644 --- a/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt @@ -1,10 +1,13 @@ +paramTagNestedWithoutTopLevelObject3.js(3,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. paramTagNestedWithoutTopLevelObject3.js(6,16): error TS2339: Property 'bar' does not exist on type 'object'. -==== paramTagNestedWithoutTopLevelObject3.js (1 errors) ==== +==== paramTagNestedWithoutTopLevelObject3.js (2 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; diff --git a/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt new file mode 100644 index 0000000000..70876409c5 --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt @@ -0,0 +1,12 @@ +paramTagNestedWithoutTopLevelObject4.js(2,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + + +==== 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/testdata/baselines/reference/submodule/conformance/paramTagOnFunctionUsingArguments.errors.txt b/testdata/baselines/reference/submodule/conformance/paramTagOnFunctionUsingArguments.errors.txt index 498f8a5d39..6732e3de27 100644 --- a/testdata/baselines/reference/submodule/conformance/paramTagOnFunctionUsingArguments.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/paramTagOnFunctionUsingArguments.errors.txt @@ -1,11 +1,14 @@ +a.js(2,20): error TS8029: JSDoc '@param' tag has name 'first', but there is no parameter with that name. It would match 'arguments' if it had an array type. a.js(19,9): error TS2554: Expected 0 arguments, but got 3. ==== decls.d.ts (0 errors) ==== declare function factory(type: string): {}; -==== a.js (1 errors) ==== +==== a.js (2 errors) ==== /** * @param {string} first + ~~~~~ +!!! error TS8029: JSDoc '@param' tag has name 'first', but there is no parameter with that name. It would match 'arguments' if it had an array type. */ function concat(/* first, second, ... */) { var s = '' diff --git a/testdata/baselines/reference/submoduleAccepted/compiler/jsdocParamTagInvalid.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/compiler/jsdocParamTagInvalid.errors.txt.diff deleted file mode 100644 index 30185220ea..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/compiler/jsdocParamTagInvalid.errors.txt.diff +++ /dev/null @@ -1,13 +0,0 @@ ---- old.jsdocParamTagInvalid.errors.txt -+++ new.jsdocParamTagInvalid.errors.txt -@@= skipped -0, +0 lines =@@ --/a.js(1,21): error TS8024: JSDoc '@param' tag has name 'colour', but there is no parameter with that name. -- -- --==== /a.js (1 errors) ==== -- /** @param {string} colour */ -- ~~~~~~ --!!! error TS8024: JSDoc '@param' tag has name 'colour', but there is no parameter with that name. -- function f(color) {} -- -+ \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTag2.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTag2.errors.txt.diff index 1313a18a87..04a0106ed7 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTag2.errors.txt.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTag2.errors.txt.diff @@ -3,88 +3,22 @@ @@= skipped -0, +0 lines =@@ -0.js(68,19): error TS2339: Property 'a' does not exist on type 'String'. -0.js(68,22): error TS2339: Property 'b' does not exist on type 'String'. --0.js(70,20): error TS8024: JSDoc '@param' tag has name 'y', but there is no parameter with that name. -- -- + 0.js(70,20): error TS8024: JSDoc '@param' tag has name 'y', but there is no parameter with that name. + + -==== 0.js (3 errors) ==== -- // Object literal syntax -- /** -- * @param {{a: string, b: string}} obj -- * @param {string} x -- */ -- function good1({a, b}, x) {} -- /** -- * @param {{a: string, b: string}} obj -- * @param {{c: number, d: number}} OBJECTION -- */ -- function good2({a, b}, {c, d}) {} -- /** -- * @param {number} x -- * @param {{a: string, b: string}} obj -- * @param {string} y -- */ -- function good3(x, {a, b}, y) {} -- /** -- * @param {{a: string, b: string}} obj -- */ -- function good4({a, b}) {} -- -- // nested object syntax -- /** -- * @param {Object} obj -- * @param {string} obj.a - this is like the saddest way to specify a type -- * @param {string} obj.b - but it sure does allow a lot of documentation -- * @param {string} x -- */ -- function good5({a, b}, x) {} -- /** -- * @param {Object} obj -- * @param {string} obj.a -- * @param {string} obj.b - but it sure does allow a lot of documentation -- * @param {Object} OBJECTION - documentation here too -- * @param {string} OBJECTION.c -- * @param {string} OBJECTION.d - meh -- */ -- function good6({a, b}, {c, d}) {} -- /** -- * @param {number} x -- * @param {Object} obj -- * @param {string} obj.a -- * @param {string} obj.b -- * @param {string} y -- */ -- function good7(x, {a, b}, y) {} -- /** -- * @param {Object} obj -- * @param {string} obj.a -- * @param {string} obj.b -- */ -- function good8({a, b}) {} -- -- /** -- * @param {{ a: string }} argument -- */ -- function good9({ a }) { -- console.log(arguments, a); -- } -- -- /** -- * @param {object} obj - this type gets ignored -- * @param {string} obj.a -- * @param {string} obj.b - and x's type gets used for both parameters -- * @param {string} x -- */ -- function bad1(x, {a, b}) {} ++==== 0.js (1 errors) ==== + // Object literal syntax + /** + * @param {{a: string, b: string}} obj +@@= skipped -71, +69 lines =@@ + * @param {string} x + */ + function bad1(x, {a, b}) {} - ~ -!!! error TS2339: Property 'a' does not exist on type 'String'. - ~ -!!! error TS2339: Property 'b' does not exist on type 'String'. -- /** -- * @param {string} y - here, y's type gets ignored but obj's is fine -- ~ --!!! error TS8024: JSDoc '@param' tag has name 'y', but there is no parameter with that name. -- * @param {{a: string, b: string}} obj -- */ -- function bad2(x, {a, b}) {} -- -+ \ No newline at end of file + /** + * @param {string} y - here, y's type gets ignored but obj's is fine + ~ \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTagTypeLiteral.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTagTypeLiteral.errors.txt.diff deleted file mode 100644 index f0663667fa..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/conformance/jsdocParamTagTypeLiteral.errors.txt.diff +++ /dev/null @@ -1,82 +0,0 @@ ---- old.jsdocParamTagTypeLiteral.errors.txt -+++ new.jsdocParamTagTypeLiteral.errors.txt -@@= skipped -0, +0 lines =@@ --0.js(3,20): error TS8024: JSDoc '@param' tag has name 'unrelated', but there is no parameter with that name. -- -- --==== 0.js (1 errors) ==== -- /** -- * @param {Object} notSpecial -- * @param {string} unrelated - not actually related because it's not notSpecial.unrelated -- ~~~~~~~~~ --!!! error TS8024: JSDoc '@param' tag has name 'unrelated', but there is no parameter with that name. -- */ -- function normal(notSpecial) { -- notSpecial; // should just be 'Object' -- } -- normal(12); -- -- /** -- * @param {Object} opts1 doc1 -- * @param {string} opts1.x doc2 -- * @param {string=} opts1.y doc3 -- * @param {string} [opts1.z] doc4 -- * @param {string} [opts1.w="hi"] doc5 -- */ -- function foo1(opts1) { -- opts1.x; -- } -- -- foo1({x: 'abc'}); -- -- /** -- * @param {Object[]} opts2 -- * @param {string} opts2[].anotherX -- * @param {string=} opts2[].anotherY -- */ -- function foo2(/** @param opts2 bad idea theatre! */opts2) { -- opts2[0].anotherX; -- } -- -- foo2([{anotherX: "world"}]); -- -- /** -- * @param {object} opts3 -- * @param {string} opts3.x -- */ -- function foo3(opts3) { -- opts3.x; -- } -- foo3({x: 'abc'}); -- -- /** -- * @param {object[]} opts4 -- * @param {string} opts4[].x -- * @param {string=} opts4[].y -- * @param {string} [opts4[].z] -- * @param {string} [opts4[].w="hi"] -- */ -- function foo4(opts4) { -- opts4[0].x; -- } -- -- foo4([{ x: 'hi' }]); -- -- /** -- * @param {object[]} opts5 - Let's test out some multiple nesting levels -- * @param {string} opts5[].help - (This one is just normal) -- * @param {object} opts5[].what - Look at us go! Here's the first nest! -- * @param {string} opts5[].what.a - (Another normal one) -- * @param {Object[]} opts5[].what.bad - Now we're nesting inside a nested type -- * @param {string} opts5[].what.bad[].idea - I don't think you can get back out of this level... -- * @param {boolean} opts5[].what.bad[].oh - Oh ... that's how you do it. -- * @param {number} opts5[].unnest - Here we are almost all the way back at the beginning. -- */ -- function foo5(opts5) { -- opts5[0].what.bad[0].idea; -- opts5[0].unnest; -- } -- -- foo5([{ help: "help", what: { a: 'a', bad: [{ idea: 'idea', oh: false }] }, unnest: 1 }]); -- -+ \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject.errors.txt.diff deleted file mode 100644 index d5a40d930b..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject.errors.txt.diff +++ /dev/null @@ -1,16 +0,0 @@ ---- old.paramTagNestedWithoutTopLevelObject.errors.txt -+++ new.paramTagNestedWithoutTopLevelObject.errors.txt -@@= skipped -0, +0 lines =@@ --paramTagNestedWithoutTopLevelObject.js(2,20): error TS8032: Qualified name 'xyz.p' is not allowed without a leading '@param {object} xyz'. -- -- --==== 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/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt.diff deleted file mode 100644 index 265bf3133e..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject2.errors.txt.diff +++ /dev/null @@ -1,17 +0,0 @@ ---- old.paramTagNestedWithoutTopLevelObject2.errors.txt -+++ new.paramTagNestedWithoutTopLevelObject2.errors.txt -@@= skipped -0, +0 lines =@@ --paramTagNestedWithoutTopLevelObject2.js(2,20): error TS8032: Qualified name 'xyz.bar' is not allowed without a leading '@param {object} xyz'. -- -- --==== 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/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt.diff index ad40d9644d..920c07865c 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject3.errors.txt.diff @@ -1,16 +1,18 @@ --- old.paramTagNestedWithoutTopLevelObject3.errors.txt +++ new.paramTagNestedWithoutTopLevelObject3.errors.txt @@= skipped -0, +0 lines =@@ --paramTagNestedWithoutTopLevelObject3.js(3,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. + paramTagNestedWithoutTopLevelObject3.js(3,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. +- +- +-==== paramTagNestedWithoutTopLevelObject3.js (1 errors) ==== +paramTagNestedWithoutTopLevelObject3.js(6,16): error TS2339: Property 'bar' does not exist on type 'object'. - - - ==== paramTagNestedWithoutTopLevelObject3.js (1 errors) ==== ++ ++ ++==== paramTagNestedWithoutTopLevelObject3.js (2 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'. +@@= skipped -9, +10 lines =@@ */ function g(xyz) { return xyz.bar.p; diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt.diff deleted file mode 100644 index 40f9e2c63b..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagNestedWithoutTopLevelObject4.errors.txt.diff +++ /dev/null @@ -1,16 +0,0 @@ ---- old.paramTagNestedWithoutTopLevelObject4.errors.txt -+++ new.paramTagNestedWithoutTopLevelObject4.errors.txt -@@= skipped -0, +0 lines =@@ --paramTagNestedWithoutTopLevelObject4.js(2,20): error TS8032: Qualified name 'xyz.bar.p' is not allowed without a leading '@param {object} xyz.bar'. -- -- --==== 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/testdata/baselines/reference/submoduleAccepted/conformance/paramTagOnFunctionUsingArguments.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagOnFunctionUsingArguments.errors.txt.diff index 2a2f3a35de..459abd06bb 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/paramTagOnFunctionUsingArguments.errors.txt.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/paramTagOnFunctionUsingArguments.errors.txt.diff @@ -1,23 +1,13 @@ --- old.paramTagOnFunctionUsingArguments.errors.txt +++ new.paramTagOnFunctionUsingArguments.errors.txt @@= skipped -0, +0 lines =@@ --a.js(2,20): error TS8029: JSDoc '@param' tag has name 'first', but there is no parameter with that name. It would match 'arguments' if it had an array type. + a.js(2,20): error TS8029: JSDoc '@param' tag has name 'first', but there is no parameter with that name. It would match 'arguments' if it had an array type. -a.js(19,9): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +a.js(19,9): error TS2554: Expected 0 arguments, but got 3. ==== decls.d.ts (0 errors) ==== - declare function factory(type: string): {}; --==== a.js (2 errors) ==== -+==== a.js (1 errors) ==== - /** - * @param {string} first -- ~~~~~ --!!! error TS8029: JSDoc '@param' tag has name 'first', but there is no parameter with that name. It would match 'arguments' if it had an array type. - */ - function concat(/* first, second, ... */) { - var s = '' -@@= skipped -25, +22 lines =@@ +@@= skipped -25, +25 lines =@@ } correct(1,2,3) // oh no