add printAst query for printing JS/TS/JSON/YAML/HTML

This commit is contained in:
Erik Krogh Kristensen
2020-10-08 21:16:40 +02:00
parent ce8567c64a
commit d3e3c11fa6
28 changed files with 6592 additions and 29 deletions

View File

@@ -0,0 +1,28 @@
/**
* @name Print AST
* @description Outputs a representation of a file's Abstract Syntax Tree. This
* query is used by the VS Code extension.
* @id js/print-ast
* @kind graph
* @tags ide-contextual-queries/print-ast
*/
import javascript
import semmle.javascript.PrintAst
import definitions
/**
* The source file to generate an AST from.
*/
external string selectedSourceFile();
class PrintAstConfigurationOverride extends PrintAstConfiguration {
/**
* Holds if the location matches the selected file in the VS Code extension and
* the element is not a synthetic constructor.
*/
override predicate shouldPrint(Locatable e, Location l) {
super.shouldPrint(e, l) and
l.getFile() = getEncodedFile(selectedSourceFile())
}
}

View File

@@ -256,6 +256,8 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
ClassDefinition getSuperClassDefinition() {
result = getSuperClass().analyze().getAValue().(AbstractClass).getClass()
}
override string getAPrimaryQlClass() { result = "ClassDefinition" }
}
/**
@@ -342,6 +344,8 @@ private class ClassInitializedMember extends MemberDeclaration {
ClassInitializedMember() { this instanceof MethodDefinition or this.isStatic() }
int getIndex() { properties(this, _, result, _, _) }
override string getAPrimaryQlClass() { result = "ClassInitializedMember" }
}
/**
@@ -361,6 +365,8 @@ class SuperExpr extends @super_expr, Expr {
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getEnclosingFunction().getThisBinder() }
override string getAPrimaryQlClass() { result = "SuperExpr" }
}
/**
@@ -412,6 +418,8 @@ class SuperPropAccess extends PropAccess {
*/
class NewTargetExpr extends @newtarget_expr, Expr {
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "NewTargetExpr" }
}
/**
@@ -574,6 +582,8 @@ class MemberDeclaration extends @property, Documentable {
* True if this is abstract, ambient, or an overload signature.
*/
predicate isSignature() { not isConcrete() }
override string getAPrimaryQlClass() { result = "MemberDeclaration" }
}
/**
@@ -748,7 +758,9 @@ private predicate hasOverloadedConstructorCallSignature(ClassOrInterface type) {
* }
* ```
*/
class MethodDefinition extends MethodDeclaration, MemberDefinition { }
class MethodDefinition extends MethodDeclaration, MemberDefinition {
override string getAPrimaryQlClass() { result = "MethodDefinition" }
}
/**
* A method signature declared in a class or interface, that is, a method without a function body.
@@ -763,7 +775,9 @@ class MethodDefinition extends MethodDeclaration, MemberDefinition { }
*
* Note that TypeScript call signatures are not considered method signatures.
*/
class MethodSignature extends MethodDeclaration, MemberSignature { }
class MethodSignature extends MethodDeclaration, MemberSignature {
override string getAPrimaryQlClass() { result = "MethodSignature" }
}
/**
* A constructor declaration in a class, either a concrete definition or a signature without a body.
@@ -792,6 +806,8 @@ class ConstructorDeclaration extends MethodDeclaration {
/** Holds if this is a synthetic default constructor. */
predicate isSynthetic() { getLocation().isEmpty() }
override string getAPrimaryQlClass() { result = "ConstructorDeclaration" }
}
/**
@@ -813,7 +829,9 @@ class ConstructorDeclaration extends MethodDeclaration {
* }
* ```
*/
class ConstructorDefinition extends ConstructorDeclaration, MethodDefinition { }
class ConstructorDefinition extends ConstructorDeclaration, MethodDefinition {
override string getAPrimaryQlClass() { result = "ConstructorDefinition" }
}
/**
* A constructor signature declared in a class, that is, a constructor without a function body.
@@ -824,7 +842,9 @@ class ConstructorDefinition extends ConstructorDeclaration, MethodDefinition { }
* }
* ```
*/
class ConstructorSignature extends ConstructorDeclaration, MethodSignature { }
class ConstructorSignature extends ConstructorDeclaration, MethodSignature {
override string getAPrimaryQlClass() { result = "ConstructorSignature" }
}
/**
* A function generated by the extractor to implement a synthetic default constructor.
@@ -925,7 +945,9 @@ abstract class AccessorMethodSignature extends MethodSignature, AccessorMethodDe
* }
* ```
*/
class GetterMethodDeclaration extends AccessorMethodDeclaration, @property_getter { }
class GetterMethodDeclaration extends AccessorMethodDeclaration, @property_getter {
override string getAPrimaryQlClass() { result = "GetterMethodDeclaration" }
}
/**
* A concrete getter method definition in a class, that is, a getter method with a function body.
@@ -945,7 +967,9 @@ class GetterMethodDeclaration extends AccessorMethodDeclaration, @property_gette
* }
* ```
*/
class GetterMethodDefinition extends GetterMethodDeclaration, AccessorMethodDefinition { }
class GetterMethodDefinition extends GetterMethodDeclaration, AccessorMethodDefinition {
override string getAPrimaryQlClass() { result = "GetterMethodDefinition" }
}
/**
* A getter method signature declared in a class or interface, that is, a getter method without a function body.
@@ -958,7 +982,9 @@ class GetterMethodDefinition extends GetterMethodDeclaration, AccessorMethodDefi
* }
* ```
*/
class GetterMethodSignature extends GetterMethodDeclaration, AccessorMethodSignature { }
class GetterMethodSignature extends GetterMethodDeclaration, AccessorMethodSignature {
override string getAPrimaryQlClass() { result = "GetterMethodSignature" }
}
/**
* A setter method declaration in a class or interface, either a concrete definition or a signature without a body.
@@ -981,7 +1007,9 @@ class GetterMethodSignature extends GetterMethodDeclaration, AccessorMethodSigna
* }
* ```
*/
class SetterMethodDeclaration extends AccessorMethodDeclaration, @property_setter { }
class SetterMethodDeclaration extends AccessorMethodDeclaration, @property_setter {
override string getAPrimaryQlClass() { result = "SetterMethodDeclaration" }
}
/**
* A concrete setter method definition in a class, that is, a setter method with a function body
@@ -1000,7 +1028,9 @@ class SetterMethodDeclaration extends AccessorMethodDeclaration, @property_sette
* }
* ```
*/
class SetterMethodDefinition extends SetterMethodDeclaration, AccessorMethodDefinition { }
class SetterMethodDefinition extends SetterMethodDeclaration, AccessorMethodDefinition {
override string getAPrimaryQlClass() { result = "SetterMethodDefinition" }
}
/**
* A setter method signature declared in a class or interface, that is, a setter method without a function body.
@@ -1013,7 +1043,9 @@ class SetterMethodDefinition extends SetterMethodDeclaration, AccessorMethodDefi
* }
* ```
*/
class SetterMethodSignature extends SetterMethodDeclaration, AccessorMethodSignature { }
class SetterMethodSignature extends SetterMethodDeclaration, AccessorMethodSignature {
override string getAPrimaryQlClass() { result = "SetterMethodSignature" }
}
/**
* A field declaration in a class or interface, either a concrete definition or an abstract or ambient field signature.
@@ -1047,6 +1079,8 @@ class FieldDeclaration extends MemberDeclaration, @field {
/** Holds if this is a TypeScript field marked as definitely assigned with the `!` operator. */
predicate hasDefiniteAssignmentAssertion() { has_definite_assignment_assertion(this) }
override string getAPrimaryQlClass() { result = "FieldDeclaration" }
}
/**
@@ -1203,4 +1237,6 @@ class IndexSignature extends @index_signature, MemberSignature {
override InterfaceDefinition getDeclaringType() {
result = MemberSignature.super.getDeclaringType()
}
override string getAPrimaryQlClass() { result = "IndexSignature" }
}

View File

@@ -79,6 +79,8 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
/** Holds if this is declared with the `type` keyword, so it only imports types. */
predicate isTypeOnly() { has_type_keyword(this) }
override string getAPrimaryQlClass() { result = "ImportDeclaration" }
}
/** A literal path expression appearing in an `import` declaration. */
@@ -129,6 +131,8 @@ class ImportSpecifier extends Expr, @import_specifier {
/** Gets the local variable into which this specifier imports. */
VarDecl getLocal() { result = getChildExpr(1) }
override string getAPrimaryQlClass() { result = "ImportSpecifier" }
}
/**
@@ -262,6 +266,8 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
/** Holds if is declared with the `type` keyword, so only types are exported. */
predicate isTypeOnly() { has_type_keyword(this) }
override string getAPrimaryQlClass() { result = "ExportDeclaration" }
}
/**
@@ -511,6 +517,8 @@ class ExportSpecifier extends Expr, @exportspecifier {
* an exported name since it does not export a unique symbol.
*/
string getExportedName() { result = getExported().getName() }
override string getAPrimaryQlClass() { result = "ExportSpecifier" }
}
/**

View File

@@ -273,6 +273,8 @@ private DataFlow::Node getCatchParameterFromStmt(Stmt stmt) {
class Identifier extends @identifier, ExprOrType {
/** Gets the name of this identifier. */
string getName() { literals(result, _, this) }
override string getAPrimaryQlClass() { result = "Identifier" }
}
/**
@@ -290,6 +292,8 @@ class Identifier extends @identifier, ExprOrType {
*/
class Label extends @label, Identifier, Expr {
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "Label" }
}
/**
@@ -317,6 +321,8 @@ class Literal extends @literal, Expr {
string getRawValue() { literals(_, result, this) }
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "Literal" }
}
/**
@@ -341,6 +347,8 @@ class ParExpr extends @par_expr, Expr {
override Expr getUnderlyingValue() { result = getExpression().getUnderlyingValue() }
override Expr getUnderlyingReference() { result = getExpression().getUnderlyingReference() }
override string getAPrimaryQlClass() { result = "ParExpr" }
}
/**
@@ -462,6 +470,8 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent {
/** Holds if this regular expression has an `s` flag. */
predicate isDotAll() { RegExp::isDotAll(getFlags()) }
override string getAPrimaryQlClass() { result = "RegExpLiteral" }
}
/**
@@ -491,6 +501,8 @@ class ThisExpr extends @this_expr, Expr {
or
result = getContainer().(TopLevel)
}
override string getAPrimaryQlClass() { result = "ThisExpr" }
}
/**
@@ -528,6 +540,8 @@ class ArrayExpr extends @array_expr, Expr {
predicate hasOmittedElement() { elementIsOmitted(_) }
override predicate isImpure() { getAnElement().isImpure() }
override string getAPrimaryQlClass() { result = "ArrayExpr" }
}
/**
@@ -568,6 +582,8 @@ class ObjectExpr extends @obj_expr, Expr {
predicate hasTrailingComma() { this.getLastToken().getPreviousToken().getValue() = "," }
override predicate isImpure() { getAProperty().isImpure() }
override string getAPrimaryQlClass() { result = "ObjectExpr" }
}
/**
@@ -668,6 +684,8 @@ class Property extends @property, Documentable {
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
override string getAPrimaryQlClass() { result = "Property" }
}
/**
@@ -791,6 +809,8 @@ class FunctionExpr extends @function_expr, Expr, Function {
override StmtContainer getEnclosingContainer() { result = Expr.super.getContainer() }
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "FunctionExpr" }
}
/**
@@ -811,6 +831,8 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function {
override predicate isImpure() { none() }
override Function getThisBinder() { result = getEnclosingContainer().(Function).getThisBinder() }
override string getAPrimaryQlClass() { result = "ArrowFunctionExpr" }
}
/**
@@ -838,6 +860,8 @@ class SeqExpr extends @seq_expr, Expr {
override predicate isImpure() { getAnOperand().isImpure() }
override Expr getUnderlyingValue() { result = getLastOperand().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "SeqExpr" }
}
/**
@@ -866,6 +890,8 @@ class ConditionalExpr extends @conditional_expr, Expr {
getCondition().isImpure() or
getABranch().isImpure()
}
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
}
/**
@@ -986,7 +1012,9 @@ class InvokeExpr extends @invokeexpr, Expr {
* new Array(16)
* ```
*/
class NewExpr extends @new_expr, InvokeExpr { }
class NewExpr extends @new_expr, InvokeExpr {
override string getAPrimaryQlClass() { result = "NewExpr" }
}
/**
* A function call expression.
@@ -1005,6 +1033,8 @@ class CallExpr extends @call_expr, InvokeExpr {
* is invoked, if any.
*/
Expr getReceiver() { result = getCallee().(PropAccess).getBase() }
override string getAPrimaryQlClass() { result = "CallExpr" }
}
/**
@@ -1037,6 +1067,8 @@ class MethodCallExpr extends CallExpr {
/** Holds if this invocation calls method `m` on expression `base`. */
predicate calls(Expr base, string m) { getMethodRef().accesses(base, m) }
override string getAPrimaryQlClass() { result = "MethodCallExpr" }
}
/**
@@ -1103,6 +1135,8 @@ class DotExpr extends @dot_expr, PropAccess {
Identifier getProperty() { result = getChildExpr(1) }
override predicate isImpure() { getBase().isImpure() }
override string getAPrimaryQlClass() { result = "DotExpr" }
}
/**
@@ -1124,6 +1158,8 @@ class IndexExpr extends @index_expr, PropAccess {
getBase().isImpure() or
getIndex().isImpure()
}
override string getAPrimaryQlClass() { result = "IndexExpr" }
}
/**
@@ -1148,6 +1184,8 @@ class UnaryExpr extends @unaryexpr, Expr {
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UnaryExpr" }
}
/**
@@ -1258,6 +1296,8 @@ class DeleteExpr extends @delete_expr, UnaryExpr {
*/
class SpreadElement extends @spread_element, UnaryExpr {
override string getOperator() { result = "..." }
override string getAPrimaryQlClass() { result = "SpreadElement" }
}
/**
@@ -1314,6 +1354,8 @@ class BinaryExpr extends @binaryexpr, Expr {
result = c4 - c3 - 1
)
}
override string getAPrimaryQlClass() { result = "BinaryExpr" }
}
/**
@@ -1846,6 +1888,8 @@ class Assignment extends @assignment, Expr {
*/
class AssignExpr extends @assign_expr, Assignment {
override Expr getUnderlyingValue() { result = getRhs().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "AssignExpr" }
}
private class TCompoundAssignExpr =
@@ -1864,7 +1908,9 @@ private class TCompoundAssignExpr =
* x /= 2
* ```
*/
class CompoundAssignExpr extends TCompoundAssignExpr, Assignment { }
class CompoundAssignExpr extends TCompoundAssignExpr, Assignment {
override string getAPrimaryQlClass() { result = "CompoundAssignExpr" }
}
/**
* A compound add-assign expression.
@@ -2056,6 +2102,8 @@ class UpdateExpr extends @updateexpr, Expr {
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UpdateExpr" }
}
/**
@@ -2137,6 +2185,8 @@ class YieldExpr extends @yield_expr, Expr {
or
not exists(getOperand()) and result = this
}
override string getAPrimaryQlClass() { result = "YieldExpr" }
}
/**
@@ -2194,6 +2244,8 @@ class ComprehensionExpr extends @comprehension_expr, Expr {
predicate isPostfix() {
exists(Token tk | tk = getFirstToken().getNextToken() | not tk.getValue().regexpMatch("if|for"))
}
override string getAPrimaryQlClass() { result = "ComprehensionExpr" }
}
/**
@@ -2246,6 +2298,8 @@ class ComprehensionBlock extends @comprehension_block, Expr {
getIterator().isImpure() or
getDomain().isImpure()
}
override string getAPrimaryQlClass() { result = "ComprehensionBlock" }
}
/**
@@ -2468,6 +2522,8 @@ class LegacyLetExpr extends Expr, @legacy_letexpr {
/** Gets the expression this `let` expression scopes over. */
Expr getBody() { result = getChildExpr(-1) }
override string getAPrimaryQlClass() { result = "LegacyLetExpr" }
}
/**
@@ -2569,6 +2625,8 @@ class AwaitExpr extends @await_expr, Expr {
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "AwaitExpr" }
}
/**
@@ -2586,6 +2644,8 @@ class AwaitExpr extends @await_expr, Expr {
*/
class FunctionSentExpr extends @function_sent_expr, Expr {
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "FunctionSentExpr" }
}
/**
@@ -2621,6 +2681,8 @@ class Decorator extends @decorator, Expr {
override ControlFlowNode getFirstControlFlowNode() {
result = getExpression().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "Decorator" }
}
/**
@@ -2687,6 +2749,8 @@ class FunctionBindExpr extends @bind_expr, Expr {
or
not exists(getObject()) and result = getCallee().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "FunctionBindExpr" }
}
/**
@@ -2711,6 +2775,8 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
override Module getEnclosingModule() { result = getTopLevel() }
override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) }
override string getAPrimaryQlClass() { result = "DynamicImportExpr" }
}
/** A literal path expression appearing in a dynamic import. */
@@ -2734,6 +2800,8 @@ private class LiteralDynamicImportPath extends PathExpr, ConstantString {
*/
class OptionalUse extends Expr, @optionalchainable {
OptionalUse() { isOptionalChaining(this) }
override string getAPrimaryQlClass() { result = "OptionalUse" }
}
private class ChainElem extends Expr, @optionalchainable {
@@ -2775,4 +2843,6 @@ class OptionalChainRoot extends ChainElem {
*/
class ImportMetaExpr extends @import_meta_expr, Expr {
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "ImportMetaExpr" }
}

View File

@@ -80,6 +80,8 @@ module HTML {
}
override string toString() { result = "<" + getName() + ">...</>" }
override string getAPrimaryQlClass() { result = "HTML::Element" }
}
/**
@@ -124,6 +126,34 @@ module HTML {
string getValue() { xmlAttrs(this, _, _, result, _, _) }
override string toString() { result = getName() + "=" + getValue() }
/**
* Gets the inline script of this attribute, if any.
*/
CodeInAttribute getCodeInAttribute() {
exists(
string f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, int sl2, int sc2,
int el2, int ec2
|
l1 = getLocation() and
l2 = result.getLocation() and
l1.hasLocationInfo(f, sl1, sc1, el1, ec1) and
l2.hasLocationInfo(f, sl2, sc2, el2, ec2)
|
(
sl1 = sl2 and sc1 < sc2
or
sl1 < sl2
) and
(
el1 = el2 and ec1 > ec2
or
el1 > el2
)
)
}
override string getAPrimaryQlClass() { result = "HTML::Attribute" }
}
/**
@@ -227,6 +257,8 @@ module HTML {
result = getInlineScript() or
result = resolveSource()
}
override string getAPrimaryQlClass() { result = "HTML::ScriptElement" }
}
/**

View File

@@ -40,6 +40,8 @@ class JSONValue extends @json_value, Locatable {
result = loc.getFile()
)
}
override string getAPrimaryQlClass() { result = "JSONValue" }
}
/**
@@ -72,7 +74,9 @@ abstract class JSONPrimitiveValue extends JSONValue {
* null
* ```
*/
class JSONNull extends @json_null, JSONPrimitiveValue { }
class JSONNull extends @json_null, JSONPrimitiveValue {
override string getAPrimaryQlClass() { result = "JSONNull" }
}
/**
* A JSON-encoded Boolean value.
@@ -84,7 +88,9 @@ class JSONNull extends @json_null, JSONPrimitiveValue { }
* false
* ```
*/
class JSONBoolean extends @json_boolean, JSONPrimitiveValue { }
class JSONBoolean extends @json_boolean, JSONPrimitiveValue {
override string getAPrimaryQlClass() { result = "JSONBoolean" }
}
/**
* A JSON-encoded number.
@@ -96,7 +102,9 @@ class JSONBoolean extends @json_boolean, JSONPrimitiveValue { }
* 1.0
* ```
*/
class JSONNumber extends @json_number, JSONPrimitiveValue { }
class JSONNumber extends @json_number, JSONPrimitiveValue {
override string getAPrimaryQlClass() { result = "JSONNumber" }
}
/**
* A JSON-encoded string value.
@@ -107,7 +115,9 @@ class JSONNumber extends @json_number, JSONPrimitiveValue { }
* "a string"
* ```
*/
class JSONString extends @json_string, JSONPrimitiveValue { }
class JSONString extends @json_string, JSONPrimitiveValue {
override string getAPrimaryQlClass() { result = "JSONString" }
}
/**
* A JSON-encoded array.
@@ -124,6 +134,8 @@ class JSONArray extends @json_array, JSONValue {
/** Gets the string value of the `i`th element of this array. */
string getElementStringValue(int i) { result = getElementValue(i).(JSONString).getValue() }
override string getAPrimaryQlClass() { result = "JSONArray" }
}
/**
@@ -141,6 +153,8 @@ class JSONObject extends @json_object, JSONValue {
/** Gets the string value of property `name` of this object. */
string getPropStringValue(string name) { result = getPropValue(name).(JSONString).getValue() }
override string getAPrimaryQlClass() { result = "JSONObject" }
}
/**

View File

@@ -26,6 +26,8 @@ class JSXNode extends Expr, @jsx_element {
* Gets the parent JSX element or fragment of this element.
*/
JSXNode getJsxParent() { this = result.getABodyElement() }
override string getAPrimaryQlClass() { result = "JSXNode" }
}
/**
@@ -61,6 +63,8 @@ class JSXElement extends JSXNode {
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "JSXElement" }
}
/**
@@ -80,6 +84,8 @@ class JSXFragment extends JSXNode {
or
not exists(getABodyElement()) and result = this
}
override string getAPrimaryQlClass() { result = "JSXFragment" }
}
/**
@@ -124,6 +130,8 @@ class JSXAttribute extends ASTNode, @jsx_attribute {
}
override string toString() { properties(this, _, _, _, result) }
override string getAPrimaryQlClass() { result = "JSXAttribute" }
}
/**
@@ -163,6 +171,8 @@ class JSXQualifiedName extends Expr, @jsx_qualified_name {
override ControlFlowNode getFirstControlFlowNode() {
result = getNamespace().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "JSXQualifiedName" }
}
/**
@@ -214,7 +224,9 @@ class JSXName extends Expr {
* { /* TBD *&#47; }
* </pre>
*/
class JSXEmptyExpr extends Expr, @jsx_empty_expr { }
class JSXEmptyExpr extends Expr, @jsx_empty_expr {
override string getAPrimaryQlClass() { result = "JSXEmptyExpr" }
}
/**
* A legacy `@jsx` pragma.

View File

@@ -131,6 +131,11 @@ class Locatable extends @locatable {
// to be overridden by subclasses
none()
}
/**
* Gets the primary QL class for the Locatable.
*/
string getAPrimaryQlClass() { result = "???" }
}
/**

View File

@@ -0,0 +1,714 @@
/**
* Provides queries to pretty-print a JavaScript AST as a graph.
*
* By default, this will print the AST for all elements in the database. To change this behavior,
* extend `PrintAstConfiguration` and override `shouldPrint` to hold for only the elements
* you wish to view the AST for.
*/
import javascript
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
/**
* The query can extend this class to control which elements are printed.
*/
class PrintAstConfiguration extends TPrintAstConfiguration {
/**
* Gets a textual representation of this `PrintAstConfiguration`.
*/
string toString() { result = "PrintAstConfiguration" }
/**
* Controls whether the `Element` should be considered for AST printing.
* By default it checks whether the `Element` `e` belongs to `Location` `l`.
*/
predicate shouldPrint(Locatable e, Location l) { l = e.getLocation() }
}
private predicate shouldPrint(Locatable e, Location l) {
exists(PrintAstConfiguration config | config.shouldPrint(e, l))
}
/** Holds if the given element does not need to be rendered in the AST, due to being compiler-generated or being a `TopLevel`. */
private predicate isNotNeeded(Locatable el) {
exists(ClassDefinition c, ConstructorDeclaration constructor |
constructor = c.getConstructor() and
constructor.isSynthetic() and
el = constructor
)
or
el instanceof TopLevel and
el.getLocation().getStartLine() = 0 and
el.getLocation().getStartColumn() = 0
or
exists(ASTNode parent | isNotNeeded(parent) and not parent instanceof TopLevel |
el = parent.getAChild()
)
or
// relaxing aggresive type inference.
none()
}
/**
* Retrieves the canonical QL class(es) for entity `el`
*/
private string getQlClass(Locatable el) {
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
// Alternative implementation -- do not delete. It is useful for QL class discovery.
// not el.getAPrimaryQlClass() = "???" and result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] " or el.getAPrimaryQlClass() = "???" and result = "??[" + concat(el.getAQlClass(), ",") + "] "
}
/**
* Printed nodes for different file types.
*/
private newtype TPrintAstNode =
// JavaScript / TypeScript
TElementNode(ASTNode el) { shouldPrint(el, _) and not isNotNeeded(el) } or
TParametersNode(Function f) { shouldPrint(f, _) and not isNotNeeded(f) } or
TTypeParametersNode(TypeParameterized f) { shouldPrint(f, _) and not isNotNeeded(f) } or
TJSXAttributesNode(JSXElement n) { shouldPrint(n, _) and not isNotNeeded(n) } or
TJSXBodyElementsNode(JSXNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
TInvokeArgumentsNode(InvokeExpr n) { shouldPrint(n, _) and not isNotNeeded(n) } or
TInvokeTypeArgumentsNode(InvokeExpr invk) { shouldPrint(invk, _) and not isNotNeeded(invk) } or
// JSON
TJSONNode(JSONValue value) { shouldPrint(value, _) and not isNotNeeded(value) } or
// YAML
TYAMLNode(YAMLNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
TYAMLMappingNode(YAMLMapping mapping, int i) {
shouldPrint(mapping, _) and not isNotNeeded(mapping) and exists(mapping.getKeyNode(i))
} or
// HTML
THTMLElementNode(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
THTMLAttributesNodes(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
THTMLAttributeNode(HTML::Attribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
THTMLScript(Script script) { shouldPrint(script, _) and not isNotNeeded(script) } or
THTMLCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) }
/**
* A node in the output tree.
*/
class PrintAstNode extends TPrintAstNode {
/**
* Gets a textual representation of this node in the PrintAst output tree.
*/
string toString() { none() }
/**
* Gets the child node at index `childIndex`. Child indices must be unique,
* but need not be contiguous.
*/
PrintAstNode getChild(int childIndex) { none() }
/**
* Gets a child of this node.
*/
final PrintAstNode getAChild() { result = getChild(_) }
/**
* Gets the parent of this node, if any.
*/
final PrintAstNode getParent() { result.getAChild() = this }
/**
* Gets the location of this node in the source code.
*/
Location getLocation() { none() }
/**
* Gets the value of the property of this node, where the name of the property
* is `key`.
*/
string getProperty(string key) {
key = "semmle.label" and
result = toString()
}
/**
* Gets the label for the edge from this node to the specified child. By
* default, this is just the index of the child, but subclasses can override
* this.
*/
string getChildEdgeLabel(int childIndex) {
exists(getChild(childIndex)) and
result = childIndex.toString()
}
}
/** A top-level AST node. */
class TopLevelPrintAstNode extends PrintAstNode {
TopLevelPrintAstNode() { not exists(this.getParent()) }
private int getOrder() {
this =
rank[result](TopLevelPrintAstNode n, Location l |
l = n.getLocation()
|
n
order by
l.getFile().getRelativePath(), l.getStartLine(), l.getStartColumn(), l.getEndLine(),
l.getEndColumn()
)
}
override string getProperty(string key) {
result = super.getProperty(key)
or
key = "semmle.order" and
result = this.getOrder().toString()
}
}
/**
* Classes for printing JavaScript AST.
*/
private module PrintJavaScript {
/**
* A print node representing an `ASTNode`.
*
* Provides a default implemention that works for some (but not all) ASTNode's.
* More specific subclasses can override this class to get more specific behavior.
*
* The more specific subclasses are mostly used aggregate the children of the `ASTNode`.
* For example by aggregating all the parameters of a function under a single child node.
*/
class ElementNode extends PrintAstNode, TElementNode {
ASTNode element;
ElementNode() {
this = TElementNode(element) and
not element instanceof Script and // Handled in module `PrintHTML`
not element instanceof CodeInAttribute // Handled in module `PrintHTML`
}
override string toString() { result = getQlClass(element) + element.toString() }
override Location getLocation() { result = element.getLocation() }
/**
* Gets the `ASTNode` represented by this node.
*/
final ASTNode getElement() { result = element }
override PrintAstNode getChild(int childIndex) {
exists(ASTNode el | result.(ElementNode).getElement() = el |
el = this.getChildNode(childIndex)
)
}
/**
* Gets the `i`th child of `element`.
* Can be overriden in subclasses to get more specific behavior for `getChild()`.
*/
ASTNode getChildNode(int childIndex) { result = element.getChild(childIndex) }
}
/**
* A print node for function invocations.
*
* The children of this node are split into 3.
* 1: The callee.
* 2: An aggregate node for all the arguments.
* 3: An aggregate node for all the type argument.
*/
class InvokeNode extends ElementNode {
override InvokeExpr element;
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(ElementNode).getElement() = element.getCallee()
or
childIndex = 1 and
exists(element.getAnArgument()) and
result.(InvokeArgumentsNode).getInvokeExpr() = element
or
childIndex = 2 and
exists(element.getATypeArgument()) and
result.(InvokeTypeArgumentsNode).getInvokeExpr() = element
}
}
/**
* An aggregate node representing all the arguments for an function invocation.
*/
class InvokeArgumentsNode extends PrintAstNode, TInvokeArgumentsNode {
InvokeExpr invk;
InvokeArgumentsNode() { this = TInvokeArgumentsNode(invk) and exists(invk.getAnArgument()) }
override string toString() { result = "(Arguments)" }
/**
* Gets the `InvokeExpr` for which this node represents the arguments.
*/
InvokeExpr getInvokeExpr() { result = invk }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = invk.getArgument(childIndex)
}
override Location getLocation() { result = invk.getLocation() }
}
/**
* An aggregate node representing all the type-arguments for an function invocation.
*/
class InvokeTypeArgumentsNode extends PrintAstNode, TInvokeTypeArgumentsNode {
InvokeExpr invk;
InvokeTypeArgumentsNode() {
this = TInvokeTypeArgumentsNode(invk) and exists(invk.getATypeArgument())
}
override string toString() { result = "(TypeArguments)" }
/**
* Gets the `InvokeExpr` for which this node represents the type-arguments.
*/
InvokeExpr getInvokeExpr() { result = invk }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = invk.getTypeArgument(childIndex)
}
override Location getLocation() { result = invk.getLocation() }
}
/**
* A print node for JSX nodes.
*
* The children of this node are split into 3.
* 1: The name of the JSX node (for example `Name` in `<Name href={foo} />`).
* 2: An aggregate node for all the attributes (for example `href={foo}` in `<Name href={foo} />`).
* 3: An aggregate node for all the body element (for example `foo` in `<span>foo</span>`).
*/
class JSXNodeNode extends ElementNode {
override JSXNode element;
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(ElementNode).getElement() = element.(JSXElement).getNameExpr()
or
childIndex = 1 and
exists(element.getABodyElement()) and
result.(JSXBodyElementsNode).getJSXNode() = element
or
childIndex = 2 and
exists(element.(JSXElement).getAttribute(_)) and
result.(JSXAttributesNode).getJSXElement() = element
}
}
/**
* An aggregate node representing all the attributes in a `JSXNode`.
*/
class JSXAttributesNode extends PrintAstNode, TJSXAttributesNode {
JSXElement n;
JSXAttributesNode() { this = TJSXAttributesNode(n) and exists(n.getAttribute(_)) }
override string toString() { result = "(Attributes)" }
/**
* Gets the `JSXElement` for which this node represents the attributes.
*/
JSXElement getJSXElement() { result = n }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = n.getAttribute(childIndex)
}
override Location getLocation() { result = n.getLocation() }
}
/**
* An aggregate node representing all the body elements in a `JSXNode`.
*/
class JSXBodyElementsNode extends PrintAstNode, TJSXBodyElementsNode {
JSXNode n;
JSXBodyElementsNode() { this = TJSXBodyElementsNode(n) and exists(n.getBodyElement(_)) }
override string toString() { result = "(Body)" }
/**
* Gets the `JSXNode` for which this node represents the body elements.
*/
JSXNode getJSXNode() { result = n }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = n.getBodyElement(childIndex)
}
override Location getLocation() { result = n.getLocation() }
}
/**
* A node representing any `ASTNode` that has type-parameters.
*
* The first child of this node is an aggregate node representing all the type-parameters.
*/
class TypeParameterizedNode extends ElementNode {
override TypeParameterized element;
override PrintAstNode getChild(int childIndex) {
childIndex = -100 and result.(TypeParametersNode).getTypeParameterized() = element
or
result = super.getChild(childIndex) and
not result.(ElementNode).getElement() = element.getATypeParameter()
}
}
/**
* A `PrintAstNode` for functions.
*
* The children of this node is split into 6:
* - The identifier (name) of the function.
* - An aggregate node for all the parameters of the function.
* - An aggregate node for all the type parameters of the function.
* - The `this` type annotation.
* - The return type annotation.
* - The body
*/
class FunctionNode extends TypeParameterizedNode {
override Function element;
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(ElementNode).getElement() = element.getIdentifier()
or
childIndex = 1 and
result.(ParametersNode).getFunction() = element and
exists(element.getAParameter())
or
childIndex = 2 and
result.(TypeParametersNode).getTypeParameterized() = element and
exists(element.getATypeParameter())
or
childIndex = 3 and result.(ElementNode).getElement() = element.getThisTypeAnnotation()
or
childIndex = 4 and result.(ElementNode).getElement() = element.getReturnTypeAnnotation()
or
childIndex = 5 and result.(ElementNode).getElement() = element.getBody()
}
}
/**
* A `PrintAstNode` for parameters.
*
* This node puts the type-annotation and default value of a parameter as children of the parameter itself.
* Instead of the default behavior (from `ElementNode`) where they would be children of the function.
*/
class ParameterNode extends ElementNode {
override Parameter element;
override ASTNode getChildNode(int childIndex) {
childIndex = 0 and result = element.getTypeAnnotation()
or
childIndex = 1 and result = element.getDefault()
}
}
/**
* An aggregate node representing all the parameters in a function.
*/
class ParametersNode extends PrintAstNode, TParametersNode {
Function f;
ParametersNode() { this = TParametersNode(f) and exists(f.getAParameter()) }
override string toString() { result = "(Parameters)" }
/**
* Gets the `Function` for which this node represents the parameters.
*/
Function getFunction() { result = f }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = f.getParameter(childIndex)
}
override Location getLocation() { result = f.getLocation() }
}
/**
* An aggregate node representing all the type parameters in a function.
*/
class TypeParametersNode extends PrintAstNode, TTypeParametersNode {
TypeParameterized f;
TypeParametersNode() { this = TTypeParametersNode(f) and exists(f.getATypeParameter()) }
override string toString() { result = "(TypeParameters)" }
/**
* Gets the `Function` for which this node represents the type-parameters.
*/
TypeParameterized getTypeParameterized() { result = f }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() = f.getTypeParameter(childIndex)
}
override Location getLocation() { result = f.getLocation() }
}
}
/**
* Classes for printing JSON AST.
*/
private module PrintJSON {
/**
* A print node representing a JSON value in a .json file.
*/
class JSONNode extends PrintAstNode, TJSONNode {
JSONValue value;
JSONNode() { this = TJSONNode(value) }
override string toString() { result = getQlClass(value) + value.toString() }
override Location getLocation() { result = value.getLocation() }
/**
* Gets the `JSONValue` represented by this node.
*/
final JSONValue getValue() { result = value }
override PrintAstNode getChild(int childIndex) {
exists(JSONValue child | result.(JSONNode).getValue() = child |
child = value.getChild(childIndex)
)
}
}
}
/**
* Classes for printing YAML AST.
*/
module PrintYAML {
/**
* A print node representing a YAML value in a .yml file.
*/
class YAMLNodeNode extends PrintAstNode, TYAMLNode {
YAMLNode node;
YAMLNodeNode() { this = TYAMLNode(node) }
override string toString() { result = getQlClass(node) + node.toString() }
override Location getLocation() { result = node.getLocation() }
/**
* Gets the `YAMLNode` represented by this node.
*/
final YAMLNode getValue() { result = node }
override PrintAstNode getChild(int childIndex) {
exists(YAMLNode child | result.(YAMLNodeNode).getValue() = child |
child = node.getChildNode(childIndex)
)
}
}
/**
* A print node representing a `YAMLMapping`.
*
* Each child of this node aggregates the key and value of a mapping.
*/
class YAMLMappingNode extends YAMLNodeNode {
override YAMLMapping node;
override PrintAstNode getChild(int childIndex) {
exists(YAMLMappingMapNode map | map = result | map.maps(node, childIndex))
}
}
/**
* A print node representing the `i`th mapping in `mapping`.
*/
class YAMLMappingMapNode extends PrintAstNode, TYAMLMappingNode {
YAMLMapping mapping;
int i;
YAMLMappingMapNode() { this = TYAMLMappingNode(mapping, i) }
override string toString() { result = "(Mapping " + i + ")" }
/**
* Holds if this print node represents the `index`th mapping of `m`.
*/
predicate maps(YAMLMapping m, int index) {
m = mapping and
index = i
}
override Location getLocation() { result = mapping.getKeyNode(i).getLocation() }
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(YAMLNodeNode).getValue() = mapping.getKeyNode(i)
or
childIndex = 1 and result.(YAMLNodeNode).getValue() = mapping.getValueNode(i)
}
}
}
/**
* Classes for printing HTML AST.
*/
module PrintHTML {
/**
* A print node representing an HTML node in a .html file.
*/
class HTMLElementNode extends PrintAstNode, THTMLElementNode {
HTML::Element element;
HTMLElementNode() { this = THTMLElementNode(element) }
override string toString() { result = getQlClass(element) + element.toString() }
override Location getLocation() { result = element.getLocation() }
/**
* Gets the `HTML::Element` represented by this node.
*/
final HTML::Element getElement() { result = element }
override PrintAstNode getChild(int childIndex) {
childIndex = -1 and result.(HTMLAttributesNodes).getElement() = element
or
exists(HTML::Element child | result.(HTMLElementNode).getElement() = child |
child = element.(HTML::Element).getChild(childIndex)
)
}
}
/**
* A print node representing an HTML node in a .html file.
*/
class HTMLScriptElementNode extends HTMLElementNode {
override HTML::ScriptElement element;
override PrintAstNode getChild(int childIndex) {
childIndex = -200 and result.(HTMLScript).getScript() = element.getScript()
or
result = super.getChild(childIndex)
}
}
/**
* A print node representing the code inside a `<script>` element.
*/
class HTMLScript extends PrintAstNode, THTMLScript {
Script script;
HTMLScript() {
this = THTMLScript(script) and
any(HTMLScriptElementNode se).getElement().(HTML::ScriptElement).getScript() = script
}
override string toString() { result = "(Script)" }
override Location getLocation() { result = script.getLocation() }
/**
* Gets the `Script` for which this node represents code.
*/
Script getScript() { result = script }
override PrintAstNode getChild(int childIndex) {
result.(PrintJavaScript::ElementNode).getElement() = script.getChild(childIndex)
}
}
/**
* A print node representing the code inside a `<script>` element.
*/
class HTMLCodeInAttr extends PrintAstNode, THTMLCodeInAttr {
CodeInAttribute attr;
HTMLCodeInAttr() {
this = THTMLCodeInAttr(attr) and
any(HTMLAttributeNode an).getAttribute().getCodeInAttribute() = attr
}
override string toString() { result = "(Script)" }
override Location getLocation() { result = attr.getLocation() }
/**
* Gets the `CodeInAttribute` for which this node represents code.
*/
CodeInAttribute getCode() { result = attr }
override PrintAstNode getChild(int childIndex) {
result.(PrintJavaScript::ElementNode).getElement() = attr.getChild(childIndex)
}
}
/**
* An aggregate node representing all the attributes of an HTMLElement.
*/
class HTMLAttributesNodes extends PrintAstNode, THTMLAttributesNodes {
HTML::Element element;
HTMLAttributesNodes() {
this = THTMLAttributesNodes(element) and exists(element.getAttribute(_))
}
override string toString() { result = "(Attributes)" }
/**
* Gets the `HTMLElement` for which this node represents the attributes.
*/
HTML::Element getElement() { result = element }
override PrintAstNode getChild(int childIndex) {
result.(HTMLAttributeNode).getAttribute() = element.getAttribute(childIndex)
}
override Location getLocation() { result = element.getLocation() }
}
/**
* A print node representing an HTML attribute in a .html file.
*/
class HTMLAttributeNode extends PrintAstNode, THTMLAttributeNode {
HTML::Attribute attr;
HTMLAttributeNode() { this = THTMLAttributeNode(attr) }
override string toString() { result = getQlClass(attr) + attr.toString() }
override Location getLocation() { result = attr.getLocation() }
/**
* Gets the `HTMLAttribute` represented by this node.
*/
final HTML::Attribute getAttribute() { result = attr }
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(HTMLCodeInAttr).getCode() = attr.getCodeInAttribute()
}
}
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintAstNode node, string key, string value) { value = node.getProperty(key) }
/**
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
* given `value`.
*/
query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
exists(int childIndex |
target = source.getChild(childIndex) and
(
key = "semmle.label" and value = source.getChildEdgeLabel(childIndex)
or
key = "semmle.order" and value = childIndex.toString()
)
)
}
/** Holds if property `key` of the graph has the given `value`. */
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "tree"
}

