mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
add printAst query for printing JS/TS/JSON/YAML/HTML
This commit is contained in:
28
javascript/ql/src/printAst.ql
Normal file
28
javascript/ql/src/printAst.ql
Normal 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())
|
||||
}
|
||||
}
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 */ }
|
||||
* </pre>
|
||||
*/
|
||||
class JSXEmptyExpr extends Expr, @jsx_empty_expr { }
|
||||
class JSXEmptyExpr extends Expr, @jsx_empty_expr {
|
||||
override string getAPrimaryQlClass() { result = "JSXEmptyExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A legacy `@jsx` pragma.
|
||||
|
||||
@@ -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 = "???" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
714
javascript/ql/src/semmle/javascript/PrintAst.qll
Normal file
714
javascript/ql/src/semmle/javascript/PrintAst.qll
Normal 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"
|
||||
}
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user