Prototype-property assignment:fix name resolution crash (#23680)

This commit is contained in:
Nathan Shively-Sanders 2018-04-25 13:59:40 -07:00 committed by GitHub
parent 9b05bd5cd7
commit b2bfccfce4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 2 deletions

View File

@ -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);
}
}
}
}

View File

@ -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.<Object>} 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'.

View File

@ -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.<Object>} 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))

View File

@ -38,3 +38,16 @@ let s = g('hi')()
>g : <T>(a: T) => () => T
>'hi' : "hi"
/**
* @param {Array.<Object>} 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[]

View File

@ -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.<Object>} 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) {};