View File

@@ -128,7 +128,9 @@ class LoopStmt extends TLoopStmt, ControlStmt {
* ;
* ```
*/
class EmptyStmt extends @empty_stmt, Stmt { }
class EmptyStmt extends @empty_stmt, Stmt {
override string getAPrimaryQlClass() { result = "EmptyStmt" }
}
/**
* A block of statements.
@@ -153,6 +155,8 @@ class BlockStmt extends @block_stmt, Stmt {
/** Holds if this block is a function body. */
predicate isFunctionBody() { this.getParent() instanceof Function }
override string getAPrimaryQlClass() { result = "BlockStmt" }
}
/**
@@ -192,6 +196,8 @@ class ExprStmt extends @expr_stmt, Stmt {
f = assgn.getRhs()
)
}
override string getAPrimaryQlClass() { result = "ExprStmt" }
}
/**
@@ -432,6 +438,8 @@ class IfStmt extends @if_stmt, ControlStmt {
/** Holds if this `if` statement is an `else if` of an outer `if` statement. */
predicate isElseIf() { exists(IfStmt outer | outer.getElse() = this) }
override string getAPrimaryQlClass() { result = "IfStmt" }
}
/**
@@ -455,6 +463,8 @@ class LabeledStmt extends @labeled_stmt, Stmt {
/** Gets the labeled statement of this statement. */
Stmt getStmt() { result = getChildStmt(1) }
override string getAPrimaryQlClass() { result = "LabeledStmt" }
}
private class TJumpStmt = TBreakOrContinueStmt or @return_stmt or @throw_stmt;
@@ -524,7 +534,9 @@ class BreakOrContinueStmt extends TBreakOrContinueStmt, JumpStmt {
* break;
* ```
*/
class BreakStmt extends @break_stmt, BreakOrContinueStmt { }
class BreakStmt extends @break_stmt, BreakOrContinueStmt {
override string getAPrimaryQlClass() { result = "BreakStmt" }
}
/**
* A `continue` statement.
@@ -536,7 +548,9 @@ class BreakStmt extends @break_stmt, BreakOrContinueStmt { }
* continue;
* ```
*/
class ContinueStmt extends @continue_stmt, BreakOrContinueStmt { }
class ContinueStmt extends @continue_stmt, BreakOrContinueStmt {
override string getAPrimaryQlClass() { result = "ContinueStmt" }
}
/**
* A `with` statement.
@@ -570,6 +584,8 @@ class WithStmt extends @with_stmt, ControlStmt {
}
override Stmt getAControlledStmt() { result = getBody() }
override string getAPrimaryQlClass() { result = "WithStmt" }
}
/**
@@ -604,6 +620,8 @@ class SwitchStmt extends @switch_stmt, ControlStmt {
int getNumCase() { result = count(getACase()) }
override Case getAControlledStmt() { result = getACase() }
override string getAPrimaryQlClass() { result = "SwitchStmt" }
}
/**
@@ -628,6 +646,8 @@ class ReturnStmt extends @return_stmt, JumpStmt {
}
override predicate isSubjectToSemicolonInsertion() { any() }
override string getAPrimaryQlClass() { result = "ReturnStmt" }
}
/**
@@ -661,6 +681,8 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
}
override predicate isSubjectToSemicolonInsertion() { any() }
override string getAPrimaryQlClass() { result = "ThrowStmt" }
}
/**
@@ -710,6 +732,8 @@ class TryStmt extends @try_stmt, ControlStmt {
/** Gets the `finally` block of this `try` statement, if any. */
BlockStmt getFinally() { result = getChildStmt(-1) }
override string getAPrimaryQlClass() { result = "TryStmt" }
}
/**
@@ -730,6 +754,8 @@ class WhileStmt extends @while_stmt, LoopStmt {
override Expr getTest() { result = getExpr() }
override Stmt getBody() { result = getChildStmt(1) }
override string getAPrimaryQlClass() { result = "WhileStmt" }
}
/**
@@ -752,6 +778,8 @@ class DoWhileStmt extends @do_while_stmt, LoopStmt {
override Stmt getBody() { result = getChildStmt(0) }
override predicate isSubjectToSemicolonInsertion() { any() }
override string getAPrimaryQlClass() { result = "DoWhileStmt" }
}
/**
@@ -795,6 +823,8 @@ class ForStmt extends @for_stmt, LoopStmt {
Expr getUpdate() { result = getChildExpr(2) }
override Stmt getBody() { result = getChildStmt(3) }
override string getAPrimaryQlClass() { result = "ForStmt" }
}
/**
@@ -878,7 +908,9 @@ class EnhancedForLoop extends TEnhancedForLoop, LoopStmt {
* }
* ```
*/
class ForInStmt extends @for_in_stmt, EnhancedForLoop { }
class ForInStmt extends @for_in_stmt, EnhancedForLoop {
override string getAPrimaryQlClass() { result = "ForInStmt" }
}
/**
* A `for`-`of` loop.
@@ -896,6 +928,8 @@ class ForOfStmt extends @for_of_stmt, EnhancedForLoop {
* Holds if this is a `for-await-of` statement.
*/
predicate isAwait() { is_for_await_of(this) }
override string getAPrimaryQlClass() { result = "ForOfStmt" }
}
/**
@@ -909,7 +943,9 @@ class ForOfStmt extends @for_of_stmt, EnhancedForLoop {
* }
* ```
*/
class ForEachStmt extends @for_each_stmt, EnhancedForLoop { }
class ForEachStmt extends @for_each_stmt, EnhancedForLoop {
override string getAPrimaryQlClass() { result = "ForEachStmt" }
}
/**
* A `debugger` statement.
@@ -922,6 +958,8 @@ class ForEachStmt extends @for_each_stmt, EnhancedForLoop { }
*/
class DebuggerStmt extends @debugger_stmt, Stmt {
override predicate isSubjectToSemicolonInsertion() { any() }
override string getAPrimaryQlClass() { result = "DebuggerStmt" }
}
/**
@@ -937,6 +975,8 @@ class DebuggerStmt extends @debugger_stmt, Stmt {
*/
class FunctionDeclStmt extends @function_decl_stmt, Stmt, Function {
override Stmt getEnclosingStmt() { result = this }
override string getAPrimaryQlClass() { result = "FunctionDeclStmt" }
}
/**
@@ -962,6 +1002,8 @@ class DeclStmt extends @decl_stmt, Stmt {
// exclude variable declarations in the init part of for/for-in/for-of loops
not exists(LoopStmt for | this = for.getAChildStmt() and this != for.getBody())
}
override string getAPrimaryQlClass() { result = "DeclStmt" }
}
/**
@@ -1043,6 +1085,8 @@ class Case extends @case, Stmt {
/** Gets the `switch` statement to which this clause belongs. */
SwitchStmt getSwitch() { result = getParent() }
override string getAPrimaryQlClass() { result = "Case" }
}
/**
@@ -1067,4 +1111,6 @@ class CatchClause extends @catch_clause, ControlStmt, Parameterized {
/** Gets the scope induced by this `catch` clause. */
CatchScope getScope() { result.getCatchClause() = this }
override string getAPrimaryQlClass() { result = "CatchClause" }
}

