Merge pull request #1257 from asger-semmle/jsdoc

JS: Add common interface between TypeExpr and JSDocTypeExpr
This commit is contained in:
Max Schaefer
2019-04-29 16:20:17 +01:00
committed by GitHub
26 changed files with 3398 additions and 851 deletions

View File

@@ -3,7 +3,6 @@
*/
import Customizations
import semmle.javascript.Aliases
import semmle.javascript.AMD
import semmle.javascript.AST
@@ -49,6 +48,7 @@ import semmle.javascript.StringConcatenation
import semmle.javascript.StringOps
import semmle.javascript.Templates
import semmle.javascript.Tokens
import semmle.javascript.TypeAnnotations
import semmle.javascript.TypeScript
import semmle.javascript.Util
import semmle.javascript.Variables

View File

@@ -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() }
}
/**

View File

@@ -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.

View File

@@ -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() }
}
/**

View 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() }
}

View File

@@ -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() }
}
/**

View File

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

View File

@@ -232,6 +232,7 @@ isDelegating (int yield: @yieldexpr ref);
@exprortype = @expr | @typeexpr;
@exprparent = @exprorstmt | @property | @functiontypeexpr;
@arraylike = @arrayexpr | @arraypattern;
@type_annotation = @typeexpr | @jsdoc_type_expr;
case @expr.kind of
0 = @label

View File

@@ -1,19 +1,19 @@
test_JSDocUnionTypeExpr
| (string\|number) | number |
| (string\|number) | string |
| (string\|number\|null) | null |
| (string\|number\|null) | number |
| (string\|number\|null) | string |
| (string\|undefined) | string |
| (string\|undefined) | undefined |
| tst.js:1:3:1:16 | (string\|number) | tst.js:1:9:1:9 | string |
| tst.js:1:3:1:16 | (string\|number) | tst.js:1:16:1:16 | number |
| tst.js:1:8:1:17 | (string\|undefined) | tst.js:1:8:1:8 | string |
| tst.js:1:8:1:17 | (string\|undefined) | tst.js:1:18:1:17 | undefined |
| tst.js:1:8:1:19 | (string\|number\|null) | tst.js:1:8:1:8 | string |
| tst.js:1:8:1:19 | (string\|number\|null) | tst.js:1:15:1:15 | number |
| tst.js:1:8:1:19 | (string\|number\|null) | tst.js:1:20:1:19 | null |
test_JSDocArrayTypeExpr
| [number] | 0 | number |
| tst.js:1:29:1:30 | [number] | 0 | tst.js:1:29:1:29 | number |
test_Parameter_getDocumentation
| tst.js:149:28:149:28 | a | tst.js:149:14:149:26 | /** number */ |
| tst.js:149:45:149:45 | b | tst.js:149:31:149:43 | /** number */ |
test_JSDocRestParameterTypeExpr
| ...[number] | [number] |
| ...number | number |
| tst.js:1:5:1:10 | ...number | tst.js:1:11:1:10 | number |
| tst.js:1:23:1:30 | ...[number] | tst.js:1:29:1:30 | [number] |
test_AssignExpr_getDocumentation
| tst.js:12:1:12:29 | mynames ... 'stout' | tst.js:7:1:11:3 | /**\\n * ... ng}\\n */ |
| tst.js:14:15:14:39 | MyClass ... 'stout' | tst.js:14:1:14:13 | /** @const */ |
@@ -47,8 +47,8 @@ test_AssignExpr_getDocumentation
| tst.js:336:1:336:24 | FooImpl ... n() { } | tst.js:331:1:335:3 | /**\\n * ... r>}\\n */ |
| tst.js:343:1:343:36 | identit ... rn a; } | tst.js:338:1:342:3 | /**\\n * ... e T\\n */ |
test_JSDocRecordTypeExpr
| {myNum: number, myObject} | myNum | number |
| {myNum: number, myObject} | myObject | (none) |
| tst.js:1:3:1:26 | {myNum: number, myObject} | myNum | number |
| tst.js:1:3:1:26 | {myNum: number, myObject} | myObject | (none) |
test_JSDoc
| tst.js:5:1:5:13 | /** @const */ | | tst.js:5:1:5:13 | /** @const */ |
| tst.js:7:1:11:3 | /**\\n * ... ng}\\n */ | My namespace's favorite kind of beer. | tst.js:7:1:11:3 | /**\\n * ... ng}\\n */ |
@@ -234,19 +234,19 @@ test_ObjectExpr_getDocumentation
| tst.js:117:43:119:9 | {\\n ... } | tst.js:117:9:117:40 | /** @le ... ype} */ |
| tst.js:192:27:192:36 | { x: 321 } | tst.js:192:12:192:25 | /** @struct */ |
test_JSDocFunctionTypeExpr
| function (?string=, number=) | (none) | (none) | 0 | ?string= | no |
| function (?string=, number=) | (none) | (none) | 1 | number= | no |
| function (new: goog.ui.Menu, string) | (none) | goog.ui.Menu | 0 | string | yes |
| function (string, ...[number]): number | number | (none) | 0 | string | no |
| function (string, ...[number]): number | number | (none) | 1 | ...[number] | no |
| function (string, boolean) | (none) | (none) | 0 | string | no |
| function (string, boolean) | (none) | (none) | 1 | boolean | no |
| function (this: goog.ui.Menu, string) | (none) | goog.ui.Menu | 0 | string | no |
| function (x: !number, y: !number): number | number | (none) | 0 | !number | no |
| function (x: !number, y: !number): number | number | (none) | 1 | !number | no |
| tst.js:1:10:1:26 | function (string, boolean) | (none) | (none) | 0 | tst.js:1:17:1:17 | string | no |
| tst.js:1:10:1:26 | function (string, boolean) | (none) | (none) | 1 | tst.js:1:26:1:26 | boolean | no |
| tst.js:1:10:1:28 | function (?string=, number=) | (none) | (none) | 0 | tst.js:1:12:1:19 | ?string= | no |
| tst.js:1:10:1:28 | function (?string=, number=) | (none) | (none) | 1 | tst.js:1:27:1:28 | number= | no |
| tst.js:1:10:1:35 | function (new: goog.ui.Menu, string) | (none) | goog.ui.Menu | 0 | tst.js:1:35:1:35 | string | yes |
| tst.js:1:10:1:36 | function (this: goog.ui.Menu, string) | (none) | goog.ui.Menu | 0 | tst.js:1:36:1:36 | string | no |
| tst.js:1:10:1:38 | function (string, ...[number]): number | number | (none) | 0 | tst.js:1:17:1:17 | string | no |
| tst.js:1:10:1:38 | function (string, ...[number]): number | number | (none) | 1 | tst.js:1:23:1:30 | ...[number] | no |
| tst.js:1:10:1:38 | function (x: !number, y: !number): number | number | (none) | 0 | tst.js:1:14:1:20 | !number | no |
| tst.js:1:10:1:38 | function (x: !number, y: !number): number | number | (none) | 1 | tst.js:1:25:1:31 | !number | no |
test_JSDocNullableTypeExpr
| ?string | string | prefix |
| number? | number | postfix |
| tst.js:1:8:1:8 | number? | tst.js:1:8:1:8 | number | postfix |
| tst.js:1:12:1:18 | ?string | tst.js:1:18:1:18 | string | prefix |
test_next_token
| tst.js:1:1:1:117 | // Test ... mpiler, | tst.js:5:15:5:17 | var |
| tst.js:2:1:2:118 | // whic ... se 2.0; | tst.js:5:15:5:17 | var |
@@ -340,127 +340,127 @@ test_next_token
| tst.js:375:3:377:5 | /**\\n ... p\\n */ | tst.js:378:3:378:13 | constructor |
| tst.js:380:3:382:5 | /**\\n ... p\\n */ | tst.js:383:3:383:13 | classMethod |
test_JSDocTypeExpr
| !Foo.<string> | @type | 0 |
| !Foo.<string> | @type | 0 |
| !Object | @type | 0 |
| !number | function (x: !number, y: !number): number | 0 |
| !number | function (x: !number, y: !number): number | 1 |
| (string\|number) | @typedef | 0 |
| (string\|number\|null) | @param | 0 |
| (string\|undefined) | @type | 0 |
| * | @param | 0 |
| ...[number] | function (string, ...[number]): number | 1 |
| ...number | @param | 0 |
| ? | @param | 0 |
| ?string | ?string= | 0 |
| ?string= | function (?string=, number=) | 0 |
| A | A.<U> | -1 |
| A | A.<string> | -1 |
| A.<U> | @extends | 0 |
| A.<string> | @extends | 0 |
| Array | Array.<Function> | -1 |
| Array | Array.<number> | -1 |
| Array.<Function> | @type | 0 |
| Array.<number> | @param | 0 |
| DOMException | @throws | 0 |
| Element | @param | 0 |
| Element | @return | 0 |
| Foo | Foo.<X> | -1 |
| Foo | Foo.<Y> | -1 |
| Foo | Foo.<Y> | -1 |
| Foo | Foo.<number> | -1 |
| Foo | Foo.<string> | -1 |
| Foo | Foo.<string> | -1 |
| Foo | Foo.<string> | -1 |
| Foo.<X> | @type | 0 |
| Foo.<Y> | @param | 0 |
| Foo.<Y> | @type | 0 |
| Foo.<number> | @implements | 0 |
| Foo.<string> | !Foo.<string> | 0 |
| Foo.<string> | !Foo.<string> | 0 |
| Foo.<string> | @implements | 0 |
| Function | Array.<Function> | 0 |
| MyMap | MyMap.<string, number> | -1 |
| MyMap.<string, number> | @type | 0 |
| Object | !Object | 0 |
| Object | @return | 0 |
| Shape | @extends | 0 |
| Shape | @implements | 0 |
| T | @param | 0 |
| T | @param | 0 |
| T | @param | 0 |
| T | @param | 0 |
| T | @return | 0 |
| T | @return | 0 |
| T | @return | 0 |
| T1 | @param | 0 |
| T2 | @param | 0 |
| T3 | @param | 0 |
| T4 | @param | 0 |
| U | A.<U> | 0 |
| X | @extends | 0 |
| X | Foo.<X> | 0 |
| Y | Foo.<Y> | 0 |
| Y | Foo.<Y> | 0 |
| [number] | ...[number] | 0 |
| boolean | @define | 0 |
| boolean | @define | 0 |
| boolean | @return | 0 |
| boolean | function (string, boolean) | 1 |
| function (): number | @param | 0 |
| function (?string=, number=) | @param | 0 |
| function (new: goog.ui.Menu, string) | @param | 0 |
| function (string, ...[number]): number | @param | 0 |
| function (string, boolean) | @param | 0 |
| function (this: goog.ui.Menu, string) | @param | 0 |
| function (x: !number, y: !number): number | @param | 0 |
| goog.NumberLike | @param | 0 |
| goog.ds.BasicNodeList | @extends | 0 |
| goog.ui.Menu | function (new: goog.ui.Menu, string) | -2 |
| goog.ui.Menu | function (this: goog.ui.Menu, string) | -2 |
| null | (string\|number\|null) | 2 |
| number | !number | 0 |
| number | !number | 0 |
| number | (string\|number) | 1 |
| number | (string\|number\|null) | 1 |
| number | ...number | 0 |
| number | @enum | 0 |
| number | @param | 0 |
| number | @type | 0 |
| number | @type | 0 |
| number | Array.<number> | 0 |
| number | Foo.<number> | 0 |
| number | MyMap.<string, number> | 1 |
| number | [number] | 0 |
| number | function (): number | -1 |
| number | function (string, ...[number]): number | -1 |
| number | function (x: !number, y: !number): number | -1 |
| number | number= | 0 |
| number | number= | 0 |
| number | number? | 0 |
| number | {myNum: number, myObject} | 0 |
| number= | @param | 0 |
| number= | function (?string=, number=) | 1 |
| number? | @type | 0 |
| string | (string\|number) | 0 |
| string | (string\|number\|null) | 0 |
| string | (string\|undefined) | 0 |
| string | ?string | 0 |
| string | @return | 0 |
| string | @type | 0 |
| string | @type | 0 |
| string | @type | 0 |
| string | A.<string> | 0 |
| string | Foo.<string> | 0 |
| string | Foo.<string> | 0 |
| string | Foo.<string> | 0 |
| string | MyMap.<string, number> | 0 |
| string | function (new: goog.ui.Menu, string) | 0 |
| string | function (string, ...[number]): number | 0 |
| string | function (string, boolean) | 0 |
| string | function (this: goog.ui.Menu, string) | 0 |
| undefined | (string\|undefined) | 1 |
| {myNum: number, myObject} | @type | 0 |
| tst.js:1:3:1:2 | * | tst.js:241:4:241:9 | @param | 0 |
| tst.js:1:3:1:2 | ? | tst.js:242:4:242:9 | @param | 0 |
| tst.js:1:3:1:2 | T | tst.js:252:5:252:11 | @return | 0 |
| tst.js:1:3:1:2 | T | tst.js:255:5:255:10 | @param | 0 |
| tst.js:1:3:1:2 | T | tst.js:262:4:262:9 | @param | 0 |
| tst.js:1:3:1:2 | T | tst.js:306:5:306:10 | @param | 0 |
| tst.js:1:3:1:2 | T | tst.js:328:5:328:11 | @return | 0 |
| tst.js:1:3:1:2 | T | tst.js:339:4:339:9 | @param | 0 |
| tst.js:1:3:1:2 | T | tst.js:340:4:340:10 | @return | 0 |
| tst.js:1:3:1:2 | X | tst.js:283:4:283:11 | @extends | 0 |
| tst.js:1:3:1:4 | A | tst.js:1:3:1:6 | A.<U> | -1 |
| tst.js:1:3:1:4 | A | tst.js:1:3:1:11 | A.<string> | -1 |
| tst.js:1:3:1:6 | A.<U> | tst.js:318:4:318:11 | @extends | 0 |
| tst.js:1:3:1:8 | !Object | tst.js:229:5:229:9 | @type | 0 |
| tst.js:1:3:1:11 | A.<string> | tst.js:311:4:311:11 | @extends | 0 |
| tst.js:1:3:1:14 | !Foo.<string> | tst.js:258:5:258:9 | @type | 0 |
| tst.js:1:3:1:14 | !Foo.<string> | tst.js:259:15:259:19 | @type | 0 |
| tst.js:1:3:1:16 | (string\|number) | tst.js:216:5:216:12 | @typedef | 0 |
| tst.js:1:3:1:26 | {myNum: number, myObject} | tst.js:223:5:223:9 | @type | 0 |
| tst.js:1:4:1:3 | T1 | tst.js:364:6:364:11 | @param | 0 |
| tst.js:1:4:1:3 | T2 | tst.js:369:6:369:11 | @param | 0 |
| tst.js:1:4:1:3 | T3 | tst.js:376:6:376:11 | @param | 0 |
| tst.js:1:4:1:3 | T4 | tst.js:381:6:381:11 | @param | 0 |
| tst.js:1:5:1:6 | Foo | tst.js:1:5:1:8 | Foo.<X> | -1 |
| tst.js:1:5:1:6 | Foo | tst.js:1:5:1:8 | Foo.<Y> | -1 |
| tst.js:1:5:1:6 | Foo | tst.js:1:5:1:8 | Foo.<Y> | -1 |
| tst.js:1:5:1:6 | Foo | tst.js:1:5:1:13 | Foo.<number> | -1 |
| tst.js:1:5:1:6 | Foo | tst.js:1:5:1:13 | Foo.<string> | -1 |
| tst.js:1:5:1:8 | Foo.<X> | tst.js:288:5:288:9 | @type | 0 |
| tst.js:1:5:1:8 | Foo.<Y> | tst.js:289:5:289:9 | @type | 0 |
| tst.js:1:5:1:8 | Foo.<Y> | tst.js:294:5:294:10 | @param | 0 |
| tst.js:1:5:1:10 | ...number | tst.js:238:4:238:9 | @param | 0 |
| tst.js:1:5:1:13 | Foo.<number> | tst.js:334:4:334:14 | @implements | 0 |
| tst.js:1:5:1:13 | Foo.<string> | tst.js:333:4:333:14 | @implements | 0 |
| tst.js:1:6:1:6 | U | tst.js:1:3:1:6 | A.<U> | 0 |
| tst.js:1:6:1:7 | Foo | tst.js:1:6:1:14 | Foo.<string> | -1 |
| tst.js:1:6:1:7 | Foo | tst.js:1:6:1:14 | Foo.<string> | -1 |
| tst.js:1:6:1:14 | Foo.<string> | tst.js:1:3:1:14 | !Foo.<string> | 0 |
| tst.js:1:6:1:14 | Foo.<string> | tst.js:1:3:1:14 | !Foo.<string> | 0 |
| tst.js:1:7:1:6 | Shape | tst.js:95:4:95:14 | @implements | 0 |
| tst.js:1:7:1:6 | Shape | tst.js:110:4:110:11 | @extends | 0 |
| tst.js:1:7:1:8 | Array | tst.js:1:7:1:15 | Array.<number> | -1 |
| tst.js:1:7:1:8 | MyMap | tst.js:1:7:1:23 | MyMap.<string, number> | -1 |
| tst.js:1:7:1:15 | Array.<number> | tst.js:357:4:357:9 | @param | 0 |
| tst.js:1:7:1:23 | MyMap.<string, number> | tst.js:275:5:275:9 | @type | 0 |
| tst.js:1:8:1:7 | Object | tst.js:134:4:134:10 | @return | 0 |
| tst.js:1:8:1:7 | number | tst.js:53:4:53:8 | @enum | 0 |
| tst.js:1:8:1:7 | number | tst.js:142:4:142:9 | @param | 0 |
| tst.js:1:8:1:7 | number | tst.js:346:5:346:9 | @type | 0 |
| tst.js:1:8:1:7 | number | tst.js:347:5:347:9 | @type | 0 |
| tst.js:1:8:1:7 | string | tst.js:10:4:10:8 | @type | 0 |
| tst.js:1:8:1:7 | string | tst.js:171:4:171:10 | @return | 0 |
| tst.js:1:8:1:7 | string | tst.js:212:4:212:8 | @type | 0 |
| tst.js:1:8:1:7 | string | tst.js:345:5:345:9 | @type | 0 |
| tst.js:1:8:1:8 | X | tst.js:1:5:1:8 | Foo.<X> | 0 |
| tst.js:1:8:1:8 | Y | tst.js:1:5:1:8 | Foo.<Y> | 0 |
| tst.js:1:8:1:8 | Y | tst.js:1:5:1:8 | Foo.<Y> | 0 |
| tst.js:1:8:1:8 | number | tst.js:1:8:1:8 | number= | 0 |
| tst.js:1:8:1:8 | number | tst.js:1:8:1:8 | number? | 0 |
| tst.js:1:8:1:8 | number= | tst.js:239:4:239:9 | @param | 0 |
| tst.js:1:8:1:8 | number? | tst.js:226:5:226:9 | @type | 0 |
| tst.js:1:8:1:8 | string | tst.js:1:8:1:17 | (string\|undefined) | 0 |
| tst.js:1:8:1:8 | string | tst.js:1:8:1:19 | (string\|number\|null) | 0 |
| tst.js:1:8:1:17 | (string\|undefined) | tst.js:349:5:349:9 | @type | 0 |
| tst.js:1:8:1:19 | (string\|number\|null) | tst.js:143:4:143:9 | @param | 0 |
| tst.js:1:9:1:8 | Element | tst.js:163:4:163:9 | @param | 0 |
| tst.js:1:9:1:8 | Element | tst.js:199:12:199:18 | @return | 0 |
| tst.js:1:9:1:8 | Object | tst.js:1:3:1:8 | !Object | 0 |
| tst.js:1:9:1:8 | boolean | tst.js:23:5:23:11 | @define | 0 |
| tst.js:1:9:1:8 | boolean | tst.js:26:5:26:11 | @define | 0 |
| tst.js:1:9:1:8 | boolean | tst.js:31:4:31:10 | @return | 0 |
| tst.js:1:9:1:9 | string | tst.js:1:3:1:16 | (string\|number) | 0 |
| tst.js:1:10:1:10 | Function | tst.js:1:10:1:11 | Array.<Function> | 0 |
| tst.js:1:10:1:11 | Array | tst.js:1:10:1:11 | Array.<Function> | -1 |
| tst.js:1:10:1:11 | Array.<Function> | tst.js:155:4:155:8 | @type | 0 |
| tst.js:1:10:1:19 | function (): number | tst.js:234:4:234:9 | @param | 0 |
| tst.js:1:10:1:26 | function (string, boolean) | tst.js:233:4:233:9 | @param | 0 |
| tst.js:1:10:1:28 | function (?string=, number=) | tst.js:240:4:240:9 | @param | 0 |
| tst.js:1:10:1:35 | function (new: goog.ui.Menu, string) | tst.js:236:4:236:9 | @param | 0 |
| tst.js:1:10:1:36 | function (this: goog.ui.Menu, string) | tst.js:235:4:235:9 | @param | 0 |
| tst.js:1:10:1:38 | function (string, ...[number]): number | tst.js:237:4:237:9 | @param | 0 |
| tst.js:1:10:1:38 | function (x: !number, y: !number): number | tst.js:358:4:358:9 | @param | 0 |
| tst.js:1:11:1:10 | number | tst.js:1:5:1:10 | ...number | 0 |
| tst.js:1:11:1:11 | string | tst.js:1:3:1:11 | A.<string> | 0 |
| tst.js:1:12:1:18 | ?string | tst.js:1:12:1:19 | ?string= | 0 |
| tst.js:1:12:1:19 | ?string= | tst.js:1:10:1:28 | function (?string=, number=) | 0 |
| tst.js:1:13:1:13 | number | tst.js:1:5:1:13 | Foo.<number> | 0 |
| tst.js:1:13:1:13 | string | tst.js:1:5:1:13 | Foo.<string> | 0 |
| tst.js:1:14:1:13 | DOMException | tst.js:206:4:206:10 | @throws | 0 |
| tst.js:1:14:1:14 | string | tst.js:1:6:1:14 | Foo.<string> | 0 |
| tst.js:1:14:1:14 | string | tst.js:1:6:1:14 | Foo.<string> | 0 |
| tst.js:1:14:1:20 | !number | tst.js:1:10:1:38 | function (x: !number, y: !number): number | 0 |
| tst.js:1:15:1:15 | number | tst.js:1:7:1:15 | Array.<number> | 0 |
| tst.js:1:15:1:15 | number | tst.js:1:8:1:19 | (string\|number\|null) | 1 |
| tst.js:1:15:1:15 | string | tst.js:1:7:1:23 | MyMap.<string, number> | 0 |
| tst.js:1:16:1:16 | number | tst.js:1:3:1:16 | (string\|number) | 1 |
| tst.js:1:16:1:16 | number | tst.js:1:3:1:26 | {myNum: number, myObject} | 0 |
| tst.js:1:17:1:16 | goog.NumberLike | tst.js:219:5:219:10 | @param | 0 |
| tst.js:1:17:1:17 | string | tst.js:1:10:1:26 | function (string, boolean) | 0 |
| tst.js:1:17:1:17 | string | tst.js:1:10:1:38 | function (string, ...[number]): number | 0 |
| tst.js:1:18:1:17 | undefined | tst.js:1:8:1:17 | (string\|undefined) | 1 |
| tst.js:1:18:1:18 | string | tst.js:1:12:1:18 | ?string | 0 |
| tst.js:1:20:1:19 | null | tst.js:1:8:1:19 | (string\|number\|null) | 2 |
| tst.js:1:20:1:19 | number | tst.js:1:10:1:19 | function (): number | -1 |
| tst.js:1:20:1:20 | number | tst.js:1:14:1:20 | !number | 0 |
| tst.js:1:23:1:22 | goog.ds.BasicNodeList | tst.js:68:4:68:11 | @extends | 0 |
| tst.js:1:23:1:23 | number | tst.js:1:7:1:23 | MyMap.<string, number> | 1 |
| tst.js:1:23:1:30 | ...[number] | tst.js:1:10:1:38 | function (string, ...[number]): number | 1 |
| tst.js:1:25:1:31 | !number | tst.js:1:10:1:38 | function (x: !number, y: !number): number | 1 |
| tst.js:1:26:1:26 | boolean | tst.js:1:10:1:26 | function (string, boolean) | 1 |
| tst.js:1:27:1:27 | goog.ui.Menu | tst.js:1:10:1:35 | function (new: goog.ui.Menu, string) | -2 |
| tst.js:1:27:1:27 | number | tst.js:1:27:1:28 | number= | 0 |
| tst.js:1:27:1:28 | number= | tst.js:1:10:1:28 | function (?string=, number=) | 1 |
| tst.js:1:28:1:28 | goog.ui.Menu | tst.js:1:10:1:36 | function (this: goog.ui.Menu, string) | -2 |
| tst.js:1:29:1:29 | number | tst.js:1:29:1:30 | [number] | 0 |
| tst.js:1:29:1:30 | [number] | tst.js:1:23:1:30 | ...[number] | 0 |
| tst.js:1:31:1:31 | number | tst.js:1:25:1:31 | !number | 0 |
| tst.js:1:35:1:35 | string | tst.js:1:10:1:35 | function (new: goog.ui.Menu, string) | 0 |
| tst.js:1:36:1:36 | string | tst.js:1:10:1:36 | function (this: goog.ui.Menu, string) | 0 |
| tst.js:1:39:1:38 | number | tst.js:1:10:1:38 | function (string, ...[number]): number | -1 |
| tst.js:1:39:1:38 | number | tst.js:1:10:1:38 | function (x: !number, y: !number): number | -1 |
test_Function_getDocumentation
| tst.js:20:1:21:1 | functio ... t() {\\n} | tst.js:16:1:19:3 | /**\\n * ... tor\\n */ |
| tst.js:36:34:37:1 | function(node) {\\n} | tst.js:29:1:35:3 | /**\\n * ... ().\\n */ |
@@ -506,25 +506,25 @@ test_Function_getDocumentation
| tst.js:378:14:378:19 | (p) {} | tst.js:375:3:377:5 | /**\\n ... p\\n */ |
| tst.js:383:14:383:19 | (p) {} | tst.js:380:3:382:5 | /**\\n ... p\\n */ |
test_JSDocOptionalParameterTypeExpr
| ?string= | ?string |
| number= | number |
| number= | number |
| tst.js:1:8:1:8 | number= | tst.js:1:8:1:8 | number |
| tst.js:1:12:1:19 | ?string= | tst.js:1:12:1:18 | ?string |
| tst.js:1:27:1:28 | number= | tst.js:1:27:1:27 | number |
test_getParameterTag
| tst.js:146:37:146:44 | groupNum | groupNum | tst.js:142:4:142:9 | @param | groupNum | number |
| tst.js:146:47:146:50 | term | term | tst.js:143:4:143:9 | @param | term | (string\|number\|null) |
| tst.js:166:59:166:65 | element | element | tst.js:163:4:163:9 | @param | element | Element |
| tst.js:220:28:220:28 | x | x | tst.js:219:5:219:10 | @param | x | goog.NumberLike |
| tst.js:256:30:256:30 | t | t | tst.js:255:5:255:10 | @param | t | T |
| tst.js:266:16:266:16 | t | t | tst.js:262:4:262:9 | @param | t | T |
| tst.js:295:22:295:25 | fooY | fooY | tst.js:294:5:294:10 | @param | fooY | Foo.<Y> |
| tst.js:307:31:307:31 | t | t | tst.js:306:5:306:10 | @param | t | T |
| tst.js:343:21:343:21 | a | a | tst.js:339:4:339:9 | @param | a | T |
| tst.js:360:15:360:19 | array | array | tst.js:357:4:357:9 | @param | array | Array.<number> |
| tst.js:360:22:360:23 | fn | fn | tst.js:358:4:358:9 | @param | fn | function (x: !number, y: !number): number |
| tst.js:366:27:366:27 | p | p | tst.js:364:6:364:11 | @param | p | T1 |
| tst.js:371:15:371:15 | p | p | tst.js:369:6:369:11 | @param | p | T2 |
| tst.js:378:15:378:15 | p | p | tst.js:376:6:376:11 | @param | p | T3 |
| tst.js:383:15:383:15 | p | p | tst.js:381:6:381:11 | @param | p | T4 |
| tst.js:146:37:146:44 | groupNum | groupNum | tst.js:142:4:142:9 | @param | groupNum | tst.js:1:8:1:7 | number |
| tst.js:146:47:146:50 | term | term | tst.js:143:4:143:9 | @param | term | tst.js:1:8:1:19 | (string\|number\|null) |
| tst.js:166:59:166:65 | element | element | tst.js:163:4:163:9 | @param | element | tst.js:1:9:1:8 | Element |
| tst.js:220:28:220:28 | x | x | tst.js:219:5:219:10 | @param | x | tst.js:1:17:1:16 | goog.NumberLike |
| tst.js:256:30:256:30 | t | t | tst.js:255:5:255:10 | @param | t | tst.js:1:3:1:2 | T |
| tst.js:266:16:266:16 | t | t | tst.js:262:4:262:9 | @param | t | tst.js:1:3:1:2 | T |
| tst.js:295:22:295:25 | fooY | fooY | tst.js:294:5:294:10 | @param | fooY | tst.js:1:5:1:8 | Foo.<Y> |
| tst.js:307:31:307:31 | t | t | tst.js:306:5:306:10 | @param | t | tst.js:1:3:1:2 | T |
| tst.js:343:21:343:21 | a | a | tst.js:339:4:339:9 | @param | a | tst.js:1:3:1:2 | T |
| tst.js:360:15:360:19 | array | array | tst.js:357:4:357:9 | @param | array | tst.js:1:7:1:15 | Array.<number> |
| tst.js:360:22:360:23 | fn | fn | tst.js:358:4:358:9 | @param | fn | tst.js:1:10:1:38 | function (x: !number, y: !number): number |
| tst.js:366:27:366:27 | p | p | tst.js:364:6:364:11 | @param | p | tst.js:1:4:1:3 | T1 |
| tst.js:371:15:371:15 | p | p | tst.js:369:6:369:11 | @param | p | tst.js:1:4:1:3 | T2 |
| tst.js:378:15:378:15 | p | p | tst.js:376:6:376:11 | @param | p | tst.js:1:4:1:3 | T3 |
| tst.js:383:15:383:15 | p | p | tst.js:381:6:381:11 | @param | p | tst.js:1:4:1:3 | T4 |
test_VarDeclStmt_getDocumentation
| tst.js:5:15:5:36 | var MY_ ... stout'; | tst.js:5:1:5:13 | /** @const */ |
| tst.js:24:1:24:24 | var ENA ... = true; | tst.js:23:1:23:24 | /** @de ... ean} */ |
@@ -544,25 +544,25 @@ test_VarDeclStmt_getDocumentation
| tst.js:347:23:347:60 | var sum ... y("2"); | tst.js:347:1:347:21 | /** @ty ... ber} */ |
| tst.js:349:33:349:52 | var string_or_undef; | tst.js:349:1:349:31 | /** @ty ... ned} */ |
test_JSDocAppliedTypeExpr
| A.<U> | A | 0 | U |
| A.<string> | A | 0 | string |
| Array.<Function> | Array | 0 | Function |
| Array.<number> | Array | 0 | number |
| Foo.<X> | Foo | 0 | X |
| Foo.<Y> | Foo | 0 | Y |
| Foo.<Y> | Foo | 0 | Y |
| Foo.<number> | Foo | 0 | number |
| Foo.<string> | Foo | 0 | string |
| Foo.<string> | Foo | 0 | string |
| Foo.<string> | Foo | 0 | string |
| MyMap.<string, number> | MyMap | 0 | string |
| MyMap.<string, number> | MyMap | 1 | number |
| tst.js:1:3:1:6 | A.<U> | tst.js:1:3:1:4 | A | 0 | tst.js:1:6:1:6 | U |
| tst.js:1:3:1:11 | A.<string> | tst.js:1:3:1:4 | A | 0 | tst.js:1:11:1:11 | string |
| tst.js:1:5:1:8 | Foo.<X> | tst.js:1:5:1:6 | Foo | 0 | tst.js:1:8:1:8 | X |
| tst.js:1:5:1:8 | Foo.<Y> | tst.js:1:5:1:6 | Foo | 0 | tst.js:1:8:1:8 | Y |
| tst.js:1:5:1:8 | Foo.<Y> | tst.js:1:5:1:6 | Foo | 0 | tst.js:1:8:1:8 | Y |
| tst.js:1:5:1:13 | Foo.<number> | tst.js:1:5:1:6 | Foo | 0 | tst.js:1:13:1:13 | number |
| tst.js:1:5:1:13 | Foo.<string> | tst.js:1:5:1:6 | Foo | 0 | tst.js:1:13:1:13 | string |
| tst.js:1:6:1:14 | Foo.<string> | tst.js:1:6:1:7 | Foo | 0 | tst.js:1:14:1:14 | string |
| tst.js:1:6:1:14 | Foo.<string> | tst.js:1:6:1:7 | Foo | 0 | tst.js:1:14:1:14 | string |
| tst.js:1:7:1:15 | Array.<number> | tst.js:1:7:1:8 | Array | 0 | tst.js:1:15:1:15 | number |
| tst.js:1:7:1:23 | MyMap.<string, number> | tst.js:1:7:1:8 | MyMap | 0 | tst.js:1:15:1:15 | string |
| tst.js:1:7:1:23 | MyMap.<string, number> | tst.js:1:7:1:8 | MyMap | 1 | tst.js:1:23:1:23 | number |
| tst.js:1:10:1:11 | Array.<Function> | tst.js:1:10:1:11 | Array | 0 | tst.js:1:10:1:10 | Function |
test_JSDocNonNullableTypeExpr
| !Foo.<string> | Foo.<string> | prefix |
| !Foo.<string> | Foo.<string> | prefix |
| !Object | Object | prefix |
| !number | number | prefix |
| !number | number | prefix |
| tst.js:1:3:1:8 | !Object | tst.js:1:9:1:8 | Object | prefix |
| tst.js:1:3:1:14 | !Foo.<string> | tst.js:1:6:1:14 | Foo.<string> | prefix |
| tst.js:1:3:1:14 | !Foo.<string> | tst.js:1:6:1:14 | Foo.<string> | prefix |
| tst.js:1:14:1:20 | !number | tst.js:1:20:1:20 | number | prefix |
| tst.js:1:25:1:31 | !number | tst.js:1:31:1:31 | number | prefix |
test_ParExpr_getDocumentation
| tst.js:117:42:119:10 | ({\\n ... }) | tst.js:117:9:117:40 | /** @le ... ype} */ |
| tst.js:259:40:259:50 | (new Foo()) | tst.js:259:11:259:38 | /** @ty ... ng>} */ |

