mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge pull request #3297 from asger-semmle/js/isambient-refactor
Approved by esbena
This commit is contained in:
@@ -125,6 +125,42 @@ class ASTNode extends @ast_node, Locatable {
|
||||
/** Holds if this syntactic entity belongs to an externs file. */
|
||||
predicate inExternsFile() { getTopLevel().isExterns() }
|
||||
|
||||
/**
|
||||
* Holds if this is an ambient node that is not a `TypeExpr` and is not inside a `.d.ts` file
|
||||
*
|
||||
* Since the overwhelming majority of ambient nodes are `TypeExpr` or inside `.d.ts` files,
|
||||
* we avoid caching them.
|
||||
*/
|
||||
cached
|
||||
private predicate isAmbientInternal() {
|
||||
getParent().isAmbientInternal()
|
||||
or
|
||||
not isAmbientTopLevel(getTopLevel()) and
|
||||
(
|
||||
this instanceof ExternalModuleDeclaration
|
||||
or
|
||||
this instanceof GlobalAugmentationDeclaration
|
||||
or
|
||||
this instanceof ExportAsNamespaceDeclaration
|
||||
or
|
||||
this instanceof TypeAliasDeclaration
|
||||
or
|
||||
this instanceof InterfaceDeclaration
|
||||
or
|
||||
hasDeclareKeyword(this)
|
||||
or
|
||||
hasTypeKeyword(this)
|
||||
or
|
||||
// An export such as `export declare function f()` should be seen as ambient.
|
||||
hasDeclareKeyword(this.(ExportNamedDeclaration).getOperand())
|
||||
or
|
||||
exists(Function f |
|
||||
this = f and
|
||||
not f.hasBody()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is part of an ambient declaration or type annotation in a TypeScript file.
|
||||
*
|
||||
@@ -134,9 +170,22 @@ class ASTNode extends @ast_node, Locatable {
|
||||
* The TypeScript compiler emits no code for ambient declarations, but they
|
||||
* can affect name resolution and type checking at compile-time.
|
||||
*/
|
||||
predicate isAmbient() { getParent().isAmbient() }
|
||||
pragma[inline]
|
||||
predicate isAmbient() {
|
||||
isAmbientInternal()
|
||||
or
|
||||
isAmbientTopLevel(getTopLevel())
|
||||
or
|
||||
this instanceof TypeExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given file is a `.d.ts` file.
|
||||
*/
|
||||
cached
|
||||
private predicate isAmbientTopLevel(TopLevel tl) { tl.getFile().getBaseName().matches("%.d.ts") }
|
||||
|
||||
/**
|
||||
* A toplevel syntactic unit; that is, a stand-alone script, an inline script
|
||||
* embedded in an HTML `<script>` tag, a code snippet assigned to an HTML event
|
||||
@@ -197,11 +246,6 @@ class TopLevel extends @toplevel, StmtContainer {
|
||||
override ControlFlowNode getFirstControlFlowNode() { result = getEntry() }
|
||||
|
||||
override string toString() { result = "<toplevel>" }
|
||||
|
||||
override predicate isAmbient() {
|
||||
getFile().getFileType().isTypeScript() and
|
||||
getFile().getBaseName().matches("%.d.ts")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1059,12 +1059,6 @@ class FieldDeclaration extends MemberDeclaration, @field {
|
||||
|
||||
/** Holds if this is a TypeScript field marked as definitely assigned with the `!` operator. */
|
||||
predicate hasDefiniteAssignmentAssertion() { hasDefiniteAssignmentAssertion(this) }
|
||||
|
||||
override predicate isAmbient() {
|
||||
hasDeclareKeyword(this)
|
||||
or
|
||||
getParent().isAmbient()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,11 +79,6 @@ class ImportDeclaration extends Stmt, Import, @importdeclaration {
|
||||
|
||||
/** Holds if this is declared with the `type` keyword, so it only imports types. */
|
||||
predicate isTypeOnly() { hasTypeKeyword(this) }
|
||||
|
||||
override predicate isAmbient() {
|
||||
Stmt.super.isAmbient() or
|
||||
isTypeOnly()
|
||||
}
|
||||
}
|
||||
|
||||
/** A literal path expression appearing in an `import` declaration. */
|
||||
@@ -267,11 +262,6 @@ abstract class ExportDeclaration extends Stmt, @exportdeclaration {
|
||||
|
||||
/** Holds if is declared with the `type` keyword, so only types are exported. */
|
||||
predicate isTypeOnly() { hasTypeKeyword(this) }
|
||||
|
||||
override predicate isAmbient() {
|
||||
Stmt.super.isAmbient() or
|
||||
isTypeOnly()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -422,11 +412,6 @@ class ExportNamedDeclaration extends ExportDeclaration, @exportnameddeclaration
|
||||
|
||||
/** Gets an export specifier of this declaration. */
|
||||
ExportSpecifier getASpecifier() { result = getSpecifier(_) }
|
||||
|
||||
override predicate isAmbient() {
|
||||
// An export such as `export declare function f()` should be seen as ambient.
|
||||
hasDeclareKeyword(getOperand()) or getParent().isAmbient()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -397,8 +397,6 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
*/
|
||||
predicate isAbstract() { exists(MethodDeclaration md | this = md.getBody() | md.isAbstract()) }
|
||||
|
||||
override predicate isAmbient() { getParent().isAmbient() or not hasBody() }
|
||||
|
||||
/**
|
||||
* Holds if this function cannot be invoked using `new` because it
|
||||
* is of the given `kind`.
|
||||
|
||||
@@ -54,8 +54,6 @@ class Stmt extends @stmt, ExprOrStmt, Documentable {
|
||||
getContainer().(Expr).getEnclosingStmt().nestedIn(outer)
|
||||
}
|
||||
|
||||
override predicate isAmbient() { hasDeclareKeyword(this) or getParent().isAmbient() }
|
||||
|
||||
/**
|
||||
* Gets the `try` statement with a catch block containing this statement without
|
||||
* crossing function boundaries or other `try ` statements with catch blocks.
|
||||
@@ -931,8 +929,6 @@ class DebuggerStmt extends @debuggerstmt, Stmt {
|
||||
*/
|
||||
class FunctionDeclStmt extends @functiondeclstmt, Stmt, Function {
|
||||
override Stmt getEnclosingStmt() { result = this }
|
||||
|
||||
override predicate isAmbient() { Function.super.isAmbient() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -155,8 +155,6 @@ class ExternalModuleDeclaration extends Stmt, StmtContainer, @externalmoduledecl
|
||||
int getNumStmt() { result = count(getAStmt()) }
|
||||
|
||||
override StmtContainer getEnclosingContainer() { result = this.getContainer() }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,8 +174,6 @@ class GlobalAugmentationDeclaration extends Stmt, StmtContainer, @globalaugmenta
|
||||
int getNumStmt() { result = count(getAStmt()) }
|
||||
|
||||
override StmtContainer getEnclosingContainer() { result = this.getContainer() }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
}
|
||||
|
||||
/** A TypeScript "import-equals" declaration. */
|
||||
@@ -237,8 +233,6 @@ class ExportAsNamespaceDeclaration extends Stmt, @exportasnamespacedeclaration {
|
||||
* Gets the `X` in `export as namespace X`.
|
||||
*/
|
||||
Identifier getIdentifier() { result = getChildExpr(0) }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,8 +253,6 @@ class TypeAliasDeclaration extends @typealiasdeclaration, TypeParameterized, Stm
|
||||
|
||||
override string describe() { result = "type alias " + getName() }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
|
||||
/**
|
||||
* Gets the canonical name of the type being defined.
|
||||
*/
|
||||
@@ -286,8 +278,6 @@ class InterfaceDeclaration extends Stmt, InterfaceDefinition, @interfacedeclarat
|
||||
|
||||
override StmtContainer getContainer() { result = Stmt.super.getContainer() }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
|
||||
override string describe() { result = "interface " + getName() }
|
||||
|
||||
/**
|
||||
@@ -533,8 +523,6 @@ class LocalNamespaceName extends @local_namespace_name, LexicalName {
|
||||
class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation {
|
||||
override string toString() { typeexprs(this, _, _, _, result) }
|
||||
|
||||
override predicate isAmbient() { any() }
|
||||
|
||||
/**
|
||||
* Gets the static type expressed by this type annotation.
|
||||
*
|
||||
@@ -1410,8 +1398,6 @@ class EnumDeclaration extends NamespaceDefinition, @enumdeclaration, AST::ValueN
|
||||
/** Holds if this enumeration is declared with the `const` keyword. */
|
||||
predicate isConst() { isConstEnum(this) }
|
||||
|
||||
override predicate isAmbient() { hasDeclareKeyword(this) or getParent().isAmbient() }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() { result = getIdentifier() }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user