# Copyright (c) Meta Platforms, Inc. and affiliates. schema codemarkup.30 { import src import code.24 import codemarkup.buck import codemarkup.csharp import codemarkup.cxx import codemarkup.dataswarm import codemarkup.yaml import codemarkup.erlang import codemarkup.fbthrift import codemarkup.flow import codemarkup.graphql.1 import codemarkup.hack import codemarkup.haskell import codemarkup.java import codemarkup.kotlin import codemarkup.lsif import codemarkup.pp import codemarkup.python import codemarkup.scip import codemarkup.types import codemarkup.anglelang # one direct use of python.Declaration, flow.Declaration import python import flow # # Public API # # Public language-agnostic API # Associates an entity with a symbol kind. # Note: available for partial indices where EntityInfo is incomplete. # this is used directly by Glass in Query.searchByLocalName predicate EntityKind: { entity: code.Entity, kind: codemarkup.types.SymbolKind, } { Entity, Kind } where (codemarkup.python.PythonEntityKind { E, Kind }; { python = E } = Entity) | (codemarkup.cxx.CxxEntityKind { E, Kind }; { cxx = E } = Entity) | (codemarkup.pp.PpEntityKind { E, Kind }; { pp = E } = Entity) | (codemarkup.hack.HackEntityKind { E, Kind }; { hack = E } = Entity) | (codemarkup.erlang.ErlangEntityKind { E, Kind }; { erlang = E } = Entity) | (codemarkup.lsif.EntityInfo { E, { kind = Kind }}; { lsif = E } = Entity) | (codemarkup.scip.EntityInfo { E, { kind = Kind }}; { scip = E } = Entity) | (codemarkup.flow.FlowEntityKind { E, Kind }; { flow = E } = Entity) | (codemarkup.java.JavaEntityKind { E, Kind }; { java = E } = Entity) | (codemarkup.kotlin.KotlinEntityKind { E, Kind }; { kotlin = E } = Entity) | (codemarkup.fbthrift.ThriftEntityKind { E, Kind }; { fbthrift = E } = Entity) | (codemarkup.buck.BuckEntityKind { E, Kind }; { buck = E } = Entity) | (codemarkup.csharp.CSharpEntityKind { E, Kind }; { csharp = E } = Entity) | (codemarkup.graphql.GraphQLEntityKind { E, Kind }; { graphql = E } = Entity) ; # Retrieve information about an entity predicate EntityInfo: { entity: code.Entity, info: codemarkup.types.SymbolInfo, } { Entity, Info } where ( { kind = Kind, isAbstract = false } = Info; ((codemarkup.python.PythonEntityKind { E, Kind }; { python = E } = Entity) | (codemarkup.pp.PpEntityKind { E, Kind }; { pp = E } = Entity) | (codemarkup.erlang.ErlangEntityKind { E, Kind }; { erlang = E } = Entity) | (codemarkup.flow.FlowEntityKind { E, Kind }; { flow = E } = Entity) | (codemarkup.java.JavaEntityKind { E, Kind }; { java = E } = Entity) | (codemarkup.kotlin.KotlinEntityKind { E, Kind }; { kotlin = E } = Entity) | (codemarkup.buck.BuckEntityKind { E, Kind }; { buck = E } = Entity) | (codemarkup.csharp.CSharpEntityKind { E, Kind }; { csharp = E } = Entity) | (codemarkup.graphql.GraphQLEntityKind { E, Kind }; { graphql = E } = Entity); ) ) | (codemarkup.cxx.CxxEntityInfo { E, Info }; { cxx = E } = Entity) | (codemarkup.hack.HackEntityInfo { E, Info }; { hack = E } = Entity) | (codemarkup.lsif.EntityInfo { E, Info }; { lsif = E } = Entity) | (codemarkup.scip.EntityInfo { E, Info }; { scip = E } = Entity); # Source code digests produced by unspecified hash function predicate FileEntityDigest: { file: src.File , entity: code.Entity, } -> string # All entities defined in a src.File and their locations predicate FileEntityLocations: { file: src.File, location: codemarkup.types.Location, entity: code.Entity, } { File, Location, Entity } where codemarkup.types.Location { file = File } = Location; ResolveLocation { Location, Entity }; # All entities defined in a src.File, and their kinds predicate FileEntityKinds: { file: src.File, entity: code.Entity, kind: codemarkup.types.SymbolKind, } { File, Entity, Kind } where FileEntityLocations { File, _, Entity }; EntityKind { Entity, Kind }; predicate FileEntityInfos: { file: src.File, entity: code.Entity, info: codemarkup.types.SymbolInfo, } { File, Entity, Info } where FileEntityLocations { File, _, Entity }; EntityInfo { Entity, Info }; # Map a location to the Entity declared there predicate ResolveLocation: { location: codemarkup.types.Location, entity: code.Entity, } { Location, Entity } where (codemarkup.hack.HackResolveLocation { Location, E }; { hack = E } = Entity) | (codemarkup.python.PythonResolveLocation { Location, E }; { python = E } = Entity) | (codemarkup.flow.FlowResolveLocation { Location, E }; { flow = E } = Entity) | (codemarkup.cxx.CxxResolveLocation { Location, E }; { cxx = E } = Entity) | (codemarkup.pp.PpResolveLocation { Location, E }; { pp = E } = Entity) | (codemarkup.haskell.HaskellResolveLocation { Location, E }; { hs = E } = Entity) | (codemarkup.buck.BuckResolveLocation { Location, E }; { buck = E } = Entity) | (codemarkup.fbthrift.ThriftResolveLocation { Location, E }; { fbthrift = E } = Entity) | (codemarkup.erlang.ErlangResolveLocation { Location, E }; { erlang = E } = Entity) | (codemarkup.lsif.LsifResolveLocation { Location, E }; { lsif = E } = Entity) | (codemarkup.scip.ScipResolveLocation { Location, E }; { scip = E } = Entity) | (codemarkup.java.JavaResolveLocation { Location, E }; { java = E } = Entity) | (codemarkup.kotlin.KotlinResolveLocation { Location, E }; { kotlin = E } = Entity) | (codemarkup.csharp.CSharpResolveLocation { Location, E }; { csharp = E } = Entity) | (codemarkup.graphql.GraphQLResolveLocation { Location, E }; { graphql = E } = Entity) | (codemarkup.anglelang.AngleResolveLocation { Location, E }; { angle = E } = Entity); predicate EntityLocation: { entity: code.Entity, location: codemarkup.types.Location, } { Entity, Location } where (codemarkup.hack.HackEntityLocation { E, Location }; { hack = E } = Entity) | (codemarkup.python.PythonEntityLocation { E, Location }; { python = E } = Entity) | (codemarkup.flow.FlowEntityLocation { E, Location }; { flow = E } = Entity) | (codemarkup.cxx.CxxEntityLocation { E, Location }; { cxx = E } = Entity) | (codemarkup.pp.PPEntityLocation { E, Location }; { pp = E } = Entity) | (codemarkup.haskell.HaskellEntityLocation { E, Location }; { hs = E } = Entity) | (codemarkup.buck.BuckEntityLocation { E, Location }; { buck = E } = Entity) | (codemarkup.fbthrift.ThriftEntityLocation { E, Location }; { fbthrift = E } = Entity) | (codemarkup.erlang.ErlangEntityLocation { E, Location }; { erlang = E } = Entity) | (codemarkup.lsif.LsifEntityLocation { E, Location }; { lsif = E } = Entity) | (codemarkup.scip.ScipEntityLocation { E, Location }; { scip = E } = Entity) | (codemarkup.java.JavaEntityLocation { E, Location }; { java = E } = Entity) | (codemarkup.kotlin.KotlinEntityLocation { E, Location }; { kotlin = E } = Entity) | (codemarkup.csharp.CSharpEntityLocation { E, Location }; { csharp = E } = Entity) | (codemarkup.graphql.GraphQLEntityLocation { E, Location }; { graphql = E } = Entity) | (codemarkup.anglelang.AngleEntityLocation { E, Location }; { angle = E } = Entity); # Maps a generated entity to its source definition predicate GeneratedEntityToIdlEntity: { entity: code.Entity, idlEntity: code.IdlEntity, } { Entity, IdlEntity } where (codemarkup.hack.HackEntityIdl { E, IdlEntity }; { hack = E } = Entity) | (codemarkup.cxx.CxxEntityIdl { E, IdlEntity }; { cxx = E } = Entity) # generic entities are either # - plainEntity: regular entities within the same db as the source file # - xlang entities for which target location may not be known (need to be # resolved client side) type GenericEntity = { plainEntity: { xref: codemarkup.types.XRefLocation, entity : code.Entity } | xlangEntity: { source : codemarkup.types.RangeSpan, entity : code.IdlEntity } | xlangSymbol: { source : codemarkup.types.RangeSpan, symbol : code.SymbolId } } # Finding xrefs to generic entities. Same thing as # FileEntityXRefLocations, but allows references to cross-language entities # for which we can't compute # the target span directly (see code.IdlEntity) predicate FileXRefsGenericEntities: { file: src.File, genEntity: GenericEntity } { File, GenEntity } where (codemarkup.hack.HackFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { hack = E } } } = GenEntity ) | (codemarkup.hack.HackFileEntityXRefLocations { File, { source = Source }, E }; codemarkup.hack.HackEntityIdl { E, IdlEntity }; { xlangEntity = { source = Source, entity = IdlEntity } } = GenEntity ) | (codemarkup.flow.FlowFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { flow = E } } } = GenEntity ) | (codemarkup.python.PythonFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { python = E } } } = GenEntity ) | (codemarkup.cxx.CxxFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { cxx = E } } } = GenEntity ) | (codemarkup.pp.PpFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { pp = E } } } = GenEntity ) | (codemarkup.haskell.HaskellFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { hs = E } } } = GenEntity ) | (codemarkup.buck.BuckFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { buck = E } } } = GenEntity) | (codemarkup.fbthrift.ThriftFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { fbthrift = E } } } = GenEntity) | (codemarkup.erlang.ErlangFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { erlang = E } } } = GenEntity) | (codemarkup.lsif.LsifFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { lsif = E } } } = GenEntity) | ( codemarkup.scip.ScipFileEntityXRefLocations { File, XRef, E } ; { plainEntity = { xref = XRef, entity = { scip = E } } } = GenEntity ) | ( codemarkup.scip.FileXLangSymbolRefs { File, Source, Symbol } ; { xlangSymbol = { source = Source, symbol = { scip = Symbol } } } = GenEntity ) | (codemarkup.java.JavalFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { java = E } } } = GenEntity) | (codemarkup.kotlin.KotlinFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { kotlin = E } } } = GenEntity) | (codemarkup.csharp.CSharpFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { csharp = E } } } = GenEntity) | (codemarkup.graphql.GraphQLFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { graphql = E } } } = GenEntity) | (codemarkup.dataswarm.DataswarmFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { dataswarm = E } } } = GenEntity) | (codemarkup.yaml.YamlFileEntityXLangXRefLocations { File, Source, E }; { xlangEntity = { source = Source, entity = E } } = GenEntity) | (codemarkup.anglelang.AngleFileEntityXRefLocations { File, XRef, E }; { plainEntity = { xref = XRef, entity = { angle = E } } } = GenEntity) predicate SymbolToEntity: { symbol: code.SymbolId, entity: code.Entity, } { Symbol, Entity } where { cxx = CxxSymbol } = Symbol ; codemarkup.cxx.SymbolToEntity { CxxSymbol, CxxEntity } ; { cxx = CxxEntity } = Entity; # Finding xrefs. All references in a file and their targets predicate FileEntityXRefLocations: { file: src.File, xref: codemarkup.types.XRefLocation, entity: code.Entity, } { File, XRef, Entity } where (codemarkup.hack.HackFileEntityXRefLocations { File, XRef, E }; { hack = E } = Entity) | (codemarkup.flow.FlowFileEntityXRefLocations { File, XRef, E }; { flow = E } = Entity) | (codemarkup.python.PythonFileEntityXRefLocations { File, XRef, E }; { python = E } = Entity) | (codemarkup.cxx.CxxFileEntityXRefLocations { File, XRef, E }; { cxx = E } = Entity) | (codemarkup.pp.PpFileEntityXRefLocations { File, XRef, E }; { pp = E } = Entity) | (codemarkup.haskell.HaskellFileEntityXRefLocations { File, XRef, E }; { hs = E } = Entity) | (codemarkup.buck.BuckFileEntityXRefLocations { File, XRef, E }; { buck = E } = Entity) | (codemarkup.fbthrift.ThriftFileEntityXRefLocations { File, XRef, E }; { fbthrift = E } = Entity) | (codemarkup.erlang.ErlangFileEntityXRefLocations { File, XRef, E }; { erlang = E } = Entity) | (codemarkup.lsif.LsifFileEntityXRefLocations { File, XRef, E }; { lsif = E } = Entity) | (codemarkup.scip.ScipFileEntityXRefLocations { File, XRef, E }; { scip = E } = Entity) | (codemarkup.java.JavalFileEntityXRefLocations { File, XRef, E }; { java = E } = Entity) | (codemarkup.kotlin.KotlinFileEntityXRefLocations { File, XRef, E }; { kotlin = E } = Entity) | (codemarkup.csharp.CSharpFileEntityXRefLocations { File, XRef, E }; { csharp = E } = Entity) | (codemarkup.graphql.GraphQLFileEntityXRefLocations { File, XRef, E }; { graphql = E } = Entity) | (codemarkup.dataswarm.DataswarmFileEntityXRefLocations { File, XRef, E }; { dataswarm = E } = Entity) | (codemarkup.anglelang.AngleFileEntityXRefLocations { File, XRef, E }; { angle = E } = Entity); # Xrefs without the target location. This can be useful in cases # where we don't have a target location, but we don't need it. This # happens when indexing a subset of Hack files in a repo, for example. predicate FileEntityXRefRangeSpans: { file: src.File, location: codemarkup.types.RangeSpan, entity: code.Entity, } { File, RangeSpan, Entity } where ( codemarkup.hack.HackFileEntityXRefSpans { File, Span, E }; { hack = E } = Entity; { span = Span } = RangeSpan) | ( (codemarkup.flow.FlowFileEntityXRefLocations { File, XRef, E }; { flow = E } = Entity) | (codemarkup.python.PythonFileEntityXRefLocations { File, XRef, E }; { python = E } = Entity) | (codemarkup.cxx.CxxFileEntityXRefLocations { File, XRef, E }; { cxx = E } = Entity) | (codemarkup.haskell.HaskellFileEntityXRefLocations { File, XRef, E }; { hs = E } = Entity) | (codemarkup.buck.BuckFileEntityXRefLocations { File, XRef, E }; { buck = E } = Entity) | (codemarkup.fbthrift.ThriftFileEntityXRefLocations { File, XRef, E }; { fbthrift = E } = Entity) | (codemarkup.erlang.ErlangFileEntityXRefLocations { File, XRef, E }; { erlang = E } = Entity) | (codemarkup.lsif.LsifFileEntityXRefLocations { File, XRef, E }; { lsif = E } = Entity) | (codemarkup.scip.ScipFileEntityXRefLocations { File, XRef, E }; { scip = E } = Entity) | (codemarkup.java.JavalFileEntityXRefLocations { File, XRef, E }; { java = E } = Entity) | (codemarkup.kotlin.KotlinFileEntityXRefLocations { File, XRef, E }; { kotlin = E } = Entity) | (codemarkup.csharp.CSharpFileEntityXRefLocations { File, XRef, E }; { csharp = E } = Entity); { source = RangeSpan} = XRef ) # Finding xrefs. All references in a file, and their kinds predicate FileEntityXRefKinds: { file: src.File, entity: code.Entity, kind: codemarkup.types.SymbolKind, } { File, Entity, Kind } where FileEntityXRefLocations { File, _, Entity }; EntityKind { Entity, Kind }; predicate FileEntityXRefInfos: { file: src.File, entity: code.Entity, info: codemarkup.types.SymbolInfo, } { File, Entity, Info } where FileEntityXRefLocations { File, _, Entity }; EntityInfo { Entity, Info }; # Find references to a language entity # (deprecated in favor of more general codemarkup.EntityReferences) predicate EntityUses: { target: code.Entity, file: src.File, span: src.ByteSpan } {Entity, File, Span} where codemarkup.EntityReferences { Entity, File, { span = Span }} # Find references to a language entity (same as EntityUses but with RangeSpans) predicate EntityReferences: { target: code.Entity, file: src.File, range: codemarkup.types.RangeSpan } {Entity, File, RangeSpan} where ( (codemarkup.hack.HackEntityUses { E, File, Span }; { hack = E } = Entity) | (codemarkup.flow.FlowEntityUses { E, File, Span }; { flow = E } = Entity) | (codemarkup.python.PythonEntityUses { E, File, Span }; { python = E } = Entity) | (codemarkup.cxx.CxxEntityUses { E, File, Span }; { cxx = E } = Entity) | (codemarkup.haskell.HaskellEntityUses { E, File, Span }; { hs = E } = Entity) | (codemarkup.buck.BuckEntityUses { E, File, Span }; { buck = E } = Entity) | (codemarkup.erlang.ErlangEntityUses { E, File, Span }; { erlang = E } = Entity) | (codemarkup.java.JavaEntityUses { E, File, Span }; { java = E } = Entity) | (codemarkup.kotlin.KotlinEntityUses { E, File, Span }; { kotlin = E } = Entity) | (codemarkup.pp.PpEntityUses { E, File, Span }; { pp = E } = Entity) | (codemarkup.graphql.GraphQLEntityUses { E, File, Span }; { graphql = E } = Entity); { span = Span } = RangeSpan; ) | ( codemarkup.lsif.LsifEntityUses { E, File, Range }; { lsif = E } = Entity; { range = Range } = RangeSpan; ) | ( codemarkup.scip.ScipEntityUses { E, File, Range }; { scip = E } = Entity; { range = Range } = RangeSpan; ) | ( codemarkup.fbthrift.FbthriftEntityUses { E, File, Range }; { fbthrift = E } = Entity; { range = Range } = RangeSpan; ) | ( codemarkup.anglelang.AngleEntityUses { E, File, Span }; { span = Span } = RangeSpan; { angle = E } = Entity; ) | ( codemarkup.hack.HackIdlEntityUses { Entity, File, Span }; { span = Span } = RangeSpan; ) | ( codemarkup.cxx.CxxIdlEntityUses { Entity, File, Span }; { span = Span } = RangeSpan; ); # Information for all calls, organized by file and callee_span predicate FileCall : { file: src.File, span: src.ByteSpan, arguments: [code.CallArgument], callee_xref: maybe code.Entity, dispatch_arg: maybe code.CallArgument, receiver_type: maybe code.Entity, } {File, Span, CodeArgs, Callee, DispatchArg, StaticType} where ( (codemarkup.python.PythonFileCall{File, Span, CodeArgs}; nothing = Callee; nothing = DispatchArg; nothing = StaticType) | codemarkup.hack.HackFileCall{File, Span, CodeArgs, Callee, DispatchArg, StaticType} ) # Look up entities that reference the given target. # This can be used, for example, to find calling functions # (by narrowing the results using `FileEntityKinds`). predicate ReferencingEntity : { target: code.Entity, referrer: code.Entity, reference_file: src.File, reference_range: codemarkup.types.RangeSpan, referrer_location: codemarkup.types.Location, } { Target, Referrer, File, Span, RLocation } where EntityReferences { Target, File, Span }; FileEntityLocations { File, RLocation, Referrer }; { location = RSpan } = RLocation; codemarkup.types.RangeSpanContains { RSpan, Span } # Lookup entities referring to the given target # Less general version of ReferencingEntity that omits the reference range predicate EntitySource: { target: code.Entity, source: code.Entity, } { Target, Referrer} where ( {cxx = CxxTarget} = Target ; codemarkup.cxx.CxxEntitySource { CxxTarget, CxxReferrer}; {cxx = CxxReferrer} = Referrer ) | ( {hack = HackTarget} = Target ; codemarkup.hack.HackEntitySource { HackTarget, HackReferrer}; {hack = HackReferrer} = Referrer ) # # Annotations. decorates, attributes or other symbols/strings associated with # symbols. e.g. @nullsafe or <<__Memoize>> # predicate EntityToAnnotations : { entity: code.Entity, annotations : code.Annotations, } { Entity, Annotations } where ( { cxx = Ent } = Entity; codemarkup.cxx.CxxAnnotation { Ent, Anns }; { cxx = Anns } = Annotations ) | ( { hack = Ent } = Entity; codemarkup.hack.HackAnnotation { Ent, Anns }; { hack = Anns } = Annotations ) | ( { python = Ent } = Entity; codemarkup.python.PythonAnnotation { Ent, Anns }; { python = Anns } = Annotations ) | ( { java = Ent } = Entity; codemarkup.java.JavaAnnotation { Ent, Anns }; { java = Anns } = Annotations ); # # Visibility and other keywords # predicate EntityVisibility : code.Entity -> codemarkup.types.Visibility Entity -> Visibility where ( { cxx = E } = Entity; codemarkup.cxx.CxxVisibility { E, Visibility } ) | ( { hack = E } = Entity; codemarkup.hack.HackVisibility { E, Visibility } ) | ( { python = E } = Entity; codemarkup.python.PythonVisibility { E, Visibility } ) | ( { java = E } = Entity; codemarkup.java.JavaVisibility { E, Visibility } ) # Language keywords like `static` or `final`, or `mutable` .. predicate EntityModifiers: { entity: code.Entity, modifiers: codemarkup.types.Modifiers } { Entity, Modifiers } where ( { hack = E } = Entity; codemarkup.hack.HackModifiers { E, Modifiers } ) | ( { cxx = E } = Entity; codemarkup.cxx.CxxModifiers { E, Modifiers } ) | ( { python = E } = Entity; codemarkup.python.PythonModifiers { E, Modifiers } ) | ( { java = E } = Entity; codemarkup.java.JavaModifiers { E, Modifiers } ); # Entities that represent the canonical definition of the thing. Does # not hold for declarations in C++, imports in Python, or imports in JS predicate EntityIsDefinition: code.Entity ({ cxx = D } where { defn = _ } = D) | ({ python = { decl = D }} where D : python.Declaration; !({ imp = _ } = D)) | ({ hack = _ }) | ({ pp = _ }) | ({ erlang = _ }) | ({ lsif = _ }) | ({ scip = _ }) | ({ flow = { decl = { localDecl = D }}} where D : flow.Declaration; !(flow.ImportDeclaration { declaration = D })) | ({ buck = _ }) | ({ java = _ }) | ({ fbthrift = _ }) | ({ kotlin = _ }) # If an entity is a declaration, try to find its definition, which # might be in a different file. There can be multiple definitions. # If `entity` has no separate definition, `definition == entity`. predicate FindEntityDefinition: { entity: code.Entity, definition: code.Entity } { Decl, Defn } where if ( { cxx = E } = Decl; ) then ( codemarkup.cxx.CxxFindDefinitionOfEntity { E, CxxDefn }; { cxx = CxxDefn } = Defn ) else ( Decl = Defn ) # # Relations todo to code.search.* # # A child `extends` a parent predicate ExtendsParentEntity : { child: code.Entity, parent: code.Entity } { Child, Parent } where ( { hack = C } = Child; codemarkup.hack.HackExtendsParentEntity { C, P }; { hack = P } = Parent ) | ( { cxx = C } = Child; codemarkup.cxx.CxxExtendsParentEntity { C, P }; { cxx = P } = Parent ) | ( { python = C } = Child; codemarkup.python.PythonExtendsParentEntity { C, P }; { python = P } = Parent ) | ( { fbthrift = C } = Child; codemarkup.fbthrift.ThriftExtendsParentEntity { C, P }; { fbthrift = P } = Parent ) | ( { java = C } = Child; codemarkup.java.JavaExtendsParentEntity { C, P }; { java = P } = Parent ) | ( { kotlin = C } = Child; codemarkup.kotlin.KotlinExtendsParentEntity { C, P }; { kotlin = P } = Parent ) # This implements the ExtendsParentEntity relation, but for "interesting" # parents only. I.e. with this you are allowed to implement server-side # filtering of containers we wouldn't include as they are boring. E.g. because # they are tests, code gen'd or verbose. predicate ExtendsParentEntityConcise : { child: code.Entity, parent: code.Entity } { Child, Parent } where if ( { hack = C } = Child ) then ( codemarkup.hack.HackExtendsParentEntityConcise { C, P }; { hack = P } = Parent; ) else ( # generic implementation ExtendsParentEntity { Child, Parent }; ) # A parent `is extended by` a child predicate ExtendsChildEntity : { parent: code.Entity, child: code.Entity } { Parent, Child } where ( { hack = P } = Parent; codemarkup.hack.HackExtendsChildEntity { P, C }; { hack = C } = Child ) | ( { cxx = P } = Parent; codemarkup.cxx.CxxExtendsChildEntity { P, C }; { cxx = C } = Child ) | ( { python = P } = Parent; codemarkup.python.PythonExtendsChildEntity { P, C }; { python = C } = Child ) | ( { fbthrift = P } = Parent; codemarkup.fbthrift.ThriftExtendsChildEntity { P, C }; { fbthrift = C } = Child ) | ( { java = P } = Parent; codemarkup.java.JavaExtendsChildEntity { P, C }; { java = C } = Child ) # A child `is contained by` a parent predicate ContainsParentEntity : { child: code.Entity, parent: code.Entity, } { Child, Parent } where ( { hack = C } = Child; codemarkup.hack.HackContainsParentEntity { C, P }; { hack = P } = Parent ) | ( { cxx = C } = Child; codemarkup.cxx.CxxContainsParentEntity { C, P }; { cxx = P } = Parent ) | ( { python = C } = Child; codemarkup.python.PythonContainsParentEntity { C, P }; { python = P } = Parent ) | ( { flow = C } = Child; codemarkup.flow.FlowContainsParentEntity { C, P }; { flow = P } = Parent ) | ( { fbthrift = C } = Child; codemarkup.fbthrift.ThriftContainsParentEntity { C, P }; { fbthrift = P } = Parent ) | ( { java = C } = Child; codemarkup.java.JavaContainsParentEntity { C, P }; { java = P } = Parent ) | ( { kotlin = C } = Child; codemarkup.kotlin.KotlinContainsParentEntity { C, P }; { kotlin = P } = Parent ) | ( { hs = C } = Child; codemarkup.haskell.HaskellContainsParentEntity { C, P }; { hs = P } = Parent ) # A parent `contains` a child predicate ContainsChildEntity : { parent: code.Entity, child: code.Entity } { Parent, Child } where ( { hack = P } = Parent; codemarkup.hack.HackContainsChildEntity { P, C }; { hack = C } = Child ) | ( {cxx = P} = Parent; codemarkup.cxx.CxxContainsChildEntity { P, C }; { cxx = C } = Child ) | ( { python = P } = Parent; codemarkup.python.PythonContainsChildEntity { P, C }; { python = C } = Child ) | ( { flow = P } = Parent; codemarkup.flow.FlowContainsChildEntity { P, C }; { flow = C } = Child ) | ( { fbthrift = P } = Parent; codemarkup.fbthrift.ThriftContainsChildEntity { P, C }; { fbthrift = C } = Child ) | ( { java = P } = Parent; codemarkup.java.JavaContainsChildEntity { P, C }; { java = C } = Child ) | ( { kotlin = P } = Parent; codemarkup.kotlin.KotlinContainsChildEntity { P, C }; { kotlin = C } = Child ) | ( { hs = P } = Parent; codemarkup.haskell.HaskellContainsChildEntity { P, C }; { hs = C } = Child ) # # Generic relational search API, so you can call different searches # in a uniform way # # useful newtypes for a bit of client-side type safety in relational queries type ParentEntity = { parent: code.Entity, location: codemarkup.types.Location } type ChildEntity = { child: code.Entity, location: codemarkup.types.Location } # hide different relation types and directions under a search flag type RelationType = enum { ExtendsParentOfChild | ExtendsChildOfParent | ContainsChildOfParent | ContainsParentOfChild | # Trait And Interface Requirements, Hack specific # https://docs.hhvm.com/hack/traits-and-interfaces/trait-and-interface-requirements RequireExtendsParentOfChild | RequireImplementsParentOfChild | RequireClassParentOfChild | } # we can prune some of the relationships by hiding "uninteresting" results type SearchStyle = enum { ShowAll | HideUninteresting | # perhaps us to drop language specific uninteresting cases } # given a container entity, get all its (located) inherited member, including origin location, predicate SearchInheritedEntities: { base: code.Entity, parent: ParentEntity, child: ChildEntity, style: SearchStyle, # all results or hide uninteresting } { CE, { parent = PE, location = PELoc } , { child = ME, location = MELoc }, Style } where codemarkup.hack.HackInheritedEntities { container = HCD, member = HD }; { hack = { decl = { container = HCD } } } = CE : code.Entity; { hack = { decl = HD } } = ME : code.Entity; codemarkup.hack.HackContainsParentEntity { child = { decl = HD }, parent = Parent }; { hack = Parent } = PE : code.Entity; codemarkup.EntityLocation {PE, PELoc}; codemarkup.EntityLocation {ME, MELoc}; ( ( HideUninteresting = Style; !(codemarkup.hack.EntityHasHideFromDocsAttr Parent) ) | ( ShowAll = Style ) ) # find parent/child semantic relationships predicate SearchRelatedEntities: { query: RelationType, # extends or contains, parent or child direction parent: ParentEntity, child: ChildEntity, style: SearchStyle, # all results or hide uninteresting } { Query, {parent = P, location = PLoc}, {child = C, location = CLoc}, Style } where ( ShowAll = Style; ( ExtendsParentOfChild = Query; ExtendsParentEntity { C, P }) | # child key ( ExtendsChildOfParent = Query; ExtendsChildEntity { P, C } ) | # parent key ( ContainsParentOfChild = Query; ContainsParentEntity { C, P }) | # child key ( ContainsChildOfParent = Query; ContainsChildEntity { P, C }) | # parent key ( RequireExtendsParentOfChild = Query; { hack = HC } = C; { hack = HP } = P; codemarkup.hack.HackRequiredConstraint { HC, extends_, HP }) | ( RequireImplementsParentOfChild = Query; { hack = HC } = C; { hack = HP } = P; codemarkup.hack.HackRequiredConstraint { HC, implements_, HP }) | ( RequireClassParentOfChild = Query; { hack = HC } = C; { hack = HP } = P; codemarkup.hack.HackRequiredConstraint { HC, class_, HP }); ) | ( HideUninteresting = Style; # only one hide unteresting relation style atm ExtendsParentOfChild = Query; ExtendsParentEntityConcise { C, P } ); codemarkup.EntityLocation {C, CLoc}; codemarkup.EntityLocation {P, PLoc}; # # Expanded version of codemarkup.EntityDocumentation that knows about # docs stored in the index itself. Indexers are still required to support # the span/file format. Optionally, they may provide pre-rendered comments in # markdown format # predicate EntityComments: { entity : code.Entity, file : src.File, span : src.ByteSpan, text : maybe string, } { Entity, File, Span, Text } where ( { cxx = Decl } = Entity; codemarkup.cxx.CxxEntityDocumentation { Decl, File, Span }; nothing = Text ) | ( { hack = Decl } = Entity; codemarkup.hack.HackEntityDocumentation { Decl, File, Span }; nothing = Text ) | ( { flow = Decl } = Entity; codemarkup.flow.FlowEntityDocumentation { Decl, File, Span }; nothing = Text ) | ( { python = Decl } = Entity; codemarkup.python.PythonEntityComments { Decl, File, Span, Text } ) | ( { java = Decl } = Entity; codemarkup.java.JavaEntityDocumentation { Decl, File, Span }; nothing = Text ) | ( { erlang = Decl } = Entity; codemarkup.erlang.ErlangEntityDocumentation { Decl, File, Span, Text} ) | ( { fbthrift = Decl } = Entity; codemarkup.fbthrift.FbthriftEntityDocumentation { Decl, File, Span }; nothing = Text ) # Find module name as string given entity. # No result if the entity is a non-module. predicate EntityModuleName: { entity: code.Entity, name: string, } { Entity, Name } where ( { hack = Decl } = Entity; codemarkup.hack.HackEntityModuleName { Decl, Name } ) | ( { flow = Decl } = Entity; codemarkup.flow.FlowEntityModuleName { Decl, Name } ) | ( { python = Decl } = Entity; codemarkup.python.PythonEntityModuleName { Decl, Name } ) | ( { lsif = Decl } = Entity; codemarkup.lsif.LsifEntityModuleName { Decl, Name } ) # Identifies indexed files predicate IndexedFile: src.File File where codemarkup.cxx.CxxDataAvailable File | codemarkup.EntityDataAvailable File | # All Yaml files are indexable, even though they don't # contain entities codemarkup.yaml.YamlDataAvailable File # Identifies files with indexed entities. # You should not use this, instead use codemarkup.IndexedFile predicate EntityDataAvailable: src.File File where src.File _ = File; # bind File as demanded by the schema consistency check # double negation is used to check for existence # (even if the Angle compiler could notice and optimize) !(!(codemarkup.FileEntityLocations { file = File } | codemarkup.FileEntityXRefRangeSpans {file = File } )) # end }