View File

@@ -0,0 +1,21 @@
test_isString
| tst.js:1:8:1:7 | string |
test_isNumber
| tst.js:1:8:1:8 | number |
test_QualifiedName
| VarType | tst.js:1:9:1:8 | VarType |
| boolean | tst.js:1:9:1:8 | boolean |
| foo.bar.baz | tst.js:1:13:1:12 | foo.bar.baz |
| number | tst.js:1:8:1:8 | number |
| string | tst.js:1:8:1:7 | string |
test_ParameterType
| tst.js:7:12:7:12 | x | tst.js:1:8:1:7 | string |
| tst.js:7:15:7:15 | y | tst.js:1:8:1:8 | number? |
| tst.js:7:18:7:18 | z | tst.js:1:13:1:12 | foo.bar.baz |
test_VarType
| tst.js:7:12:7:12 | x | tst.js:1:8:1:7 | string |
| tst.js:7:15:7:15 | y | tst.js:1:8:1:8 | number? |
| tst.js:7:18:7:18 | z | tst.js:1:13:1:12 | foo.bar.baz |
| tst.js:11:7:11:7 | w | tst.js:1:9:1:8 | VarType |
test_ReturnType
| tst.js:7:1:12:1 | functio ... null;\\n} | tst.js:1:9:1:8 | boolean |

