diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3be433aec1..65342c51881 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2134,14 +2134,22 @@ namespace ts { return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } + /** + * For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too. + * Note that prototype-property assignment to locations outside the current file (eg globals) doesn't work, so + * name resolution won't work either. + */ function resolveEntityNameFromJSPrototype(name: Identifier, meaning: SymbolFlags) { if (isJSDocTypeReference(name.parent) && isJSDocTag(name.parent.parent.parent)) { const host = getJSDocHost(name.parent.parent.parent as JSDocTag); if (isExpressionStatement(host) && isBinaryExpression(host.expression) && getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) { - const secondaryLocation = getSymbolOfNode(host.expression.left).parent.valueDeclaration; - return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); + const symbol = getSymbolOfNode(host.expression.left); + if (symbol) { + const secondaryLocation = symbol.parent.valueDeclaration; + return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); + } } } } diff --git a/tests/baselines/reference/jsdocTemplateTag.errors.txt b/tests/baselines/reference/jsdocTemplateTag.errors.txt new file mode 100644 index 00000000000..c8b3e92f8c0 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/jsdoc/forgot.js(23,19): error TS2339: Property 'animate' does not exist on type 'Element'. + + +==== tests/cases/conformance/jsdoc/forgot.js (1 errors) ==== + /** + * @param {T} a + * @template T + */ + function f(a) { + return () => a + } + let n = f(1)() + + /** + * @param {T} a + * @template T + * @returns {function(): T} + */ + function g(a) { + return () => a + } + let s = g('hi')() + + /** + * @param {Array.} keyframes - Can't look up types on Element since it's a global in another file. (But it shouldn't crash). + */ + Element.prototype.animate = function(keyframes) {}; + ~~~~~~~ +!!! error TS2339: Property 'animate' does not exist on type 'Element'. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocTemplateTag.symbols b/tests/baselines/reference/jsdocTemplateTag.symbols index 98eee628178..235f26c330e 100644 --- a/tests/baselines/reference/jsdocTemplateTag.symbols +++ b/tests/baselines/reference/jsdocTemplateTag.symbols @@ -30,3 +30,12 @@ let s = g('hi')() >s : Symbol(s, Decl(forgot.js, 17, 3)) >g : Symbol(g, Decl(forgot.js, 7, 14)) +/** + * @param {Array.} keyframes - Can't look up types on Element since it's a global in another file. (But it shouldn't crash). + */ +Element.prototype.animate = function(keyframes) {}; +>Element.prototype : Symbol(prototype, Decl(lib.dom.d.ts, --, --)) +>Element : Symbol(Element, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>prototype : Symbol(prototype, Decl(lib.dom.d.ts, --, --)) +>keyframes : Symbol(keyframes, Decl(forgot.js, 22, 37)) + diff --git a/tests/baselines/reference/jsdocTemplateTag.types b/tests/baselines/reference/jsdocTemplateTag.types index b1d8c46720d..7917329b3e6 100644 --- a/tests/baselines/reference/jsdocTemplateTag.types +++ b/tests/baselines/reference/jsdocTemplateTag.types @@ -38,3 +38,16 @@ let s = g('hi')() >g : (a: T) => () => T >'hi' : "hi" +/** + * @param {Array.} keyframes - Can't look up types on Element since it's a global in another file. (But it shouldn't crash). + */ +Element.prototype.animate = function(keyframes) {}; +>Element.prototype.animate = function(keyframes) {} : (keyframes: any[]) => void +>Element.prototype.animate : any +>Element.prototype : Element +>Element : { new (): Element; prototype: Element; } +>prototype : Element +>animate : any +>function(keyframes) {} : (keyframes: any[]) => void +>keyframes : any[] + diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts b/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts index 79dc083a952..e69756c0941 100644 --- a/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts +++ b/tests/cases/conformance/jsdoc/jsdocTemplateTag.ts @@ -1,6 +1,7 @@ // @allowJs: true // @checkJs: true // @noEmit: true +// @lib: dom,esnext // @Filename: forgot.js /** * @param {T} a @@ -20,3 +21,8 @@ function g(a) { return () => a } let s = g('hi')() + +/** + * @param {Array.} keyframes - Can't look up types on Element since it's a global in another file. (But it shouldn't crash). + */ +Element.prototype.animate = function(keyframes) {};