Merge pull request #3088 from tausbn/python-prepare-autoformatting

Python: Prepare for autoformatting.
This commit is contained in:
Rasmus Wriedt Larsen
2020-03-18 17:48:46 +01:00
committed by GitHub
33 changed files with 194 additions and 193 deletions

View File

@@ -22,8 +22,8 @@ predicate multiple_calls_to_superclass_method(ClassObject self, FunctionObject m
multiple_invocation_paths(top, i1, i2, multi) and
top.runtime(self.declaredAttribute(name)) and
self.getASuperType().declaredAttribute(name) = multi |
/* Only called twice if called from different functions,
* or if one call-site can reach the other */
// Only called twice if called from different functions,
// or if one call-site can reach the other.
i1.getCall().getScope() != i2.getCall().getScope()
or
i1.getCall().strictlyReaches(i2.getCall())

View File

@@ -139,10 +139,9 @@ predicate too_few_args_objectapi(Call call, Object callable, int limit) {
arg_count_objectapi(call) < limit and
exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) |
call = func.getAFunctionCall().getNode() and limit = func.minParameters() and
/* The combination of misuse of `mox.Mox().StubOutWithMock()`
* and a bug in mox's implementation of methods results in having to
* pass 1 too few arguments to the mocked function.
*/
// The combination of misuse of `mox.Mox().StubOutWithMock()`
// and a bug in mox's implementation of methods results in having to
// pass 1 too few arguments to the mocked function.
not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod())
or
call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1
@@ -160,10 +159,9 @@ predicate too_few_args(Call call, Value callable, int limit) {
arg_count(call) < limit and
exists(FunctionValue func | func = get_function_or_initializer(callable) |
call = func.getACall().getNode() and limit = func.minParameters() and
/* The combination of misuse of `mox.Mox().StubOutWithMock()`
* and a bug in mox's implementation of methods results in having to
* pass 1 too few arguments to the mocked function.
*/
// The combination of misuse of `mox.Mox().StubOutWithMock()`
// and a bug in mox's implementation of methods results in having to
// pass 1 too few arguments to the mocked function.
not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod())
or
call = func.getACall().getNode() and limit = func.minParameters() - 1

View File

@@ -1,7 +1,6 @@
import python
/** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`.
*/
/** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. */
predicate useOfMoxInModule(Module m) {
exists(ModuleObject mox |
mox.getName() = "mox" or mox.getName() = "mox3.mox" |

View File

@@ -48,8 +48,7 @@ class Symbol extends TSymbol {
)
}
/** Finds the `AstNode` that this `Symbol` refers to.
*/
/** Finds the `AstNode` that this `Symbol` refers to. */
AstNode find() {
this = TModule(result)
or
@@ -91,8 +90,7 @@ class Symbol extends TSymbol {
)
}
/** Gets the `Symbol` that is the named member of this `Symbol`.
*/
/** Gets the `Symbol` that is the named member of this `Symbol`. */
Symbol getMember(string name) {
result = TMember(this, name)
}

View File

@@ -10,8 +10,7 @@ private newtype TDefinition =
a instanceof Expr or a instanceof Stmt or a instanceof Module
}
/** A definition for the purposes of jump-to-definition.
*/
/** A definition for the purposes of jump-to-definition. */
class Definition extends TLocalDefinition {
@@ -159,8 +158,7 @@ private predicate delete_defn(DeletionDefinition def, Definition defn) {
none()
}
/* Implicit "defn" of the names of submodules at the start of an `__init__.py` file.
*/
/* Implicit "defn" of the names of submodules at the start of an `__init__.py` file. */
private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Definition defn) {
exists(PackageObject package, ModuleObject mod |
package.getInitModule().getModule() = def.getDefiningNode().getScope() and
@@ -170,7 +168,9 @@ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Defin
}
/* Helper for scope_entry_value_transfer(...). Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters */
/* Helper for scope_entry_value_transfer(...).
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters
*/
private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
exists(CallNode callsite, FunctionObject f |
f.getACall() = callsite and
@@ -469,8 +469,8 @@ class NiceLocationExpr extends @py_expr {
or
this.(Name).getLocation().hasLocationInfo(f, bl, bc, el, ec)
or
/* Show xxx for `xxx` in `from xxx import y` or
* for `import xxx` or for `import xxx as yyy`. */
// Show xxx for `xxx` in `from xxx import y` or
// for `import xxx` or for `import xxx as yyy`.
this.(ImportExpr).getLocation().hasLocationInfo(f, bl, bc, el, ec)
or
/* Show y for `y` in `from xxx import y` */

View File

@@ -1,8 +1,7 @@
import python
/* A class representing the six comparison operators, ==, !=, <, <=, > and >=.
* */
/** A class representing the six comparison operators, ==, !=, <, <=, > and >=. */
class CompareOp extends int {
CompareOp() {

View File

@@ -356,7 +356,7 @@ class Repr extends Repr_ {
/* Constants */
/** A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as
`"hello"` are treated as Bytes for Python2, but Unicode for Python3. */
* `"hello"` are treated as Bytes for Python2, but Unicode for Python3. */
class Bytes extends StrConst {
/* syntax: b"hello" */
@@ -395,8 +395,7 @@ class Ellipsis extends Ellipsis_ {
}
/** Immutable literal expressions (except tuples).
* Consists of string (both unicode and byte) literals
* and numeric literals.
* Consists of string (both unicode and byte) literals and numeric literals.
*/
abstract class ImmutableLiteral extends Expr {
@@ -433,8 +432,10 @@ class IntegerLiteral extends Num {
not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral
}
/** Gets the (integer) value of this constant. Will not return a result if the value does not fit into
a 32 bit signed value */
/**
* Gets the (integer) value of this constant. Will not return a result if the value does not fit into
* a 32 bit signed value
*/
int getValue() {
result = this.getN().toInt()
}
@@ -540,8 +541,10 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
}
/** Gets the (integer) value of this constant. Will not return a result if the value does not fit into
a 32 bit signed value */
/**
* Gets the (integer) value of this constant. Will not return a result if the value does not fit into
* a 32 bit signed value
*/
int getValue() {
result = -(this.getOperand().(IntegerLiteral).getValue())
}
@@ -549,7 +552,8 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
}
/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as
"hello" are treated as Bytes for Python2, but Unicode for Python3. */
* "hello" are treated as Bytes for Python2, but Unicode for Python3.
*/
class Unicode extends StrConst {
/* syntax: "hello" */

View File

@@ -129,8 +129,10 @@ class Folder extends Container {
}
/** A container is an abstract representation of a file system object that can
hold elements of interest. */
/**
* A container is an abstract representation of a file system object that can
* hold elements of interest.
*/
abstract class Container extends @container {
Container getParent() {
@@ -473,8 +475,10 @@ class Line extends @py_line {
}
/** A syntax error. Note that if there is a syntax error in a module,
much information about that module will be lost */
/**
* A syntax error. Note that if there is a syntax error in a module,
* much information about that module will be lost
*/
class SyntaxError extends Location {
SyntaxError() {
@@ -492,8 +496,10 @@ class SyntaxError extends Location {
}
/** An encoding error. Note that if there is an encoding error in a module,
much information about that module will be lost */
/**
* An encoding error. Note that if there is an encoding error in a module,
* much information about that module will be lost
*/
class EncodingError extends SyntaxError {
EncodingError() {

View File

@@ -27,8 +27,8 @@ private AstNode toAst(ControlFlowNode n) {
/** A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes,
* although most syntactic nodes have only one corresponding control flow node.
* Edges between control flow nodes include exceptional as well as normal control flow.
*/
* Edges between control flow nodes include exceptional as well as normal control flow.
*/
class ControlFlowNode extends @py_flow_node {
/** Whether this control flow node is a load (including those in augmented assignments) */
@@ -235,7 +235,8 @@ class ControlFlowNode extends @py_flow_node {
PointsTo::pointsTo(this, context, value, origin)
}
/** Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
/**
* Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
* precise, but may not provide information for a significant number of flow-nodes.
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
@@ -245,8 +246,7 @@ class ControlFlowNode extends @py_flow_node {
this.refersTo(_, obj, cls, origin)
}
/** Gets what this expression might "refer-to" in the given `context`.
*/
/** Gets what this expression might "refer-to" in the given `context`. */
pragma [nomagic]
predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) {
not obj = unknownValue() and
@@ -329,8 +329,8 @@ class ControlFlowNode extends @py_flow_node {
exists(BasicBlock b |
start_bb_likely_reachable(b) and
not end_bb_likely_reachable(b) and
/* If there is an unlikely successor edge earlier in the BB
* than this node, then this node must be unreachable */
// If there is an unlikely successor edge earlier in the BB
// than this node, then this node must be unreachable.
exists(ControlFlowNode p, int i, int j |
p.(RaisingNode).unlikelySuccessor(_) and
p = b.getNode(i) and
@@ -531,7 +531,7 @@ class AttrNode extends ControlFlowNode {
}
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node,
with the matching name */
* with the matching name */
ControlFlowNode getObject(string name) {
exists(Attribute a |
this.getNode() = a and a.getObject() = result.getNode() and
@@ -555,7 +555,7 @@ class ImportMemberNode extends ControlFlowNode {
}
/** Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node,
with the matching name*/
* with the matching name */
ControlFlowNode getModule(string name) {
exists(ImportMember i |
this.getNode() = i and i.getModule() = result.getNode() |

View File

@@ -1,7 +1,9 @@
import python
/** A function, independent of defaults and binding.
It is the syntactic entity that is compiled to a code object. */
/**
* A function, independent of defaults and binding.
* It is the syntactic entity that is compiled to a code object.
*/
class Function extends Function_, Scope, AstNode {
/** The expression defining this function */
@@ -33,8 +35,10 @@ class Function extends Function_, Scope, AstNode {
name != "__init__")
}
/** Whether this function is a generator function,
that is whether it contains a yield or yield-from expression */
/**
* Whether this function is a generator function,
* that is whether it contains a yield or yield-from expression
*/
predicate isGenerator() {
exists(Yield y | y.getScope() = this)
or

View File

@@ -9,37 +9,38 @@ class ConditionBlock extends BasicBlock {
/** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */
predicate controls(BasicBlock controlled, boolean testIsTrue) {
/* For this block to control the block 'controlled' with 'testIsTrue' the following must be true:
Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'.
Execution must have passed through the 'testIsTrue' edge leaving 'this'.
Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled',
the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor()
so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that
all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor().
For example, in the following python snippet:
<code>
if x:
controlled
false_successor
uncontrolled
</code>
false_successor dominates uncontrolled, but not all of its predecessors are this (if x)
or dominated by itself. Whereas in the following code:
<code>
if x:
while controlled:
also_controlled
false_successor
uncontrolled
</code>
the block 'while controlled' is controlled because all of its predecessors are this (if x)
or (in the case of 'also_controlled') dominated by itself.
The additional constraint on the predecessors of the test successor implies
that `this` strictly dominates `controlled` so that isn't necessary to check
directly.
/*
* For this block to control the block 'controlled' with 'testIsTrue' the following must be true:
* Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'.
* Execution must have passed through the 'testIsTrue' edge leaving 'this'.
*
* Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled',
* the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor()
* so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that
* all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor().
*
* For example, in the following python snippet:
* <code>
* if x:
* controlled
* false_successor
* uncontrolled
* </code>
* false_successor dominates uncontrolled, but not all of its predecessors are this (if x)
* or dominated by itself. Whereas in the following code:
* <code>
* if x:
* while controlled:
* also_controlled
* false_successor
* uncontrolled
* </code>
* the block 'while controlled' is controlled because all of its predecessors are this (if x)
* or (in the case of 'also_controlled') dominated by itself.
*
* The additional constraint on the predecessors of the test successor implies
* that `this` strictly dominates `controlled` so that isn't necessary to check
* directly.
*/
exists(BasicBlock succ |
testIsTrue = true and succ = this.getATrueSuccessor()

View File

@@ -2,7 +2,7 @@ import python
private import semmle.python.types.Builtins
/** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
`import x` is transformed into `import x as x` */
* `import x` is transformed into `import x as x` */
class Alias extends Alias_ {
Location getLocation() {
@@ -38,7 +38,7 @@ class ImportExpr extends ImportExpr_ {
}
/** The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports,
and level > 0 for explicit relative imports. */
* and level > 0 for explicit relative imports. */
override int getLevel() {
exists(int l | l = super.getLevel() |
l > 0 and result = l

View File

@@ -4,7 +4,7 @@ import python
class FunctionMetrics extends Function {
/** Gets the total number of lines (including blank lines)
from the definition to the end of the function */
* from the definition to the end of the function */
int getNumberOfLines() {
py_alllines(this, result)
}
@@ -53,8 +53,8 @@ class FunctionMetrics extends Function {
}
/** Dependency of Callables
One callable "this" depends on another callable "result"
if "this" makes some call to a method that may end up being "result".
* One callable "this" depends on another callable "result"
* if "this" makes some call to a method that may end up being "result".
*/
FunctionMetrics getADependency() {
result != this and
@@ -78,16 +78,16 @@ class FunctionMetrics extends Function {
}
/** Afferent Coupling
the number of callables that depend on this method.
This is sometimes called the "fan-in" of a method.
* the number of callables that depend on this method.
* This is sometimes called the "fan-in" of a method.
*/
int getAfferentCoupling() {
result = count(FunctionMetrics m | m.getADependency() = this )
}
/** Efferent Coupling
the number of methods that this method depends on
This is sometimes called the "fan-out" of a method.
* the number of methods that this method depends on
* This is sometimes called the "fan-out" of a method.
*/
int getEfferentCoupling() {
result = count(FunctionMetrics m | this.getADependency() = m)
@@ -112,7 +112,7 @@ class FunctionMetrics extends Function {
class ClassMetrics extends Class {
/** Gets the total number of lines (including blank lines)
from the definition to the end of the class */
* from the definition to the end of the class */
int getNumberOfLines() {
py_alllines(this, result)
}
@@ -172,19 +172,18 @@ class ClassMetrics extends Class {
/* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */
/* The aim of this metric is to try and determine whether a class
represents one abstraction (good) or multiple abstractions (bad).
If a class represents multiple abstractions, it should be split
up into multiple classes.
In the Chidamber and Kemerer method, this is measured as follows:
n1 = number of pairs of distinct methods in a class that do *not*
have at least one commonly accessed field
n2 = number of pairs of distinct methods in a class that do
have at least one commonly accessed field
lcom = ((n1 - n2)/2 max 0)
We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2.
* represents one abstraction (good) or multiple abstractions (bad).
* If a class represents multiple abstractions, it should be split
* up into multiple classes.
*
* In the Chidamber and Kemerer method, this is measured as follows:
* n1 = number of pairs of distinct methods in a class that do *not*
* have at least one commonly accessed field
* n2 = number of pairs of distinct methods in a class that do
* have at least one commonly accessed field
* lcom = ((n1 - n2)/2 max 0)
*
* We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2.
*/
/** should function f be excluded from the cohesion computation? */

View File

@@ -41,10 +41,9 @@ class SelfAttributeRead extends SelfAttribute {
SelfAttributeRead() {
this.getCtx() instanceof Load and
/* Be stricter for loads.
* We want to generous as to what is defined (ie stores),
* but strict as to what needs to be defined (ie loads).
*/
// Be stricter for loads.
// We want to generous as to what is defined (i.e. stores),
// but strict as to what needs to be defined (i.e. loads).
exists(ClassObject cls, FunctionObject func |
cls.declaredAttribute(_) = func |
func.getFunction() = this.getScope() and

View File

@@ -471,8 +471,7 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition {
}
/** A definition of an ESSA variable that takes another ESSA variable as an input.
*/
/** A definition of an ESSA variable that takes another ESSA variable as an input. */
class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement {
override string toString() {

View File

@@ -232,8 +232,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
Builtin getReturnType() {
exists(Builtin func |
func = this.getBuiltin() |
/* Enumerate the types of a few builtin functions, that the CPython analysis misses.
*/
/* Enumerate the types of a few builtin functions, that the CPython analysis misses. */
func = Builtin::builtin("hex") and result = Builtin::special("str")
or
func = Builtin::builtin("oct") and result = Builtin::special("str")
@@ -294,8 +293,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
}
/** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`.
*/
/** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`. */
class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject {
override Builtin getBuiltin() {

View File

@@ -542,13 +542,13 @@ class ClassValue extends Value {
}
/** Holds if this class is a new style class.
A new style class is one that implicitly or explicitly inherits from `object`. */
* A new style class is one that implicitly or explicitly inherits from `object`. */
predicate isNewStyle() {
Types::isNewStyle(this)
}
/** Holds if this class is an old style class.
An old style class is one that does not inherit from `object`. */
* An old style class is one that does not inherit from `object`. */
predicate isOldStyle() {
Types::isOldStyle(this)
}
@@ -742,7 +742,7 @@ class TupleValue extends SequenceValue {
}
/** A class representing strings, either present in the source as a literal, or
in a builtin as a value. */
* in a builtin as a value. */
class StringValue extends Value {
StringValue() {
@@ -918,7 +918,7 @@ module ClassValue {
}
/** Get the `ClassValue` for the `str` class. This is `bytes` in Python 2,
and `str` in Python 3. */
* and `str` in Python 3. */
ClassValue str() {
if major_version() = 2 then
result = bytes()

View File

@@ -1,4 +1,4 @@
/**
/*
*
* ## Points-to analysis for Python
*

View File

@@ -3,8 +3,7 @@ private import Common
import semmle.python.security.TaintTracking
/** An extensible kind of taint representing any kind of string.
*/
/** An extensible kind of taint representing any kind of string. */
abstract class StringKind extends TaintKind {
bindingset[this]

View File

@@ -73,13 +73,13 @@ class ClassObject extends Object {
}
/** Whether this class is a new style class.
A new style class is one that implicitly or explicitly inherits from `object`. */
* A new style class is one that implicitly or explicitly inherits from `object`. */
predicate isNewStyle() {
Types::isNewStyle(theClass())
}
/** Whether this class is an old style class.
An old style class is one that does not inherit from `object`. */
* An old style class is one that does not inherit from `object`. */
predicate isOldStyle() {
Types::isOldStyle(theClass())
}
@@ -112,7 +112,7 @@ class ClassObject extends Object {
}
/** Returns an attribute as it would be when looked up at runtime on this class.
Will include attributes of super-classes */
* Will include attributes of super-classes */
Object lookupAttribute(string name) {
exists(ObjectInternal val |
theClass().lookup(name, val, _) and
@@ -155,7 +155,7 @@ class ClassObject extends Object {
}
/** Whether it is impossible to know all the attributes of this class. Usually because it is
impossible to calculate the full class hierarchy or because some attribute is too dynamic. */
* impossible to calculate the full class hierarchy or because some attribute is too dynamic. */
predicate unknowableAttributes() {
/* True for a class with undeterminable superclasses, unanalysable metaclasses, or other confusions */
this.failedInference()

View File

@@ -35,7 +35,7 @@ class RaisingNode extends ControlFlowNode {
}
/** Gets the type of an exception that may be raised
at this control flow node */
* at this control flow node */
ClassObject getARaisedType() {
result = this.localRaisedType()
or
@@ -118,8 +118,7 @@ class RaisingNode extends ControlFlowNode {
)
}
/** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ.
*/
/** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. */
predicate unlikelySuccessor(ControlFlowNode succ) {
succ = this.getAnExceptionalSuccessor() and
not this.viableExceptionEdge(succ, _) and

View File

@@ -70,21 +70,20 @@ abstract class FunctionObject extends Object {
}
/** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
* This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
*/
ControlFlowNode getArgumentForCall(CallNode call, int n) {
result = theCallable().getArgumentForCall(call, n)
}
/** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the self argument.
* This predicate will correctly handle `x.y()`, treating `x` as the self argument.
*/
ControlFlowNode getNamedArgumentForCall(CallNode call, string name) {
result = theCallable().getNamedArgumentForCall(call, name)
}
/** Whether this function never returns. This is an approximation.
*/
/** Whether this function never returns. This is an approximation. */
predicate neverReturns() {
theCallable().neverReturns()
}

View File

@@ -79,7 +79,7 @@ abstract class ModuleObject extends Object {
}
/** Whether this module "exports" `name`. That is, whether using `import *` on this module
will result in `name` being added to the namespace. */
* will result in `name` being added to the namespace. */
predicate exports(string name) {
theModule().exports(name)
}

View File

@@ -44,8 +44,8 @@ class Object extends @py_object {
this = unknownValue() and result = theUnknownType()
}
/** Whether this a builtin object. A builtin object is one defined by the implementation,
such as the integer 4 or by a native extension, such as a NumPy array class. */
/** Whether this is a builtin object. A builtin object is one defined by the implementation,
* such as the integer 4 or by a native extension, such as a NumPy array class. */
predicate isBuiltin() {
exists(this.asBuiltin())
}