glean-0.1.0.0: glean/schema/source/hack.angle
# Copyright (c) Meta Platforms, Inc. and affiliates.
schema hack.6 {
import src
import fbthrift
# Name (identifier)
predicate Name : string
# Qualified namespace name
predicate NamespaceQName :
{
name : Name,
parent : maybe NamespaceQName,
}
# Qualified identifier
predicate QName :
{
name : Name,
namespace_ : maybe NamespaceQName,
}
# Type and contexts are represented as strings.
# Qualified names use "\\" as separator, don't start with a leading "\\".
# The most common types don't start with HH https://fburl.com/code/uavv841q
#
# Example: fully qualified name -> representation in DB
# \\HH\\Contexts\\throws<\\FooException> -> HH\\Contexts\\throws<FooException>
# \\HH\\Awaitable -> Awaitable
# \\HH\\Contexts\\defaults -> HH\\Contexts\\defaults
# \\HH\\Traversable -> Traversable
predicate Type : string
predicate Context_ : string
# Hint predicate follow closely the Hack hint AST (Aast_defs.hint)
# QName uniquely defines a container, the kind (class, trait...) isn't
# needed.
type FieldClassConst = { container : QName, name : Name }
type ShapeKV = {
key: {
sf_regex_group : string |
sf_lit_string : string |
sf_class_const : FieldClassConst
},
value: Hint,
opt: bool,
}
# follow the structure of Aast_defs.hint
predicate Hint : {
apply : { class_name : QName, values : [Hint] } |
option : Hint |
like : Hint |
tuple : { req: [ Hint ], opt: [ Hint ], variadic : maybe Hint } |
class_args : Hint |
shape : { open_ : bool, map_ : [ShapeKV] } |
soft : Hint |
intersection : [ Hint ] |
union_ : [ Hint ] |
vect_or_dict : { maybe_key : maybe Hint, value_ : Hint } |
prim : Type |
var_ : string |
fun_context : string |
mixed |
wildcard |
nonnull |
this_ |
dynamic |
nothing |
other : Type | # fall back to pretty-printed type for non implemented types
}
# End Hints
predicate TypeInfo : {
displayType : Type, # human friendly textual representation
xrefs : [XRef], # spans are relative to the "displayType" field content
hint : maybe Hint, # structured representation of the type
}
# Named parameter
type Parameter =
{
name : Name,
type : maybe Type, # deprecated, replaced by TypeInfo
isInout : bool,
isVariadic : bool,
defaultValue : maybe string,
attributes : [UserAttribute],
typeInfo : maybe TypeInfo,
readonly : maybe ReadonlyKind,
}
# Type signature of function or method
predicate Signature :
{
returns : maybe Type, # deprecated, replaced by returnsTypeInfo
parameters : [Parameter],
contexts : maybe [Context_],
returnsTypeInfo : maybe TypeInfo,
}
# Visibility scope of declaration
type Visibility = enum { Private | Protected | Public | Internal }
# Variance (subtyping)
type Variance = enum { Contravariant | Covariant | Invariant }
# Reification kinds
#
# c.f. https://docs.hhvm.com/hack/reified-generics
#
# N.B. Missing __Warn T138109774
#
type ReifyKind = enum { Erased | Reified | SoftReified }
# Contrant kinds
type ConstraintKind = enum { As | Equal | Super }
# Constraint
type Constraint =
{
constraintKind : ConstraintKind,
type: Type, # deprecated, replaced by TypeInfo
typeInfo: maybe TypeInfo
}
type ReadonlyKind = enum { Readonly }
# User-defined attribute
predicate UserAttribute :
{
name : Name,
parameters : [string],
qname : maybe QName,
}
# Hack type parameter
type TypeParameter =
{
name : Name,
variance : Variance,
reifyKind : ReifyKind,
constraints : [Constraint],
attributes : [UserAttribute],
}
# Hack namespace
predicate NamespaceDeclaration : { name : NamespaceQName }
# Declaration/Definition of a Hack module
# generated from "new module" constructs)
predicate ModuleDeclaration : { name : Name }
# Declaration of a Hack class
predicate ClassDeclaration : { name : QName }
# Declaration of a Hack interface
predicate InterfaceDeclaration : { name : QName }
# Declaration of a Hack trait
predicate TraitDeclaration : { name : QName }
# Declaration of a Hack enum
predicate EnumDeclaration : { name : QName }
# Declaration of a container, which may be a parent or child of another
type ContainerDeclaration =
{
class_ : ClassDeclaration |
enum_ : EnumDeclaration |
interface_ : InterfaceDeclaration |
trait : TraitDeclaration |
}
# Declaration of a Hack typedef (type alias)
predicate TypedefDeclaration : { name : QName }
# Declaration of a global constant (top-level)
predicate GlobalConstDeclaration : { name : QName }
# Declaration of a Hack function, which could be top-level or inline
predicate FunctionDeclaration : { name : QName }
# Enumerator declaration (constant in an enum)
predicate Enumerator :
{
name : Name,
enumeration : EnumDeclaration,
}
# Declaration of a class constant (member constant)
predicate ClassConstDeclaration :
{
name : Name,
container : ContainerDeclaration,
}
# Declaration of a type constant (container member type constant)
predicate TypeConstDeclaration :
{
name : Name,
container : ContainerDeclaration,
}
# Declaration of a Hack method (member function)
predicate MethodDeclaration :
{
name : Name,
container : ContainerDeclaration,
}
# Declaration of a Hack property (container member variable)
predicate PropertyDeclaration :
{
name : Name,
container : ContainerDeclaration,
}
# Types of declarations in Hack
type Declaration =
{
classConst : ClassConstDeclaration |
container : ContainerDeclaration |
enumerator : Enumerator |
function_ : FunctionDeclaration |
globalConst : GlobalConstDeclaration |
namespace_ : NamespaceDeclaration |
method : MethodDeclaration |
property_ : PropertyDeclaration |
typeConst : TypeConstDeclaration |
typedef_ : TypedefDeclaration |
module : ModuleDeclaration |
}
# The location of a declaration, spanning the name declared only
predicate DeclarationLocation :
{
declaration : Declaration,
file : src.File,
span : src.ByteSpan,
}
# The location of a declaration and any accompanying definition (the same source
# location in Hack), spanning the whole declaration/definition construct.
#
# Known quirk: the spans in the Hack AST include leading attributes/types for
# most constructs, but these are excluded from the span location for container
# properties, eg: the span of class property `protected string $foo = "bar";`
# starts at `$foo` rather than `protected`.
#
# For modules, the span is the whole "new module Foo {}" expression
predicate DeclarationSpan :
{
declaration : Declaration,
file : src.File,
span : src.ByteSpan,
}
# For efficient queries across all declarations in a given file.
predicate FileDeclarations :
{
file : src.File,
declarations : [Declaration],
}
# Documentation comment for a given declaration
predicate DeclarationComment :
{
declaration : Declaration,
file : src.File,
span : src.ByteSpan,
}
type ModuleMembership = { declaration: ModuleDeclaration, internal: bool}
# Infos related to a hack module
predicate ModuleDefinition :
{
declaration : ModuleDeclaration,
attributes : [UserAttribute],
}
predicate MemberCluster :
{
members : [Declaration]
}
# All declarations in a container coming from a parent class (recursively)
# or a trait. Doesn't include the declarations that directly defined
# in the container. Members are grouped in clusters for storage efficiency.
predicate InheritedMembers :
{
container : ContainerDeclaration,
inheritedMembers : [MemberCluster],
}
# Definition of a Hack class
predicate ClassDefinition :
{
declaration : ClassDeclaration,
isAbstract : bool,
isFinal : bool,
members : [Declaration],
extends_ : maybe ClassDeclaration,
implements_ : [InterfaceDeclaration],
uses : [TraitDeclaration],
attributes : [UserAttribute],
typeParams : [TypeParameter],
module_ : maybe ModuleMembership,
}
# Definition of a Hack interface
predicate InterfaceDefinition :
{
declaration : InterfaceDeclaration,
members : [Declaration],
extends_ : [InterfaceDeclaration],
attributes : [UserAttribute],
typeParams : [TypeParameter],
requireExtends : [ClassDeclaration],
module_ : maybe ModuleMembership,
}
# Definition of a Hack trait
predicate TraitDefinition :
{
declaration : TraitDeclaration,
members : [Declaration],
implements_ : [InterfaceDeclaration],
uses : [TraitDeclaration],
attributes : [UserAttribute],
typeParams : [TypeParameter],
requireExtends : [ClassDeclaration],
requireImplements : [InterfaceDeclaration],
module_ : maybe ModuleMembership,
requireClass : maybe [ClassDeclaration],
}
# Definition of a Hack enum
predicate EnumDefinition :
{
declaration : EnumDeclaration,
enumBase: Type, # deprecated, replaced by TypeInfo
enumBaseTypeInfo: maybe TypeInfo,
# 'as' type; always nothing for enum classes
enumConstraint: maybe Type,
enumConstraintTypeInfo: maybe TypeInfo,
enumerators : [Enumerator],
attributes : [UserAttribute],
# uses for normal enums, and extends for enum classes
includes : [EnumDeclaration],
isEnumClass : bool,
module_ : maybe ModuleMembership,
}
# Definition of a Hack typedef/alias
predicate TypedefDefinition :
{
declaration : TypedefDeclaration,
isTransparent : bool,
attributes : [UserAttribute],
typeParams : [TypeParameter],
module_ : maybe ModuleMembership,
}
# Definition of a Hack method (member function)
predicate MethodDefinition :
{
declaration: MethodDeclaration,
signature : Signature,
visibility : Visibility,
isAbstract : bool,
isAsync : bool,
isFinal : bool,
isStatic : bool,
attributes : [UserAttribute],
typeParams : [TypeParameter],
isReadonlyThis : maybe bool,
readonlyRet : maybe ReadonlyKind,
}
# Definition of a Hack property (container member variable)
predicate PropertyDefinition :
{
declaration: PropertyDeclaration,
type : maybe Type,
visibility : Visibility,
isFinal : bool,
isAbstract : bool,
isStatic : bool,
attributes : [UserAttribute],
typeInfo: maybe TypeInfo
}
# Definition of a Hack global (top-level) constant
predicate GlobalConstDefinition :
{
declaration : GlobalConstDeclaration,
type : maybe Type,
value : string,
typeInfo: maybe TypeInfo,
}
# Definition of a member constant
predicate ClassConstDefinition :
{
declaration : ClassConstDeclaration,
type : maybe Type,
# A none/nothing value indicates an abstract const
value : maybe string,
typeInfo: maybe TypeInfo
}
type TypeConstKind = enum { Abstract | Concrete | PartiallyAbstract }
# Definition of a member type constant
predicate TypeConstDefinition :
{
declaration: TypeConstDeclaration,
type : maybe Type,
kind : TypeConstKind,
attributes : [UserAttribute],
typeInfo: maybe TypeInfo
}
# Definition of a Hack function
predicate FunctionDefinition :
{
declaration : FunctionDeclaration,
signature : Signature,
isAsync : bool,
attributes : [UserAttribute],
typeParams : [TypeParameter],
module_ : maybe ModuleMembership,
readonlyRet : maybe ReadonlyKind,
}
# Types of definitions in Hack
type Definition =
{
class_ : ClassDefinition |
classConst : ClassConstDefinition |
enum_ : EnumDefinition |
function_ : FunctionDefinition |
globalConst : GlobalConstDefinition |
interface_ : InterfaceDefinition |
trait : TraitDefinition |
method : MethodDefinition |
property_ : PropertyDefinition |
typeConst : TypeConstDefinition |
typedef_ : TypedefDefinition |
module : ModuleDefinition |
}
# Occurrences are symbols referenced where the class definition could not
# be found. Expect the class name to be a special name like
# HH_FIXME\MISSING_TYPE_IN_HIERARCHY
predicate MethodOccurrence :
{
name: Name,
className: maybe Name,
}
# Where possible we will store references to MethodDefinitions. However
# if a method is dynamically invoked then we only know the method name
# not the container so we will store it as an occurrence
type Occurrence =
{
method : MethodOccurrence |
}
# String literals that occur in expression context, rather than as the
# definition of a top-level or class constant. These must be escaped
# if they are not valid UTF-8.
predicate StringLiteral : string
# Code that is referenced elsewhere
type XRefTarget =
{
declaration : Declaration |
occurrence : Occurrence |
}
# References to target code
type XRef =
{
target : XRefTarget,
ranges : [src.RelByteSpan],
}
# Cross-references to a target within a file. Note that the bytespan offsets
# are relative to each other, not the start of the file, for efficiency.
predicate FileXRefs :
{
file : src.File,
xrefs : set XRef,
}
# Context-free information about an expression argument
type Argument =
{
lit: StringLiteral |
xref: XRefTarget
}
# An argument to a particular call.
type CallArgument =
{
span: src.RelByteSpan,
argument: maybe Argument,
}
# Information for all calls, organized by file and callee_span, which
# should match an entry in FileXRefs.
# callee_xref points to the called method/function.
# dispatch_arg represents the implicit argument
predicate FileCall :
{
file: src.File,
callee_span: src.ByteSpan,
call_args: [CallArgument],
callee_xref: maybe XRefTarget, # deprecated in favor of callee_xrefs
dispatch_arg: maybe CallArgument,
receiver_type: maybe Declaration,
callee_xrefs: set XRefTarget,
}
# All uses of a declaration in a file. Note that the bytespan offsets are
# relative to each other, not the start of the file.
predicate TargetUses :
{
target : hack.XRefTarget,
file : src.File,
uses : [src.RelByteSpan],
}
stored
{ T, File, Uses } where
hack.FileXRefs { file = File, xrefs = XRefs };
hack.XRef { target = T, ranges = Uses } = elements XRefs
# A version of 'TargetUses' with the bytespans converted from relative to
# absolute offset format for convenience.
predicate TargetUsesAbs :
{
target : hack.XRefTarget,
file : src.File,
uses : [src.ByteSpan],
}
{ T, F, prim.relToAbsByteSpans U } where
hack.TargetUses { target = T, file = F, uses = U }
predicate DeclarationTarget :
{
source: Declaration,
target: Declaration,
}
predicate DeclarationSource :
{
target: Declaration,
source: Declaration,
}
stored
{T, S} where DeclarationTarget {S, T}
# Maps lower-case strings to Name, for case-insensitive search
predicate NameLowerCase :
{
nameLowercase : string,
name : Name,
}
stored
{ prim.toLower Str, N } where N = Name Str
# Definitions that contain an attribute
predicate AttributeToDefinition :
{
attribute : UserAttribute,
definition : Definition,
}
stored
{ AS[..], { class_ = { attributes = AS }}} |
{ AS[..], { enum_ = { attributes = AS }}} |
{ AS[..], { function_ = { attributes = AS }}} |
{ AS[..], { interface_ = { attributes = AS }}} |
{ AS[..], { trait = { attributes = AS }}} |
{ AS[..], { method = { attributes = AS }}} |
{ AS[..], { property_ = { attributes = AS }}} |
{ AS[..], { typeConst = { attributes = AS }}} |
{ AS[..], { module = { attributes = AS }}} |
{ AS[..], { typedef_ = { attributes = AS }}}
predicate AttributeHasParameter :
{
name : Name,
parameter : string,
attribute : UserAttribute,
}
stored
{ N, PS[..], UserAttribute { N, PS, _ }}
# Declarations within a namespace
predicate NamespaceMember :
{
namespace_ : hack.NamespaceQName,
decl : hack.Declaration
}
stored
{ NS, Decl } where DeclarationNamespace { Decl, NS }
predicate DeclarationNamespace :
{
decl : hack.Declaration,
namespace_ : hack.NamespaceQName
}
{ Decl, NS } where
Decl : hack.Declaration;
(
Decl.container?.class_?.name.namespace_.just? = NS
) | (
Decl.container?.enum_?.name.namespace_.just? = NS
) | (
Decl.container?.interface_?.name.namespace_.just? = NS
) | (
Decl.container?.trait?.name.namespace_.just? = NS
) | (
Decl.function_?.name.namespace_.just? = NS
) | (
Decl.globalConst?.name.namespace_.just? = NS
) | (
Decl.namespace_?.name.parent.just? = NS
) | (
Decl.typedef_?.name.namespace_.just? = NS
)
# Base name for a declaration (no namespace or container prefix)
predicate DeclarationName : Declaration -> Name
D -> N where
(
D.classConst?.name = N
) | (
D.container?.class_?.name.name = N
) | (
D.container?.enum_?.name.name = N
) | (
D.container?.interface_?.name.name = N
) | (
D.container?.trait?.name.name = N
) | (
D.enumerator?.name = N
) | (
D.function_?.name.name = N
) | (
D.globalConst?.name.name = N
) | (
D.namespace_?.name.name = N
) | (
D.method?.name = N
) | (
D.property_?.name = N
) | (
D.typeConst?.name = N
) | (
D.module?.name = N
) | (
D.typedef_?.name.name = N
)
predicate ContainerDeclarationQName : ContainerDeclaration -> QName
D -> QName where
(
D.class_?.name = QName
) | (
D.enum_?.name = QName
) | (
D.interface_?.name = QName
) | (
D.trait?.name = QName
)
# Container that a given container directly inherits from
# (via extends, implements, use)
predicate ContainerParent :
{
container : hack.ContainerDeclaration,
parent : hack.ContainerDeclaration,
}
stored
{ Child, Parent } where
(
hack.ClassDefinition C;
C.declaration = Child.class_?;
(
C.extends_.just? = Parent.class_?;
) | (
C.uses[..] = Parent.trait?;
) | (
C.implements_[..] = Parent.interface_?;
)
) | (
hack.TraitDefinition T;
T.declaration = Child.trait?;
(
T.uses[..] = Parent.trait?;
) | (
T.implements_[..] = Parent.interface_?;
)
) | (
hack.InterfaceDefinition I;
I.declaration = Child.interface_?;
I.extends_[..] = Parent.interface_?;
) | (
hack.EnumDefinition E;
E.declaration = Child.enum_?;
E.includes[..] = Parent.enum_?;
)
predicate ContainerChild:
{
container : hack.ContainerDeclaration,
child : hack.ContainerDeclaration,
}
stored { Parent, Child }
where hack.ContainerParent { container=Child, parent=Parent }
# parent module of any declaration
predicate ModuleParent:
{
decl: hack.Declaration,
module: hack.ModuleDeclaration
}
{ Decl, M.just?.declaration } where
(
hack.FunctionDefinition D;
Decl.function_? = D.declaration;
M = D.module_;
) | (
hack.TypedefDefinition D;
Decl.typedef_? = D.declaration;
M = D.module_;
) | (
Decl.container? = Container;
( Container.class_? = CDecl;
hack.ClassDefinition D;
D.declaration = CDecl;
D.module_ = M;
) | (
Container.enum_? = CDecl;
hack.EnumDefinition D;
D.declaration = CDecl;
D.module_ = M;
) | (
Container.interface_? = CDecl;
hack.InterfaceDefinition I;
I.declaration = CDecl;
I.module_ = M;
) | (
Container.trait? = CDecl;
hack.TraitDefinition T;
T.declaration = CDecl;
T.module_ = M;
)
)
# derive children decls that are members of a parent module
predicate ModuleChild:
{
module: hack.ModuleDeclaration,
decl : hack.Declaration
} stored { Module, Decl } where hack.ModuleParent { Decl, Module }
# Generally, method "derived" overrides "base", if "derived" would have been inherited
# in case where "base" wasn't defined.
# Note that class methods implementing interface aren't considered as override, but
# trait methods can override interface methods.
predicate MethodOverrides :
{
derived : MethodDeclaration,
base : MethodDeclaration,
annotation : maybe bool,
}
# hack.MethodsOverrides can look up from derived to base; reverse this
# here to look up from base to derived
predicate MethodOverridden :
{
base : MethodDeclaration,
derived : MethodDeclaration,
annotation : maybe bool,
}
stored
{Base, Derived, Annotation}
where
hack.MethodOverrides{
derived = Derived,
base = Base,
annotation = Annotation
}
# Maps an attribute to its defining class, and file where the class is defined
predicate AttributeToDeclaration :
{
attribute : UserAttribute,
declaration : Declaration,
file : src.File
}
stored
{ Attr, Decl, File } where
Attr.name = Decl.container?.class_?.name.name;
DeclarationLocation { declaration = Decl, file = File };
# TODO qname for attributes aren't filled by the indexer yet
# See T111862540. Also this should be a stored predicate
# In the meantime, we just use the name. It'll work as
# attribute names are never qualified in the codebase.
# The correct version is below
# { qname = { just = Q } } = A;
# { container = { class_ = { name = Q } } } = D
# Store arrays of Md5 hashes which characterize indexer inputs.
# This is used for incremental indexing to avoid regenerating
# existing facts.
#
# Hash is specified by the indexer, roughly defined as
# md5(filename||symbols_def). It characterizes the "external"
# symbols within a hack file.
#
# The key string is the name of the batch of files used to
# generate the array.
#
# This is experimental and may change in the future
predicate IndexerInputsHash : string -> [byte]
# Generated from `auto_namespace_map` in .hhconfig
predicate GlobalNamespaceAlias : { from: Name, to: NamespaceQName }
predicate HackToThrift:
{
from: hack.Declaration,
to: fbthrift.Declaration
}
predicate ThriftToHack:
{
to: fbthrift.Declaration,
from: hack.Declaration
}
stored { To, From }
where hack.HackToThrift { From, To }
#
# kind-oriented search. We have one table for string to decl for each kind,
# and one table of lowercase name to normal name for each kind. the keys to the
# decl form are always the local namestr and parent scope.
#
# no more searching through all hack.Name facts.
#
predicate SearchClassConstByName:
{
name: string,
parent: QName, # parent container
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.ClassConstDeclaration { Name NameStr, C };
ContainerDeclarationQName C -> Parent;
{ classConst = D } = Decl
predicate SearchClassConstByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.ClassConstDeclaration { name = Name NameStr }
predicate SearchEnumeratorByName:
{
name: string,
parent: QName, # parent container
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.Enumerator { Name NameStr, { name = Parent } };
{ enumerator = D } = Decl
predicate SearchEnumeratorByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.Enumerator { name = Name NameStr }
predicate SearchMethodByName:
{
name: string,
parent: QName, # parent container
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.MethodDeclaration { Name NameStr, C };
ContainerDeclarationQName C -> Parent;
{ method = D } = Decl
predicate SearchMethodByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.MethodDeclaration { name = Name NameStr }
predicate SearchPropertyByName:
{
name: string,
parent: QName, # parent container
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.PropertyDeclaration { Name NameStr, C };
ContainerDeclarationQName C -> Parent;
{ property_ = D } = Decl
predicate SearchPropertyByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.PropertyDeclaration { name = Name NameStr }
predicate SearchTypeConstByName:
{
name: string,
parent: QName, # parent container
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.TypeConstDeclaration { Name NameStr, C };
ContainerDeclarationQName C -> Parent;
{ typeConst = D } = Decl
predicate SearchTypeConstByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.TypeConstDeclaration { name = Name NameStr }
predicate SearchModuleByName:
{
name: string,
decl: hack.Declaration
} stored { NameStr, Decl } where
D = hack.ModuleDeclaration { name = Name NameStr };
{ module = D } = Decl
predicate SearchModuleByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.ModuleDeclaration { name = Name NameStr }
predicate SearchClassByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.ClassDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ container = { class_ = D } } = Decl
predicate SearchClassByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.ClassDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchInterfaceByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.InterfaceDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ container = { interface_ = D } } = Decl
predicate SearchInterfaceByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.InterfaceDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchTraitByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.TraitDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ container = { trait = D } } = Decl
predicate SearchTraitByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.TraitDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchEnumByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.EnumDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ container = { enum_ = D } } = Decl
predicate SearchEnumByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.EnumDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchFunctionByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.FunctionDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ function_ = D } = Decl
predicate SearchFunctionByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.FunctionDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchGlobalConstByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.GlobalConstDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ globalConst = D } = Decl
predicate SearchGlobalConstByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.GlobalConstDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchTypedefByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.TypedefDeclaration { name = QName };
{ Name NameStr, Parent } = QName;
{ typedef_ = D } = Decl
predicate SearchTypedefByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.TypedefDeclaration { name = QName };
{ name = Name NameStr } = QName
predicate SearchNamespaceByName:
{
name: string,
parent: maybe NamespaceQName,
decl: hack.Declaration
} stored { NameStr, Parent, Decl } where
D = hack.NamespaceDeclaration { name = NSQName };
{ Name NameStr, Parent } = NSQName;
{ namespace_ = D } = Decl
predicate SearchNamespaceByLowerCaseName:
{
name_lowercase: string,
name: string
} stored { prim.toLower NameStr, NameStr } where
hack.NamespaceDeclaration { name = NSQName };
{ name = Name NameStr } = NSQName
} # end hack.angle