mirror of
https://github.com/github/codeql.git
synced 2026-05-10 09:19:27 +02:00
Merge pull request #1257 from asger-semmle/jsdoc
JS: Add common interface between TypeExpr and JSDocTypeExpr
This commit is contained in:
@@ -551,7 +551,11 @@ class SetterMethodSignature extends SetterMethodDeclaration, AccessorMethodSigna
|
||||
*/
|
||||
class FieldDeclaration extends MemberDeclaration, @field {
|
||||
/** Gets the type annotation of this field, if any, such as `T` in `{ x: T }`. */
|
||||
TypeExpr getTypeAnnotation() { result = getChildTypeExpr(2) }
|
||||
TypeAnnotation getTypeAnnotation() {
|
||||
result = getChildTypeExpr(2)
|
||||
or
|
||||
result = getDocumentation().getATagByTitle("type").getType()
|
||||
}
|
||||
|
||||
/** Holds if this is a TypeScript field annotated with the `readonly` keyword. */
|
||||
predicate isReadonly() { hasReadonlyKeyword(this) }
|
||||
@@ -591,7 +595,7 @@ class ParameterField extends FieldDeclaration, @parameter_field {
|
||||
|
||||
override Expr getNameExpr() { result = getParameter() }
|
||||
|
||||
override TypeExpr getTypeAnnotation() { result = getParameter().getTypeAnnotation() }
|
||||
override TypeAnnotation getTypeAnnotation() { result = getParameter().getTypeAnnotation() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,11 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
*
|
||||
* `this` parameter types are specific to TypeScript.
|
||||
*/
|
||||
TypeExpr getThisTypeAnnotation() { result = getChildTypeExpr(-4) }
|
||||
TypeAnnotation getThisTypeAnnotation() {
|
||||
result = getChildTypeExpr(-4)
|
||||
or
|
||||
result = getDocumentation().getATagByTitle("this").getType()
|
||||
}
|
||||
|
||||
/** Gets the identifier specifying the name of this function, if any. */
|
||||
VarDecl getId() { result = getChildExpr(-1) }
|
||||
@@ -76,7 +80,13 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
int getNumBodyStmt() { result = count(getABodyStmt()) }
|
||||
|
||||
/** Gets the return type annotation on this function, if any. */
|
||||
TypeExpr getReturnTypeAnnotation() { typeexprs(result, _, this, -3, _) }
|
||||
TypeAnnotation getReturnTypeAnnotation() {
|
||||
typeexprs(result, _, this, -3, _)
|
||||
or
|
||||
exists(string title | title = "return" or title = "returns" |
|
||||
result = getDocumentation().getATagByTitle(title).getType()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this function is a generator function. */
|
||||
predicate isGenerator() {
|
||||
@@ -163,24 +173,24 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
result = getAReturnStmt().getExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets a return from a function which has undefined value (that is, implicit
|
||||
* returns and returns without expressions).
|
||||
*
|
||||
* Functions can have undefined returns in a few different ways:
|
||||
*
|
||||
*
|
||||
* 1. An explicit return statement with no expression (the statement `return;`)
|
||||
*
|
||||
*
|
||||
* 2. An implicit return resulting from an expression executing as the last thing
|
||||
* in the function. For example, the test in a final `if` statement:
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* function foo() {
|
||||
* ...
|
||||
* if (test) { return 1; }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Some things look like they might return undefined but actually don't because
|
||||
* the containing functioning doesn't return at all. For instance, `throw`
|
||||
* statements prevent the containing function from returning, so they don't count
|
||||
@@ -189,13 +199,12 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
* exclude yields entirely. Likewise, we exclude generator functions from
|
||||
* consideration, as well as asynchronous functions, since calls to both produce
|
||||
* something distinct from what's explicitly returned by the function.
|
||||
*
|
||||
*
|
||||
* Despite the fact that yield expressions are invalid outside of generators, we
|
||||
* include them anyway just to ensure that we're not relying on a perfect analysis
|
||||
* of a function to be a generator, and instead are looking also explicitly at the
|
||||
* return sites.
|
||||
*/
|
||||
|
||||
ConcreteControlFlowNode getAnUndefinedReturn() {
|
||||
not this.getBody() instanceof Expr and
|
||||
not this.isGenerator() and
|
||||
@@ -206,7 +215,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
result.getContainer() = this and
|
||||
result.isAFinalNode()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the function whose `this` binding a `this` expression in this function refers to,
|
||||
* which is the nearest enclosing non-arrow function.
|
||||
|
||||
@@ -17,6 +17,12 @@ class JSDoc extends @jsdoc, Locatable {
|
||||
/** Gets a JSDoc tag within this JSDoc comment. */
|
||||
JSDocTag getATag() { result.getParent() = this }
|
||||
|
||||
/** Gets a JSDoc tag within this JSDoc comment with the given title. */
|
||||
JSDocTag getATagByTitle(string title) {
|
||||
result = getATag() and
|
||||
result.getTitle() = title
|
||||
}
|
||||
|
||||
override string toString() { result = getComment().toString() }
|
||||
}
|
||||
|
||||
@@ -33,17 +39,16 @@ abstract class Documentable extends ASTNode {
|
||||
* A syntactic element that a JSDoc type expression may be nested in, that is,
|
||||
* either a JSDoc tag or another JSDoc type expression.
|
||||
*/
|
||||
class JSDocTypeExprParent extends @jsdoc_type_expr_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() }
|
||||
class JSDocTypeExprParent extends @jsdoc_type_expr_parent, Locatable {
|
||||
override Location getLocation() { hasLocation(this, result) }
|
||||
|
||||
JSDoc getJSDocComment() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A JSDoc tag such as `@param Object options An object literal with options.`
|
||||
*/
|
||||
class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent, Locatable {
|
||||
override Location getLocation() { hasLocation(this, result) }
|
||||
|
||||
class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
|
||||
/** Gets the tag title; for instance, the title of a `@param` tag is `"param"`. */
|
||||
string getTitle() { jsdoc_tags(this, result, _, _, _) }
|
||||
|
||||
@@ -77,6 +82,10 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent, Locatable {
|
||||
|
||||
/** Gets the toplevel in which this tag appears. */
|
||||
TopLevel getTopLevel() { result = getParent().getComment().getTopLevel() }
|
||||
|
||||
override JSDoc getJSDocComment() {
|
||||
result.getATag() = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +105,7 @@ class JSDocParamTag extends JSDocTag {
|
||||
/**
|
||||
* A JSDoc type expression.
|
||||
*/
|
||||
class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent {
|
||||
class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotation {
|
||||
/**
|
||||
* Gets the syntactic element in which this type expression is nested, which may either
|
||||
* be another type expression or a JSDoc tag.
|
||||
@@ -117,27 +126,88 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent {
|
||||
JSDocTypeExpr getChild(int i) { jsdoc_type_exprs(result, _, this, i, _) }
|
||||
|
||||
override string toString() { jsdoc_type_exprs(this, _, _, _, result) }
|
||||
|
||||
override JSDoc getJSDocComment() {
|
||||
result = getParent().getJSDocComment()
|
||||
}
|
||||
|
||||
override Stmt getEnclosingStmt() {
|
||||
result.getDocumentation() = getJSDocComment()
|
||||
}
|
||||
|
||||
override StmtContainer getContainer() { result = getEnclosingStmt().getContainer() }
|
||||
|
||||
override Function getEnclosingFunction() { result = getContainer() }
|
||||
|
||||
override TopLevel getTopLevel() { result = getEnclosingStmt().getTopLevel() }
|
||||
}
|
||||
|
||||
/** An `any` type expression `*`. */
|
||||
class JSDocAnyTypeExpr extends @jsdoc_any_type_expr, JSDocTypeExpr { }
|
||||
class JSDocAnyTypeExpr extends @jsdoc_any_type_expr, JSDocTypeExpr {
|
||||
override predicate isAny() { any() }
|
||||
}
|
||||
|
||||
/** A null type expression. */
|
||||
class JSDocNullTypeExpr extends @jsdoc_null_type_expr, JSDocTypeExpr { }
|
||||
class JSDocNullTypeExpr extends @jsdoc_null_type_expr, JSDocTypeExpr {
|
||||
override predicate isNull() { any() }
|
||||
}
|
||||
|
||||
/** A type expression representing the type of `undefined`. */
|
||||
class JSDocUndefinedTypeExpr extends @jsdoc_undefined_type_expr, JSDocTypeExpr { }
|
||||
class JSDocUndefinedTypeExpr extends @jsdoc_undefined_type_expr, JSDocTypeExpr {
|
||||
override predicate isUndefined() { any() }
|
||||
}
|
||||
|
||||
/** A type expression representing an unknown type `?`. */
|
||||
class JSDocUnknownTypeExpr extends @jsdoc_unknown_type_expr, JSDocTypeExpr { }
|
||||
class JSDocUnknownTypeExpr extends @jsdoc_unknown_type_expr, JSDocTypeExpr {
|
||||
override predicate isUnknownKeyword() { any() }
|
||||
}
|
||||
|
||||
/** A type expression representing the void type. */
|
||||
class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr { }
|
||||
class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr {
|
||||
override predicate isVoid() { any() }
|
||||
}
|
||||
|
||||
/** A type expression referring to a named type. */
|
||||
class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
/** Gets the name of the type the expression refers to. */
|
||||
string getName() { result = toString() }
|
||||
|
||||
override predicate isString() { getName() = "string" }
|
||||
|
||||
override predicate isStringy() {
|
||||
exists(string name | name = getName() |
|
||||
name = "string" or
|
||||
name = "String"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isNumber() { getName() = "number" }
|
||||
|
||||
override predicate isNumbery() {
|
||||
exists(string name | name = getName() |
|
||||
name = "number" or
|
||||
name = "Number" or
|
||||
name = "double" or
|
||||
name = "Double" or
|
||||
name = "int" or
|
||||
name = "integer" or
|
||||
name = "Integer"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBoolean() { getName() = "boolean" }
|
||||
|
||||
override predicate isBooleany() {
|
||||
getName() = "boolean" or
|
||||
getName() = "Boolean" or
|
||||
getName() = "bool"
|
||||
}
|
||||
|
||||
override predicate isRawFunction() { getName() = "Function" }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
globalName = getName()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,6 +230,10 @@ class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
||||
* For example, in `Array<string>`, `string` is the only argument type.
|
||||
*/
|
||||
JSDocTypeExpr getAnArgument() { result = getArgument(_) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
getHead().hasQualifiedName(globalName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,6 +245,8 @@ class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
||||
|
||||
/** Holds if the `?` operator of this type expression is written in prefix notation. */
|
||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,6 +258,8 @@ class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeE
|
||||
|
||||
/** Holds if the `!` operator of this type expression is written in prefix notation. */
|
||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,6 +298,8 @@ class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
|
||||
class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
|
||||
/** Gets one of the type alternatives of this union type. */
|
||||
JSDocTypeExpr getAnAlternative() { result = getChild(_) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getAnAlternative().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,6 +328,8 @@ class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
|
||||
class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTypeExpr {
|
||||
/** Gets the underlying type of this optional type. */
|
||||
JSDocTypeExpr getUnderlyingType() { result = getChild(0) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getUnderlyingType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
108
javascript/ql/src/semmle/javascript/TypeAnnotations.qll
Normal file
108
javascript/ql/src/semmle/javascript/TypeAnnotations.qll
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Provides classes for reasoning about type annotations independently of dialect.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* A type annotation, either in the form of a TypeScript type or a JSDoc comment.
|
||||
*/
|
||||
class TypeAnnotation extends @type_annotation, Locatable {
|
||||
/** Holds if this is the `any` type. */
|
||||
predicate isAny() { none() }
|
||||
|
||||
/** Holds if this is the `string` type. Does not hold for the (rarely used) `String` type. */
|
||||
predicate isString() { none() }
|
||||
|
||||
/** Holds if this is the `string` or `String` type. */
|
||||
predicate isStringy() { none() }
|
||||
|
||||
/** Holds if this is the `number` type. Does not hold for the (rarely used) `Number` type. */
|
||||
predicate isNumber() { none() }
|
||||
|
||||
/** Holds if this is the `number` or `Number`s type. */
|
||||
predicate isNumbery() { none() }
|
||||
|
||||
/** Holds if this is the `boolean` type. Does not hold for the (rarely used) `Boolean` type. */
|
||||
predicate isBoolean() { none() }
|
||||
|
||||
/** Holds if this is the `boolean` or `Boolean` type. */
|
||||
predicate isBooleany() { none() }
|
||||
|
||||
/** Holds if this is the `undefined` type. */
|
||||
predicate isUndefined() { none() }
|
||||
|
||||
/** Holds if this is the `null` type. */
|
||||
predicate isNull() { none() }
|
||||
|
||||
/** Holds if this is the `void` type. */
|
||||
predicate isVoid() { none() }
|
||||
|
||||
/** Holds if this is the `never` type, or an equivalent type representing the empty set of values. */
|
||||
predicate isNever() { none() }
|
||||
|
||||
/** Holds if this is the `this` type. */
|
||||
predicate isThis() { none() }
|
||||
|
||||
/** Holds if this is the `symbol` type. */
|
||||
predicate isSymbol() { none() }
|
||||
|
||||
/** Holds if this is the `unique symbol` type. */
|
||||
predicate isUniqueSymbol() { none() }
|
||||
|
||||
/** Holds if this is the `Function` type. */
|
||||
predicate isRawFunction() { none() }
|
||||
|
||||
/** Holds if this is the `object` type. */
|
||||
predicate isObjectKeyword() { none() }
|
||||
|
||||
/** Holds if this is the `unknown` type. */
|
||||
predicate isUnknownKeyword() { none() }
|
||||
|
||||
/** Holds if this is the `bigint` type. */
|
||||
predicate isBigInt() { none() }
|
||||
|
||||
/** Holds if this is the `const` keyword, occurring in a type assertion such as `x as const`. */
|
||||
predicate isConstKeyword() { none() }
|
||||
|
||||
/**
|
||||
* Repeatedly unfolds unions, intersections, parentheses, and nullability/readonly modifiers and gets any of the underlying types,
|
||||
* or this type itself if it cannot be unfolded.
|
||||
*
|
||||
* Note that this only unfolds the syntax of the type annotation. Type aliases are not followed to their definition.
|
||||
*/
|
||||
TypeAnnotation getAnUnderlyingType() { result = this }
|
||||
|
||||
/**
|
||||
* Holds if this is a reference to the type with qualified name `globalName` relative to the global scope.
|
||||
*/
|
||||
predicate hasQualifiedName(string globalName) { none() }
|
||||
|
||||
/**
|
||||
* Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`.
|
||||
*/
|
||||
predicate hasQualifiedName(string moduleName, string exportedName) { none() }
|
||||
|
||||
/** Gets the statement in which this type appears. */
|
||||
Stmt getEnclosingStmt() { none() }
|
||||
|
||||
/** Gets the function in which this type appears, if any. */
|
||||
Function getEnclosingFunction() { none() }
|
||||
|
||||
/**
|
||||
* Gets the statement container (function or toplevel) in which this type appears.
|
||||
*/
|
||||
StmtContainer getContainer() { none() }
|
||||
|
||||
/**
|
||||
* Gets the top-level containing this type annotation.
|
||||
*/
|
||||
TopLevel getTopLevel() { none() }
|
||||
|
||||
/**
|
||||
* Gets the static type denoted by this type annotation, if one is provided by the extractor.
|
||||
*
|
||||
* Note that this has no result for JSDoc type annotations.
|
||||
*/
|
||||
Type getType() { none() }
|
||||
}
|
||||
@@ -528,69 +528,9 @@ class LocalNamespaceName extends @local_namespace_name, LexicalName {
|
||||
* This class includes only explicit type annotations -
|
||||
* types inferred by the TypeScript compiler are not type expressions.
|
||||
*/
|
||||
class TypeExpr extends ExprOrType, @typeexpr {
|
||||
class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation {
|
||||
override string toString() { typeexprs(this, _, _, _, result) }
|
||||
|
||||
/** Holds if this is the `any` type. */
|
||||
predicate isAny() { none() }
|
||||
|
||||
/** Holds if this is the `string` type. Does not hold for the (rarely used) `String` type. */
|
||||
predicate isString() { none() }
|
||||
|
||||
/** Holds if this is the `string` or `String` type. */
|
||||
predicate isStringy() { none() }
|
||||
|
||||
/** Holds if this is the `number` type. Does not hold for the (rarely used) `Number` type. */
|
||||
predicate isNumber() { none() }
|
||||
|
||||
/** Holds if this is the `number` or `Number`s type. */
|
||||
predicate isNumbery() { none() }
|
||||
|
||||
/** Holds if this is the `boolean` type. Does not hold for the (rarely used) `Boolean` type. */
|
||||
predicate isBoolean() { none() }
|
||||
|
||||
/** Holds if this is the `boolean` or `Boolean` type. */
|
||||
predicate isBooleany() { none() }
|
||||
|
||||
/** Holds if this is the `undefined` type. */
|
||||
predicate isUndefined() { none() }
|
||||
|
||||
/** Holds if this is the `null` type. */
|
||||
predicate isNull() { none() }
|
||||
|
||||
/** Holds if this is the `void` type. */
|
||||
predicate isVoid() { none() }
|
||||
|
||||
/** Holds if this is the `never` type. */
|
||||
predicate isNever() { none() }
|
||||
|
||||
/** Holds if this is the `this` type. */
|
||||
predicate isThis() { none() }
|
||||
|
||||
/** Holds if this is the `symbol` type. */
|
||||
predicate isSymbol() { none() }
|
||||
|
||||
/** Holds if this is the `unique symbol` type. */
|
||||
predicate isUniqueSymbol() { none() }
|
||||
|
||||
/** Holds if this is the `Function` type. */
|
||||
predicate isRawFunction() { none() }
|
||||
|
||||
/** Holds if this is the `object` type. */
|
||||
predicate isObjectKeyword() { none() }
|
||||
|
||||
/** Holds if this is the `unknown` type. */
|
||||
predicate isUnknownKeyword() { none() }
|
||||
|
||||
/** Holds if this is the `bigint` type. */
|
||||
predicate isBigInt() { none() }
|
||||
|
||||
/** Holds if this is the `const` keyword, occurring in a type assertion such as `x as const`. */
|
||||
predicate isConstKeyword() { none() }
|
||||
|
||||
/** Gets this type expression, with any surrounding parentheses removed. */
|
||||
override TypeExpr stripParens() { result = this }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
|
||||
/**
|
||||
@@ -599,7 +539,15 @@ class TypeExpr extends ExprOrType, @typeexpr {
|
||||
* Has no result if this occurs in a TypeScript file that was extracted
|
||||
* without type information.
|
||||
*/
|
||||
Type getType() { ast_node_type(this, result) }
|
||||
override Type getType() { ast_node_type(this, result) }
|
||||
|
||||
override Stmt getEnclosingStmt() { result = ExprOrType.super.getEnclosingStmt() }
|
||||
|
||||
override Function getEnclosingFunction() { result = ExprOrType.super.getEnclosingFunction() }
|
||||
|
||||
override StmtContainer getContainer() { result = ExprOrType.super.getContainer() }
|
||||
|
||||
override TopLevel getTopLevel() { result = ExprOrType.super.getTopLevel() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,6 +664,14 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef {
|
||||
* Gets the canonical name of the type being accessed.
|
||||
*/
|
||||
TypeName getTypeName() { ast_node_symbol(this, result) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
getTypeName().hasQualifiedName(globalName)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
getTypeName().hasQualifiedName(moduleName, exportedName)
|
||||
}
|
||||
}
|
||||
|
||||
/** An identifier that is used as part of a type, such as `Date`. */
|
||||
@@ -776,6 +732,14 @@ class GenericTypeExpr extends @generictypeexpr, TypeExpr {
|
||||
|
||||
/** Gets the number of type arguments. This is always at least one. */
|
||||
int getNumTypeArgument() { result = count(getATypeArgument()) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
getTypeAccess().hasQualifiedName(globalName)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
getTypeAccess().hasQualifiedName(moduleName, exportedName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -846,6 +810,8 @@ class UnionTypeExpr extends @uniontypeexpr, TypeExpr {
|
||||
|
||||
/** Gets the number of types in the union. This is always at least two. */
|
||||
int getNumElementType() { result = count(getAnElementType()) }
|
||||
|
||||
override TypeExpr getAnUnderlyingType() { result = getAnElementType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -873,6 +839,8 @@ class IntersectionTypeExpr extends @intersectiontypeexpr, TypeExpr {
|
||||
|
||||
/** Gets the number of operands to the intersection type. This is always at least two. */
|
||||
int getNumElementType() { result = count(getAnElementType()) }
|
||||
|
||||
override TypeExpr getAnUnderlyingType() { result = getAnElementType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -883,6 +851,8 @@ class ParenthesizedTypeExpr extends @parenthesizedtypeexpr, TypeExpr {
|
||||
TypeExpr getElementType() { result = getChildTypeExpr(0) }
|
||||
|
||||
override TypeExpr stripParens() { result = getElementType().stripParens() }
|
||||
|
||||
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -962,6 +932,8 @@ class IsTypeExpr extends @istypeexpr, TypeExpr {
|
||||
class OptionalTypeExpr extends @optionaltypeexpr, TypeExpr {
|
||||
/** Gets the type `T` in `T?` */
|
||||
TypeExpr getElementType() { result = getChildTypeExpr(0) }
|
||||
|
||||
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -981,6 +953,8 @@ class RestTypeExpr extends @resttypeexpr, TypeExpr {
|
||||
class ReadonlyTypeExpr extends @readonlytypeexpr, TypeExpr {
|
||||
/** Gets the type `T` in `readonly T`. */
|
||||
TypeExpr getElementType() { result = getChildTypeExpr(0) }
|
||||
|
||||
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -326,7 +326,7 @@ class BindingPattern extends @pattern, Expr {
|
||||
predicate isLValue() { any() }
|
||||
|
||||
/**
|
||||
* Returns the TypeScript type annotation for this variable or pattern, if any.
|
||||
* Returns the type annotation for this variable or pattern, if any.
|
||||
*
|
||||
* Only the outermost part of a binding pattern can have a type annotation.
|
||||
* For instance, in the declaration,
|
||||
@@ -336,7 +336,7 @@ class BindingPattern extends @pattern, Expr {
|
||||
* the variable `x` has no type annotation, whereas the pattern `{x}` has the type
|
||||
* annotation `Point`.
|
||||
*/
|
||||
TypeExpr getTypeAnnotation() {
|
||||
TypeAnnotation getTypeAnnotation() {
|
||||
exists(VariableDeclarator decl | decl.getBindingPattern() = this |
|
||||
result = decl.getTypeAnnotation()
|
||||
)
|
||||
@@ -500,8 +500,12 @@ class VariableDeclarator extends Expr, @vardeclarator {
|
||||
/** Gets the expression specifying the initial value of the declared variable(s), if any. */
|
||||
Expr getInit() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the TypeScript type annotation for the declared variable or binding pattern. */
|
||||
TypeExpr getTypeAnnotation() { result = this.getChildTypeExpr(2) }
|
||||
/** Gets the type annotation for the declared variable or binding pattern. */
|
||||
TypeAnnotation getTypeAnnotation() {
|
||||
result = this.getChildTypeExpr(2)
|
||||
or
|
||||
result = getDeclStmt().getDocumentation().getATagByTitle("type").getType()
|
||||
}
|
||||
|
||||
/** Holds if this is a TypeScript variable marked as definitely assigned with the `!` operator. */
|
||||
predicate hasDefiniteAssignmentAssertion() { hasDefiniteAssignmentAssertion(this) }
|
||||
@@ -569,8 +573,10 @@ class Parameter extends BindingPattern {
|
||||
}
|
||||
|
||||
/** Gets the type annotation for this parameter, if any. */
|
||||
override TypeExpr getTypeAnnotation() {
|
||||
override TypeAnnotation getTypeAnnotation() {
|
||||
exists(Function f, int n | this = f.getParameter(n) | result = f.getChildTypeExpr(-(4 * n + 6)))
|
||||
or
|
||||
result = getJSDocTag().getType()
|
||||
}
|
||||
|
||||
/** Holds if this parameter is a rest parameter. */
|
||||
@@ -619,12 +625,17 @@ class SimpleParameter extends Parameter, VarDecl {
|
||||
)
|
||||
}
|
||||
|
||||
override JSDocTag getJSDocTag() {
|
||||
override JSDocParamTag getJSDocTag() {
|
||||
exists(Function fun |
|
||||
this = fun.getAParameter() and
|
||||
result = fun.getDocumentation().getATag() and
|
||||
result.getTitle() = "param" and
|
||||
result.getName() = getName()
|
||||
result = fun.getDocumentation().getATag()
|
||||
) and
|
||||
// Avoid joining on name
|
||||
exists(string tagName, string paramName |
|
||||
tagName = result.getName() and
|
||||
paramName = this.getName() and
|
||||
tagName <= paramName and
|
||||
paramName <= tagName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user