@@ -33,6 +33,9 @@ class JSDoc extends @jsdoc, Locatable {
3333 result .getTitle ( ) = title
3434 }
3535
36+ /** Gets the element to which this JSDoc comment is attached */
37+ Documentable getDocumentedElement ( ) { result .getDocumentation ( ) = this }
38+
3639 override string toString ( ) { result = this .getComment ( ) .toString ( ) }
3740}
3841
@@ -299,6 +302,41 @@ class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr
299302 override predicate isRawFunction ( ) { this .getName ( ) = "Function" }
300303}
301304
305+ private AstNode getAncestorInScope ( Documentable doc ) {
306+ any ( JSDocLocalTypeAccess t ) .getJSDocComment ( ) = doc .getDocumentation ( ) and // restrict to cases where we need this
307+ result = doc .getParent ( )
308+ or
309+ exists ( AstNode mid |
310+ mid = getAncestorInScope ( doc ) and
311+ not mid = any ( Scope s ) .getScopeElement ( ) and
312+ result = mid .getParent ( )
313+ )
314+ }
315+
316+ private Scope getScope ( Documentable doc ) { result .getScopeElement ( ) = getAncestorInScope ( doc ) }
317+
318+ pragma [ nomagic]
319+ private predicate shouldResolveName ( TopLevel top , string name ) {
320+ exists ( JSDocLocalTypeAccess access |
321+ access .getName ( ) = name and
322+ access .getTopLevel ( ) = top
323+ )
324+ }
325+
326+ private LexicalName getOwnLocal ( Scope scope , string name , DeclarationSpace space ) {
327+ scope = result .getScope ( ) and
328+ name = result .getName ( ) and
329+ space = result .getDeclarationSpace ( ) and
330+ shouldResolveName ( scope .getScopeElement ( ) .getTopLevel ( ) , name ) // restrict size of predicate
331+ }
332+
333+ private LexicalName resolveLocal ( Scope scope , string name , DeclarationSpace space ) {
334+ result = getOwnLocal ( scope , name , space )
335+ or
336+ result = resolveLocal ( scope .getOuterScope ( ) , name , space ) and
337+ not exists ( getOwnLocal ( scope , name , space ) )
338+ }
339+
302340/**
303341 * An unqualified identifier in a JSDoc type expression.
304342 *
@@ -311,6 +349,12 @@ class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr
311349 */
312350class JSDocLocalTypeAccess extends JSDocIdentifierTypeExpr {
313351 JSDocLocalTypeAccess ( ) { not this = any ( JSDocQualifiedTypeAccess a ) .getNameNode ( ) }
352+
353+ /** Gets a variable, type-name, or namespace that this expression may resolve to. */
354+ LexicalName getALexicalName ( ) {
355+ result =
356+ resolveLocal ( getScope ( this .getJSDocComment ( ) .getDocumentedElement ( ) ) , this .getName ( ) , _)
357+ }
314358}
315359
316360/**
0 commit comments