View File

@@ -28,6 +28,8 @@ class TaggedTemplateExpr extends Expr, @tagged_template_expr {
int getNumTypeArgument() { result = count(getATypeArgument()) }
override predicate isImpure() { any() }
override string getAPrimaryQlClass() { result = "TaggedTemplateExpr" }
}
/**
@@ -57,6 +59,8 @@ class TemplateLiteral extends Expr, @template_literal {
int getNumElement() { result = count(getAnElement()) }
override predicate isImpure() { getAnElement().isImpure() }
override string getAPrimaryQlClass() { result = "TemplateLiteral" }
}
/**
@@ -94,4 +98,6 @@ class TemplateElement extends Expr, @template_element {
string getRawValue() { literals(_, result, this) }
override predicate isImpure() { none() }
override string getAPrimaryQlClass() { result = "TemplateElement" }
}

View File

@@ -88,6 +88,8 @@ class NamespaceDeclaration extends NamespaceDefinition, StmtContainer, @namespac
override ControlFlowNode getFirstControlFlowNode() {
if has_declare_keyword(this) then result = this else result = getIdentifier()
}
override string getAPrimaryQlClass() { result = "NamespaceDeclaration" }
}
/**
@@ -122,6 +124,8 @@ class TypeDefinition extends ASTNode, @type_definition {
* Gets the type defined by this declaration.
*/
Type getType() { ast_node_type(getIdentifier(), result) }
override string getAPrimaryQlClass() { result = "TypeDefinition" }
}
/**
@@ -158,6 +162,8 @@ class ExternalModuleDeclaration extends Stmt, StmtContainer, @external_module_de
int getNumStmt() { result = count(getAStmt()) }
override StmtContainer getEnclosingContainer() { result = this.getContainer() }
override string getAPrimaryQlClass() { result = "ExternalModuleDeclaration" }
}
/**
@@ -177,6 +183,8 @@ class GlobalAugmentationDeclaration extends Stmt, StmtContainer, @global_augment
int getNumStmt() { result = count(getAStmt()) }
override StmtContainer getEnclosingContainer() { result = this.getContainer() }
override string getAPrimaryQlClass() { result = "GlobalAugmentationDeclaration" }
}
/** A TypeScript "import-equals" declaration. */
@@ -195,6 +203,8 @@ class ImportEqualsDeclaration extends Stmt, @import_equals_declaration {
Expr getImportedEntity() { result = getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() { result = getIdentifier() }
override string getAPrimaryQlClass() { result = "ImportEqualsDeclaration" }
}
/**
@@ -235,6 +245,8 @@ private class LiteralExternalModulePath extends PathExpr, ConstantString {
class ExportAssignDeclaration extends Stmt, @export_assign_declaration {
/** Gets the expression exported by this declaration. */
Expr getExpression() { result = getChildExpr(0) }
override string getAPrimaryQlClass() { result = "ExportAssignDeclaration" }
}
/** A TypeScript export of form `export as namespace X` where `X` is an identifier. */
@@ -243,6 +255,8 @@ class ExportAsNamespaceDeclaration extends Stmt, @export_as_namespace_declaratio
* Gets the `X` in `export as namespace X`.
*/
Identifier getIdentifier() { result = getChildExpr(0) }
override string getAPrimaryQlClass() { result = "ExportAsNamespaceDeclaration" }
}
/**
@@ -267,6 +281,8 @@ class TypeAliasDeclaration extends @type_alias_declaration, TypeParameterized, S
* Gets the canonical name of the type being defined.
*/
TypeName getTypeName() { result.getADefinition() = this }
override string getAPrimaryQlClass() { result = "TypeAliasDeclaration" }
}
/**
@@ -274,6 +290,8 @@ class TypeAliasDeclaration extends @type_alias_declaration, TypeParameterized, S
*/
class InterfaceDefinition extends @interface_definition, ClassOrInterface {
override predicate isAbstract() { any() }
override string getAPrimaryQlClass() { result = "InterfaceDefinition" }
}
/** A TypeScript interface declaration. */
@@ -301,6 +319,8 @@ class InterfaceDeclaration extends Stmt, InterfaceDefinition, @interface_declara
* Gets any type from the `extends` clause of this interface.
*/
override TypeExpr getASuperInterface() { result = InterfaceDefinition.super.getASuperInterface() }
override string getAPrimaryQlClass() { result = "InterfaceDefinition" }
}
/** An inline TypeScript interface type, such as `{x: number; y: number}`. */
@@ -308,6 +328,8 @@ class InterfaceTypeExpr extends TypeExpr, InterfaceDefinition, @interface_typeex
override Identifier getIdentifier() { none() }
override string describe() { result = "anonymous interface" }
override string getAPrimaryQlClass() { result = "InterfaceTypeExpr" }
}
/**
@@ -341,6 +363,8 @@ class FunctionTypeExpr extends TypeExpr, @function_typeexpr {
/** Gets the return type of this function type, if any. */
TypeExpr getReturnTypeAnnotation() { result = getFunction().getReturnTypeAnnotation() }
override string getAPrimaryQlClass() { result = "FunctionTypeExpr" }
}
/** A constructor type, such as `new (x: string) => Object`. */
@@ -596,6 +620,8 @@ private class KeywordTypeExpr extends @keyword_typeexpr, TypeExpr {
override predicate isBigInt() { getName() = "bigint" }
override predicate isConstKeyword() { getName() = "const" }
override string getAPrimaryQlClass() { result = "KeywordTypeExpr" }
}
/**
@@ -704,6 +730,8 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef {
.getAMemberAccess(exportedName)
)
}
override string getAPrimaryQlClass() { result = "TypeAccess" }
}
/**
@@ -742,6 +770,8 @@ class LocalTypeAccess extends @local_type_access, TypeAccess, Identifier, Lexica
* a local type name as it is declared in `lib.d.ts`.
*/
LocalTypeName getLocalTypeName() { result.getAnAccess() = this }
override string getAPrimaryQlClass() { result = "LocalTypeAccess" }
}
/**
@@ -786,6 +816,8 @@ class GenericTypeExpr extends @generic_typeexpr, TypeExpr {
override predicate hasQualifiedName(string moduleName, string exportedName) {
getTypeAccess().hasQualifiedName(moduleName, exportedName)
}
override string getAPrimaryQlClass() { result = "GenericTypeExpr" }
}
/**
@@ -802,6 +834,8 @@ class LiteralTypeExpr extends @literal_typeexpr, TypeExpr {
* string literals.
*/
string getRawValue() { literals(_, result, this) }
override string getAPrimaryQlClass() { result = "LiteralTypeExpr" }
}
/** A string literal used as a type. */
@@ -842,6 +876,8 @@ class BigIntLiteralTypeExpr extends @bigint_literal_typeexpr, LiteralTypeExpr {
class ArrayTypeExpr extends @array_typeexpr, TypeExpr {
/** Gets the type of the array elements. */
TypeExpr getElementType() { result = getChildTypeExpr(0) }
override string getAPrimaryQlClass() { result = "ArrayTypeExpr" }
}
/**
@@ -858,6 +894,8 @@ class UnionTypeExpr extends @union_typeexpr, TypeExpr {
int getNumElementType() { result = count(getAnElementType()) }
override TypeExpr getAnUnderlyingType() { result = getAnElementType().getAnUnderlyingType() }
override string getAPrimaryQlClass() { result = "UnionTypeExpr" }
}
/**
@@ -869,6 +907,8 @@ class IndexedAccessTypeExpr extends @indexed_access_typeexpr, TypeExpr {
/** Gets the type `K` in `T[K]`, denoting the property names to extract from the object type. */
TypeExpr getIndexType() { result = getChildTypeExpr(1) }
override string getAPrimaryQlClass() { result = "IndexedAccessTypeExpr" }
}
/**
@@ -887,6 +927,8 @@ class IntersectionTypeExpr extends @intersection_typeexpr, TypeExpr {
int getNumElementType() { result = count(getAnElementType()) }
override TypeExpr getAnUnderlyingType() { result = getAnElementType().getAnUnderlyingType() }
override string getAPrimaryQlClass() { result = "IntersectionTypeExpr" }
}
/**
@@ -899,6 +941,8 @@ class ParenthesizedTypeExpr extends @parenthesized_typeexpr, TypeExpr {
override TypeExpr stripParens() { result = getElementType().stripParens() }
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
override string getAPrimaryQlClass() { result = "ParenthesizedTypeExpr" }
}
/**
@@ -922,6 +966,8 @@ class TupleTypeExpr extends @tuple_typeexpr, TypeExpr {
// Type element names are at indices -1, -2, -3, ...
result = getChild(-(n + 1)) and n >= 0
}
override string getAPrimaryQlClass() { result = "TupleTypeExpr" }
}
/**
@@ -930,6 +976,8 @@ class TupleTypeExpr extends @tuple_typeexpr, TypeExpr {
class KeyofTypeExpr extends @keyof_typeexpr, TypeExpr {
/** Gets the type `T` in `keyof T`, denoting the object type whose property names are to be extracted. */
TypeExpr getElementType() { result = getChildTypeExpr(0) }
override string getAPrimaryQlClass() { result = "KeyofTypeExpr" }
}
/**
@@ -950,6 +998,8 @@ class MappedTypeExpr extends @mapped_typeexpr, TypeParameterized, TypeExpr {
TypeExpr getElementType() { result = getChildTypeExpr(1) }
override string describe() { result = "mapped type" }
override string getAPrimaryQlClass() { result = "MappedTypeExpr" }
}
/**
@@ -962,6 +1012,8 @@ class TypeofTypeExpr extends @typeof_typeexpr, TypeExpr {
* variable, function, class, or namespace whose type is to be extracted.
*/
VarTypeAccess getExpressionName() { result = this.getChildTypeExpr(0) }
override string getAPrimaryQlClass() { result = "TypeofTypeExpr" }
}
/**
@@ -991,6 +1043,8 @@ class PredicateTypeExpr extends @predicate_typeexpr, TypeExpr {
* Holds if this is a type of form `asserts E is T` or `asserts E`.
*/
predicate hasAssertsKeyword() { has_asserts_keyword(this) }
override string getAPrimaryQlClass() { result = "PredicateTypeExpr" }
}
/**
@@ -1004,6 +1058,8 @@ class PredicateTypeExpr extends @predicate_typeexpr, TypeExpr {
*/
class IsTypeExpr extends PredicateTypeExpr {
IsTypeExpr() { exists(getPredicateType()) }
override string getAPrimaryQlClass() { result = "IsTypeExpr" }
}
/**
@@ -1014,6 +1070,8 @@ class OptionalTypeExpr extends @optional_typeexpr, TypeExpr {
TypeExpr getElementType() { result = getChildTypeExpr(0) }
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
override string getAPrimaryQlClass() { result = "OptionalTypeExpr" }
}
/**
@@ -1025,6 +1083,8 @@ class RestTypeExpr extends @rest_typeexpr, TypeExpr {
/** Gets the type `T` in `...T[]`, such as `string` in `[number, ...string[]]`. */
TypeExpr getElementType() { result = getArrayType().(ArrayTypeExpr).getElementType() }
override string getAPrimaryQlClass() { result = "RestTypeExpr" }
}
/**
@@ -1035,6 +1095,8 @@ class ReadonlyTypeExpr extends @readonly_typeexpr, TypeExpr {
TypeExpr getElementType() { result = getChildTypeExpr(0) }
override TypeExpr getAnUnderlyingType() { result = getElementType().getAnUnderlyingType() }
override string getAPrimaryQlClass() { result = "ReadonlyTypeExpr" }
}
/**
@@ -1053,7 +1115,9 @@ class ReadonlyTypeExpr extends @readonly_typeexpr, TypeExpr {
*
* In the latter two cases, this may also refer to the pseudo-variable `this`.
*/
class VarTypeAccess extends @vartypeaccess, TypeExpr { }
class VarTypeAccess extends @vartypeaccess, TypeExpr {
override string getAPrimaryQlClass() { result = "VarTypeAccess" }
}
/**
* An identifier that refers to a variable from inside a type.
@@ -1063,6 +1127,8 @@ class VarTypeAccess extends @vartypeaccess, TypeExpr { }
class LocalVarTypeAccess extends @local_var_type_access, VarTypeAccess, LexicalAccess, Identifier {
/** Gets the variable being referenced, or nothing if this is a `this` keyword. */
Variable getVariable() { bind(this, result) }
override string getAPrimaryQlClass() { result = "LocalVarTypeAccess" }
}
/**
@@ -1073,7 +1139,9 @@ class LocalVarTypeAccess extends @local_var_type_access, VarTypeAccess, LexicalA
* interface Node { isLeaf(): this is Leaf; }
* ```
*/
class ThisVarTypeAccess extends @this_var_type_access, VarTypeAccess { }
class ThisVarTypeAccess extends @this_var_type_access, VarTypeAccess {
override string getAPrimaryQlClass() { result = "ThisVarTypeAccess" }
}
/**
* A qualified name that refers to a variable from inside a type.
@@ -1115,6 +1183,8 @@ class ConditionalTypeExpr extends @conditional_typeexpr, TypeExpr {
* Gets the type to be used if the `extend` condition fails, such as `B` in `T extends any[] ? A : B`.
*/
TypeExpr getFalseType() { result = getChildTypeExpr(3) }
override string getAPrimaryQlClass() { result = "ConditionalTypeExpr" }
}
/**
@@ -1129,6 +1199,8 @@ class InferTypeExpr extends @infer_typeexpr, TypeParameterized, TypeExpr {
override TypeParameter getTypeParameter(int n) { n = 0 and result = getTypeParameter() }
override string describe() { result = "'infer' type " + getTypeParameter().getName() }
override string getAPrimaryQlClass() { result = "InferTypeExpr" }
}
/**
@@ -1230,6 +1302,8 @@ class TypeParameter extends @type_parameter, TypeExpr {
* Gets the local type name declared by this type parameter.
*/
LocalTypeName getLocalTypeName() { result = getIdentifier().(TypeDecl).getLocalTypeName() }
override string getAPrimaryQlClass() { result = "TypeParameter" }
}
/**
@@ -1250,6 +1324,8 @@ class TypeAssertion extends Expr, @type_assertion {
override Expr getUnderlyingValue() { result = getExpression().getUnderlyingValue() }
override Expr getUnderlyingReference() { result = getExpression().getUnderlyingReference() }
override string getAPrimaryQlClass() { result = "TypeAssertion" }
}
/**
@@ -1272,6 +1348,8 @@ class NonNullAssertion extends Expr, @non_null_assertion {
override ControlFlowNode getFirstControlFlowNode() {
result = getExpression().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "NonNullAssertion" }
}
/**
@@ -1326,6 +1404,8 @@ class NamespaceAccess extends TypeExpr, NamespaceRef, @namespace_access {
* Gets the canonical name of the namespace being accessed.
*/
Namespace getNamespace() { ast_node_symbol(this, result) }
override string getAPrimaryQlClass() { result = "NamespaceAccess" }
}
/**
@@ -1337,6 +1417,8 @@ class LocalNamespaceAccess extends NamespaceAccess, LexicalAccess, Identifier,
/** Gets the local name being accessed. */
LocalNamespaceName getLocalNamespaceName() { namespacebind(this, result) }
override string getAPrimaryQlClass() { result = "LocalNamespaceAccess" }
}
/**
@@ -1370,22 +1452,30 @@ class ImportTypeExpr extends TypeExpr, @import_typeexpr {
/** Holds if this import is used in the context of a variable type, such as `let x: typeof import("fs")`. */
predicate isVarTypeAccess() { this instanceof @import_var_type_access }
override string getAPrimaryQlClass() { result = "ImportTypeExpr" }
}
/**
* An import used in the context of a type, such as in `let x: import("foo")`.
*/
class ImportTypeAccess extends TypeAccess, ImportTypeExpr, @import_type_access { }
class ImportTypeAccess extends TypeAccess, ImportTypeExpr, @import_type_access {
override string getAPrimaryQlClass() { result = "ImportTypeAccess" }
}
/**
* An import used in the context of a namespace inside a type annotation, such as in `let x: import("http").ServerRequest`.
*/
class ImportNamespaceAccess extends NamespaceAccess, ImportTypeExpr, @import_namespace_access { }
class ImportNamespaceAccess extends NamespaceAccess, ImportTypeExpr, @import_namespace_access {
override string getAPrimaryQlClass() { result = "ImportNamespaceAccess" }
}
/**
* An import used in the context of a variable type, such as in `let x: typeof import("fs")`.
*/
class ImportVarTypeAccess extends VarTypeAccess, ImportTypeExpr, @import_var_type_access { }
class ImportVarTypeAccess extends VarTypeAccess, ImportTypeExpr, @import_var_type_access {
override string getAPrimaryQlClass() { result = "ImportVarTypeAccess" }
}
/**
* A TypeScript enum declaration, such as the following declaration:
@@ -1463,6 +1553,8 @@ class EnumDeclaration extends NamespaceDefinition, @enum_declaration, AST::Value
predicate isConst() { is_const_enum(this) }
override ControlFlowNode getFirstControlFlowNode() { result = getIdentifier() }
override string getAPrimaryQlClass() { result = "EnumDeclaration" }
}
/**
@@ -1508,6 +1600,8 @@ class EnumMember extends ASTNode, @enum_member {
* Gets the canonical name of the type defined by this enum member.
*/
TypeName getTypeName() { ast_node_symbol(this, result) }
override string getAPrimaryQlClass() { result = "EnumMember" }
}
/**

View File

@@ -235,6 +235,8 @@ class VarRef extends @varref, Identifier, BindingPattern, LexicalRef {
override predicate isImpure() { none() }
override Expr getUnderlyingReference() { result = this }
override string getAPrimaryQlClass() { result = "VarRef" }
}
/**
@@ -395,7 +397,7 @@ class BindingPattern extends @pattern, Expr {
*
* Only the outermost part of a binding pattern can have a type annotation.
* For instance, in the declaration,
* <pre>
*<pre>
* var {x}: Point
* </pre>
* the variable `x` has no type annotation, whereas the pattern `{x}` has the type
@@ -450,6 +452,8 @@ class VarDecl extends @var_decl, VarRef, LexicalDecl {
or
exists(BindingPattern p | this = p.getABindingVarRef() and p.isLValue())
}
override string getAPrimaryQlClass() { result = "VarDecl" }
}
/**
@@ -520,6 +524,8 @@ class ArrayPattern extends DestructuringPattern, @array_pattern {
override VarRef getABindingVarRef() {
result = getAnElement().(BindingPattern).getABindingVarRef()
}
override string getAPrimaryQlClass() { result = "ArrayPattern" }
}
/**
@@ -559,6 +565,8 @@ class ObjectPattern extends DestructuringPattern, @object_pattern {
result = getAPropertyPattern().getValuePattern().(BindingPattern).getABindingVarRef() or
result = getRest().(BindingPattern).getABindingVarRef()
}
override string getAPrimaryQlClass() { result = "ObjectPattern" }
}
/**
@@ -617,6 +625,8 @@ class PropertyPattern extends @property, ASTNode {
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "PropertyPattern" }
}
/**
@@ -653,6 +663,8 @@ class VariableDeclarator extends Expr, @var_declarator {
override ControlFlowNode getFirstControlFlowNode() {
result = getBindingPattern().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "VariableDeclarator" }
}
/**
@@ -783,6 +795,8 @@ class Parameter extends BindingPattern {
* ```
*/
predicate isDeclaredOptional() { is_optional_parameter_declaration(this) }
override string getAPrimaryQlClass() { result = "Parameter" }
}
/**
@@ -824,6 +838,8 @@ class SimpleParameter extends Parameter, VarDecl {
paramName <= tagName
)
}
override string getAPrimaryQlClass() { result = "SimpleParameter" }
}
/**
@@ -844,6 +860,8 @@ class FieldParameter extends SimpleParameter {
/** Gets the field induced by this parameter. */
ParameterField getField() { result.getParameter() = this }
override string getAPrimaryQlClass() { result = "FieldParameter" }
}
/**

View File

@@ -83,6 +83,8 @@ class YAMLNode extends @yaml_node, Locatable {
* Gets the YAML value this node corresponds to after resolving aliases and includes.
*/
YAMLValue eval() { result = this }
override string getAPrimaryQlClass() { result = "YAMLNode" }
}
/**
@@ -142,6 +144,8 @@ class YAMLScalar extends YAMLValue, @yaml_scalar_node {
* Gets the value of this scalar, as a string.
*/
string getValue() { yaml_scalars(this, _, result) }
override string getAPrimaryQlClass() { result = "YAMLScalar" }
}
/**
@@ -304,7 +308,9 @@ class YAMLInclude extends YAMLScalar {
* - -blue
* ```
*/
class YAMLCollection extends YAMLValue, @yaml_collection_node { }
class YAMLCollection extends YAMLValue, @yaml_collection_node {
override string getAPrimaryQlClass() { result = "YAMLCollection" }
}
/**
* A YAML mapping.
@@ -356,6 +362,8 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node {
* Gets the value that this mapping maps `key` to.
*/
YAMLValue lookup(string key) { exists(YAMLScalar s | s.getValue() = key | maps(s, result)) }
override string getAPrimaryQlClass() { result = "YAMLMapping" }
}
/**
@@ -379,6 +387,8 @@ class YAMLSequence extends YAMLCollection, @yaml_sequence_node {
* Gets the `i`th element in this sequence, as a YAML value.
*/
YAMLValue getElement(int i) { result = getElementNode(i).eval() }
override string getAPrimaryQlClass() { result = "YAMLSequence" }
}
/**
@@ -400,6 +410,8 @@ class YAMLAliasNode extends YAMLNode, @yaml_alias_node {
* Gets the target anchor this alias refers to.
*/
string getTarget() { yaml_aliases(this, result) }
override string getAPrimaryQlClass() { result = "YAMLAliasNode" }
}
/**