View File

@@ -0,0 +1,25 @@
import javascript
query TypeAnnotation test_isString() {
result.isString()
}
query TypeAnnotation test_isNumber() {
result.isNumber()
}
query TypeAnnotation test_QualifiedName(string name) {
result.hasQualifiedName(name)
}
query TypeAnnotation test_ParameterType(Parameter p) {
result = p.getTypeAnnotation()
}
query TypeAnnotation test_VarType(VarDecl decl) {
result = decl.getTypeAnnotation()
}
query TypeAnnotation test_ReturnType(Function f) {
result = f.getReturnTypeAnnotation()
}

View File

@@ -0,0 +1,12 @@
/**
* @param {string} x
* @param {number?} y
* @param {foo.bar.baz} z
* @returns {boolean}
*/
function f(x, y, z) {
/**
* @type {VarType}
*/
var w = null;
}

View File

@@ -0,0 +1 @@
| tst.ts:5:8:5:19 | ResolvedType | resolved | ResolvedType |

View File

@@ -0,0 +1,5 @@
import javascript
from TypeAnnotation type, string mod, string name
where type.hasQualifiedName(mod, name)
select type, mod, name

View File

@@ -0,0 +1,3 @@
export interface ResolvedType {
x: number;
}

View File

@@ -0,0 +1 @@
{ "include": ["."] }

View File

@@ -0,0 +1,5 @@
import { UnresolvedType } from "unresolved";
import { ResolvedType } from "resolved";
let x: UnresolvedType;
let y: ResolvedType;